Skip to content

Commit

Permalink
Merge pull request torvalds#222 from wedsonaf/clear
Browse files Browse the repository at this point in the history
Add `UserSlicePtrWriter::clear`.
  • Loading branch information
ojeda authored Apr 27, 2021
2 parents b37d85b + 126c162 commit e3dea04
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
5 changes: 5 additions & 0 deletions rust/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ unsigned long rust_helper_copy_to_user(void __user *to, const void *from, unsign
return copy_to_user(to, from, n);
}

unsigned long rust_helper_clear_user(void __user *to, unsigned long n)
{
return clear_user(to, n);
}

void rust_helper_spin_lock_init(spinlock_t *lock, const char *name,
struct lock_class_key *key)
{
Expand Down
30 changes: 30 additions & 0 deletions rust/kernel/user_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ extern "C" {
from: *const c_types::c_void,
n: c_types::c_ulong,
) -> c_types::c_ulong;

fn rust_helper_clear_user(to: *mut c_types::c_void, n: c_types::c_ulong) -> c_types::c_ulong;
}

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

/// Writes zeroes to the user slice.
///
/// Differently from the other write functions, `clear` will zero as much as it can and update
/// the writer internal state to reflect this. It will, however, return an error if it cannot
/// clear `len` bytes.
///
/// For example, if a caller requests that 100 bytes be cleared but a segfault happens after
/// 20 bytes, then EFAULT is returned and the writer is advanced by 20 bytes.
pub fn clear(&mut self, mut len: usize) -> KernelResult {
let mut ret = Ok(());
if len > self.1 {
ret = Err(Error::EFAULT);
len = self.1;
}

// SAFETY: The buffer will be validated by `clear_user`. We ensure that `len` is within
// bounds in the check above.
let left = unsafe { rust_helper_clear_user(self.0, len as _) } as usize;
if left != 0 {
ret = Err(Error::EFAULT);
len -= left;
}

self.0 = self.0.wrapping_add(len);
self.1 -= len;
ret
}

/// Writes a byte slice to the user slice.
///
/// Returns `EFAULT` if the byte slice is bigger than the remaining size
Expand Down

0 comments on commit e3dea04

Please sign in to comment.