Skip to content

Commit 20af4c1

Browse files
Add some missing // SAFETY comments
Signed-off-by: Léo Lanteri Thauvin <[email protected]>
1 parent b9ed1ad commit 20af4c1

File tree

5 files changed

+32
-9
lines changed

5 files changed

+32
-9
lines changed

rust/kernel/file_operations.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ unsafe extern "C" fn open_callback<A: FileOpenAdapter, T: FileOpener<A::Arg>>(
100100
// be a valid non-null pointer.
101101
let ptr = T::open(unsafe { &*arg })?.into_pointer();
102102
// SAFETY: `ptr` was previously returned by `T::open`. The returned
103-
// value should be a boxed value and should live the length of the
104-
// given file.
103+
// value should be a boxed value and should outlive the given file.
105104
unsafe { (*file).private_data = ptr as *mut c_types::c_void };
106105
Ok(0)
107106
}
@@ -114,7 +113,7 @@ unsafe extern "C" fn read_callback<T: FileOperations>(
114113
offset: *mut bindings::loff_t,
115114
) -> c_types::c_ssize_t {
116115
from_kernel_result! {
117-
let mut data = unsafe { UserSlicePtr::new(buf as *mut c_types::c_void, len).writer() };
116+
let mut data = unsafe { UserSlicePtr::new(buf as *mut c_types::c_void, len) }.writer();
118117
// SAFETY: `private_data` was initialised by `open_callback` with a value returned by
119118
// `T::Wrapper::into_pointer`. `T::Wrapper::from_pointer` is only called by the `release`
120119
// callback, which the C API guarantees that will be called only when all references to

rust/kernel/miscdev.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl<T: Sync> Registration<T> {
6060
name: &'static CStr,
6161
minor: Option<i32>,
6262
) -> Result {
63-
// SAFETY: We must ensure that we never move out of `this`.
63+
// SAFETY: we don't move out of `this`.
6464
let this = unsafe { self.get_unchecked_mut() };
6565
if this.registered {
6666
// Already registered.
@@ -72,6 +72,7 @@ impl<T: Sync> Registration<T> {
7272
this.mdev.name = name.as_char_ptr();
7373
this.mdev.minor = minor.unwrap_or(bindings::MISC_DYNAMIC_MINOR as i32);
7474

75+
// SAFETY: FFI call.
7576
let ret = unsafe { bindings::misc_register(&mut this.mdev) };
7677
if ret < 0 {
7778
return Err(Error::from_kernel_errno(ret));
@@ -87,6 +88,10 @@ impl<T: Sync> FileOpenAdapter for Registration<T> {
8788
unsafe fn convert(_inode: *mut bindings::inode, file: *mut bindings::file) -> *const Self::Arg {
8889
// SAFETY: the caller must guarantee that `file` is valid.
8990
let reg = crate::container_of!(unsafe { (*file).private_data }, Self, mdev);
91+
// SAFETY: before calling the `open` callback, `file.private_data` is initialized
92+
// by the `miscdev` subsystem to point to the miscellaneous device, which is guaranteed
93+
// by the caller to have been registered through `Registration`, so `file.private_data`
94+
// is the `mdev` field of a `Registration` object.
9095
unsafe { &(*reg).context }
9196
}
9297
}

rust/kernel/pages.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl<const ORDER: u32> Pages<ORDER> {
8282
///
8383
/// # Safety
8484
///
85-
/// Callers must ensure that the destination buffer is valid for the given length.
85+
/// Callers must ensure that the destination buffer is valid for writes for the given length.
8686
/// Additionally, if the raw buffer is intended to be recast, they must ensure that the data
8787
/// can be safely cast; [`crate::io_buffer::ReadableFromBytes`] has more details about it.
8888
pub unsafe fn read(&self, dest: *mut u8, offset: usize, len: usize) -> Result {
@@ -93,15 +93,23 @@ impl<const ORDER: u32> Pages<ORDER> {
9393
}
9494

9595
let mapping = self.kmap(0).ok_or(Error::EINVAL)?;
96-
unsafe { ptr::copy((mapping.ptr as *mut u8).add(offset), dest, len) };
96+
// SAFETY: we just checked that `offset + len <= PAGE_SIZE`, so `mapping.ptr` and
97+
// `mapping.ptr + offset` are in the same allocated object, the page we're
98+
// reading from, with no overflow. Also, `offset <= PAGE_LEN < isize::MAX`
99+
// so `offset` can't overflow an `isize`.
100+
let src = unsafe { (mapping.ptr as *mut u8).add(offset) };
101+
// SAFETY: `src` is valid for reads from the type invariants, and `dest` is
102+
// guaranteed by the caller to be valid for writes. Because we're copying `u8`s
103+
// which have an alignment of 1, `src` and `dest` are always properly aligned.
104+
unsafe { ptr::copy(src, dest, len) };
97105
Ok(())
98106
}
99107

100108
/// Maps the pages and writes into them from the given bufer.
101109
///
102110
/// # Safety
103111
///
104-
/// Callers must ensure that the buffer is valid for the given length. Additionally, if the
112+
/// Callers must ensure that the source buffer is valid for reads for the given length. Additionally, if the
105113
/// page is (or will be) mapped by userspace, they must ensure that no kernel data is leaked
106114
/// through padding if it was cast from another type; [`crate::io_buffer::WritableToBytes`] has
107115
/// more details about it.
@@ -113,7 +121,15 @@ impl<const ORDER: u32> Pages<ORDER> {
113121
}
114122

115123
let mapping = self.kmap(0).ok_or(Error::EINVAL)?;
116-
unsafe { ptr::copy(src, (mapping.ptr as *mut u8).add(offset), len) };
124+
// SAFETY: we just checked that `offset + len <= PAGE_SIZE`, so `mapping.ptr` and
125+
// `mapping.ptr + offset` are in the same allocated object, the page we're
126+
// reading from, with no overflow. Also, `offset <= PAGE_LEN < isize::MAX`
127+
// so `offset` can't overflow an `isize`.
128+
let dest = unsafe { (mapping.ptr as *mut u8).add(offset) };
129+
// SAFETY: `src` is guaranteed by the caller to be valid for reads, and `dest` is
130+
//valid for writes from the type invariants. Because we're copying `u8`s
131+
// which have an alignment of 1, `src` and `dest` are always properly aligned.
132+
unsafe { ptr::copy(src, dest, len) };
117133
Ok(())
118134
}
119135

rust/kernel/print.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ unsafe fn rust_fmt_argument(buf: *mut c_char, end: *mut c_char, ptr: *const c_vo
3333
// `buf` goes past `end`.
3434
let len_to_copy = cmp::min(buf_new, self.end).saturating_sub(self.buf);
3535

36-
// SAFETY: In any case, `buf` is non-null and properly aligned.
36+
// SAFETY: The caller guarantees `buf` is non-null and properly aligned.
3737
// If `len_to_copy` is non-zero, then we know `buf` has not past
3838
// `end` yet and so is valid.
3939
unsafe {
@@ -53,6 +53,7 @@ unsafe fn rust_fmt_argument(buf: *mut c_char, end: *mut c_char, ptr: *const c_vo
5353
buf: buf as _,
5454
end: end as _,
5555
};
56+
// SAFETY: the caller must guarantee that `ptr` is valid.
5657
let _ = w.write_fmt(unsafe { *(ptr as *const fmt::Arguments<'_>) });
5758
w.buf as _
5859
}
@@ -132,6 +133,7 @@ pub unsafe fn call_printk(
132133
args: fmt::Arguments<'_>,
133134
) {
134135
// `_printk` does not seem to fail in any path.
136+
// SAFETY: FFI call.
135137
unsafe {
136138
bindings::_printk(
137139
format_string.as_ptr() as _,

rust/kernel/sync/condvar.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ impl CondVar {
127127

128128
impl NeedsLockClass for CondVar {
129129
unsafe fn init(self: Pin<&mut Self>, name: &'static CStr, key: *mut bindings::lock_class_key) {
130+
// SAFETY: FFI call.
130131
unsafe { bindings::__init_waitqueue_head(self.wait_list.get(), name.as_char_ptr(), key) };
131132
}
132133
}

0 commit comments

Comments
 (0)