Skip to content

Commit 2508227

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

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 driver to point to the miscellaneous device, which is guaranteed by
93+
// 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
@@ -96,7 +96,7 @@ impl<const ORDER: u32> Pages<ORDER> {
9696
///
9797
/// # Safety
9898
///
99-
/// Callers must ensure that the destination buffer is valid for the given length.
99+
/// Callers must ensure that the destination buffer is valid for writes for the given length.
100100
/// Additionally, if the raw buffer is intended to be recast, they must ensure that the data
101101
/// can be safely cast; [`crate::io_buffer::ReadableFromBytes`] has more details about it.
102102
pub unsafe fn read(&self, dest: *mut u8, offset: usize, len: usize) -> Result {
@@ -107,15 +107,23 @@ impl<const ORDER: u32> Pages<ORDER> {
107107
}
108108

109109
let mapping = self.kmap(0).ok_or(Error::EINVAL)?;
110-
unsafe { ptr::copy((mapping.ptr as *mut u8).add(offset), dest, len) };
110+
// SAFETY: we just checked that `offset + len <= PAGE_SIZE`, so `mapping.ptr` and
111+
// `mapping.ptr + offset` are in the same allocated object, the page we're
112+
// reading from, with no overflow. Also, `offset <= PAGE_LEN < isize::MAX`
113+
// so `offset` can't overflow an `isize`.
114+
let src = unsafe { (mapping.ptr as *mut u8).add(offset) };
115+
// SAFETY: `src` is valid for reads from the type invariants, and `dest` is
116+
// guaranteed by the caller to be valid for writes. Because we're copying `u8`s
117+
// which have an alignment of 1, `src` and `dest` are always properly aligned.
118+
unsafe { ptr::copy(src, dest, len) };
111119
Ok(())
112120
}
113121

114122
/// Maps the pages and writes into them from the given bufer.
115123
///
116124
/// # Safety
117125
///
118-
/// Callers must ensure that the buffer is valid for the given length. Additionally, if the
126+
/// Callers must ensure that the source buffer is valid for reads for the given length. Additionally, if the
119127
/// page is (or will be) mapped by userspace, they must ensure that no kernel data is leaked
120128
/// through padding if it was cast from another type; [`crate::io_buffer::WritableToBytes`] has
121129
/// more details about it.
@@ -127,7 +135,15 @@ impl<const ORDER: u32> Pages<ORDER> {
127135
}
128136

129137
let mapping = self.kmap(0).ok_or(Error::EINVAL)?;
130-
unsafe { ptr::copy(src, (mapping.ptr as *mut u8).add(offset), len) };
138+
// SAFETY: we just checked that `offset + len <= PAGE_SIZE`, so `mapping.ptr` and
139+
// `mapping.ptr + offset` are in the same allocated object, the page we're
140+
// reading from, with no overflow. Also, `offset <= PAGE_LEN < isize::MAX`
141+
// so `offset` can't overflow an `isize`.
142+
let dest = unsafe { (mapping.ptr as *mut u8).add(offset) };
143+
// SAFETY: `src` is guaranteed by the caller to be valid for reads, and `dest` is
144+
//valid for writes from the type invariants. Because we're copying `u8`s
145+
// which have an alignment of 1, `src` and `dest` are always properly aligned.
146+
unsafe { ptr::copy(src, dest, len) };
131147
Ok(())
132148
}
133149

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
@@ -131,6 +131,7 @@ impl CondVar {
131131

132132
impl NeedsLockClass for CondVar {
133133
unsafe fn init(self: Pin<&mut Self>, name: &'static CStr, key: *mut bindings::lock_class_key) {
134+
// SAFETY: FFI call.
134135
unsafe { bindings::__init_waitqueue_head(self.wait_list.get(), name.as_char_ptr(), key) };
135136
}
136137
}

0 commit comments

Comments
 (0)