Skip to content
This repository was archived by the owner on Mar 7, 2021. It is now read-only.

Commit 2cc3f5f

Browse files
geofftalex
authored andcommitted
Add comments, plus one style cleanup
1 parent 15bdc7d commit 2cc3f5f

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

src/sysctl.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ unsafe extern "C" fn proc_handler<T: SysctlStorage>(
6868
len: *mut usize,
6969
ppos: *mut bindings::loff_t,
7070
) -> c_types::c_int {
71+
// If we're reading from some offset other than the beginning of the file,
72+
// return an empty read to signal EOF.
7173
if *ppos != 0 && write == 0 {
7274
*len = 0;
7375
return 0;

src/user_ptr.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,77 @@ extern "C" {
1414
) -> c_types::c_int;
1515
}
1616

17+
/// A reference to an area in userspace memory, which can be either
18+
/// read-only or read-write.
19+
///
20+
/// All methods on this struct are safe: invalid pointers return
21+
/// `EFAULT`. Concurrent access, _including data races to/from userspace
22+
/// memory_, is permitted, because fundamentally another userspace
23+
/// thread / process could always be modifying memory at the same time
24+
/// (in the same way that userspace Rust's std::io permits data races
25+
/// with the contents of files on disk). In the presence of a race, the
26+
/// exact byte values read/written are unspecified but the operation is
27+
/// well-defined. Kernelspace code should validate its copy of data
28+
/// after completing a read, and not expect that multiple reads of the
29+
/// same address will return the same value.
30+
///
31+
/// Constructing a `UserSlicePtr` only checks that the range is in valid
32+
/// userspace memory, and does not depend on the current process (and
33+
/// can safely be constructed inside a kernel thread with no current
34+
/// userspace process). Reads and writes wrap the kernel APIs
35+
/// `copy_from_user` and `copy_to_user`, and check the memory map of the
36+
/// current process.
1737
pub struct UserSlicePtr(*mut c_types::c_void, usize);
1838

1939
impl UserSlicePtr {
40+
/// Construct a user slice from a raw pointer and a length in bytes.
41+
///
42+
/// Checks that the provided range is within the legal area for
43+
/// userspace memory, using `access_ok` (e.g., on i386, the range
44+
/// must be within the first 3 gigabytes), but does not check that
45+
/// the actual pages are mapped in the current process with
46+
/// appropriate permissions. Those checks are handled in the read
47+
/// and write methods.
2048
pub fn new(ptr: *mut c_types::c_void, length: usize) -> error::KernelResult<UserSlicePtr> {
49+
// No current access_ok implementation actually distinguishes
50+
// between VERIFY_READ and VERIFY_WRITE, so passing VERIFY_WRITE
51+
// is fine in practice and fails safe if a future implementation
52+
// bothers.
2153
if unsafe { access_ok_helper(bindings::VERIFY_WRITE, ptr, length as c_types::c_ulong) } == 0
2254
{
2355
return Err(error::Error::EFAULT);
2456
}
2557
return Ok(UserSlicePtr(ptr, length));
2658
}
2759

60+
/// Read the entirety of the user slice and return it in a `Vec`.
61+
///
62+
/// Returns EFAULT if the address does not currently point to
63+
/// mapped, readable memory.
2864
pub fn read_all(self) -> error::KernelResult<Vec<u8>> {
2965
let mut data = vec![0; self.1];
3066
self.reader().read(&mut data)?;
3167
return Ok(data);
3268
}
3369

70+
/// Construct a `UserSlicePtrReader` that can incrementally read
71+
/// from the user slice.
3472
pub fn reader(self) -> UserSlicePtrReader {
3573
return UserSlicePtrReader(self.0, self.1);
3674
}
3775

76+
/// Write the provided slice into the user slice.
77+
///
78+
/// Returns EFAULT if the address does not currently point to
79+
/// mapped, writable memory (in which case some data from before the
80+
/// fault may be written), or `data` is larger than the user slice
81+
/// (in which case no data is written).
3882
pub fn write_all(self, data: &[u8]) -> error::KernelResult<()> {
3983
return self.writer().write(data);
4084
}
4185

86+
/// Construct a `UserSlicePtrWrite` that can incrementally write
87+
/// into the user slice.
4288
pub fn writer(self) -> UserSlicePtrWriter {
4389
return UserSlicePtrWriter(self.0, self.1);
4490
}
@@ -66,7 +112,7 @@ impl UserSlicePtrReader {
66112
// behavior.
67113
self.0 = self.0.wrapping_offset(data.len());
68114
self.1 -= data.len();
69-
return Ok(());
115+
Ok(())
70116
}
71117
}
72118

0 commit comments

Comments
 (0)