Add a method to zero the remaining bytes in a UserSliceWriter. If userspace provides a buffer that is larger than necessary, provide a method to zero out the remaining UserSliceWriter buffer. This avoids userspace consuming potentially uninitialized memory and/or mistaking it for data intentionally provided by the kernel.
Since clear_user() is architecturally defined and may be a macro or inline function, add a rust helper to make clear_user() callable from rust. Signed-off-by: Deborah Brouwer <[email protected]> --- rust/helpers/uaccess.c | 6 ++++++ rust/kernel/uaccess.rs | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/rust/helpers/uaccess.c b/rust/helpers/uaccess.c index 6e59cc9c665c..e799d9ac9804 100644 --- a/rust/helpers/uaccess.c +++ b/rust/helpers/uaccess.c @@ -27,3 +27,9 @@ unsigned long rust_helper__copy_to_user(void __user *to, const void *from, unsig return _inline_copy_to_user(to, from, n); } #endif + +__rust_helper unsigned long +rust_helper_clear_user(void __user *to, unsigned long n) +{ + return clear_user(to, n); +} diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs index f1aecda7a90c..6838e7f90abb 100644 --- a/rust/kernel/uaccess.rs +++ b/rust/kernel/uaccess.rs @@ -638,6 +638,29 @@ pub fn write<T: AsBytes>(&mut self, value: &T) -> Result { pub fn write_truncated<T: AsBytes>(&mut self, value: &T) -> Result<usize> { self.write_slice_partial(value.as_bytes(), 0) } + + /// Zeros remaining bytes in the userspace buffer. + /// + /// Fails with [`EFAULT`] if the userspace memory cannot be cleared. + pub fn clear(&mut self) -> Result { + let len = self.length; + + if len == 0 { + return Ok(()); + } + // SAFETY: `clear_user` checks the userspace address and range and handles + // faults when accessing userspace memory + let res = unsafe { bindings::clear_user(self.ptr.as_mut_ptr(), len) }; + + if res != 0 { + return Err(EFAULT); + } + + self.ptr = self.ptr.wrapping_byte_add(len); + self.length = 0; + + Ok(()) + } } /// Reads a nul-terminated string into `dst` and returns the length. -- 2.56.0
