Skip to content

Commit e3dea04

Browse files
authored
Merge pull request torvalds#222 from wedsonaf/clear
Add `UserSlicePtrWriter::clear`.
2 parents b37d85b + 126c162 commit e3dea04

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

rust/helpers.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ unsigned long rust_helper_copy_to_user(void __user *to, const void *from, unsign
2222
return copy_to_user(to, from, n);
2323
}
2424

25+
unsigned long rust_helper_clear_user(void __user *to, unsigned long n)
26+
{
27+
return clear_user(to, n);
28+
}
29+
2530
void rust_helper_spin_lock_init(spinlock_t *lock, const char *name,
2631
struct lock_class_key *key)
2732
{

rust/kernel/user_ptr.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ extern "C" {
2020
from: *const c_types::c_void,
2121
n: c_types::c_ulong,
2222
) -> c_types::c_ulong;
23+
24+
fn rust_helper_clear_user(to: *mut c_types::c_void, n: c_types::c_ulong) -> c_types::c_ulong;
2325
}
2426

2527
/// Specifies that a type is safely readable from byte slices.
@@ -242,6 +244,34 @@ impl UserSlicePtrWriter {
242244
self.len() == 0
243245
}
244246

247+
/// Writes zeroes to the user slice.
248+
///
249+
/// Differently from the other write functions, `clear` will zero as much as it can and update
250+
/// the writer internal state to reflect this. It will, however, return an error if it cannot
251+
/// clear `len` bytes.
252+
///
253+
/// For example, if a caller requests that 100 bytes be cleared but a segfault happens after
254+
/// 20 bytes, then EFAULT is returned and the writer is advanced by 20 bytes.
255+
pub fn clear(&mut self, mut len: usize) -> KernelResult {
256+
let mut ret = Ok(());
257+
if len > self.1 {
258+
ret = Err(Error::EFAULT);
259+
len = self.1;
260+
}
261+
262+
// SAFETY: The buffer will be validated by `clear_user`. We ensure that `len` is within
263+
// bounds in the check above.
264+
let left = unsafe { rust_helper_clear_user(self.0, len as _) } as usize;
265+
if left != 0 {
266+
ret = Err(Error::EFAULT);
267+
len -= left;
268+
}
269+
270+
self.0 = self.0.wrapping_add(len);
271+
self.1 -= len;
272+
ret
273+
}
274+
245275
/// Writes a byte slice to the user slice.
246276
///
247277
/// Returns `EFAULT` if the byte slice is bigger than the remaining size

0 commit comments

Comments
 (0)