44//!
55//! C header: [`include/linux/uaccess.h`](../../../../include/linux/uaccess.h)
66
7- use alloc:: vec;
8- use alloc:: vec:: Vec ;
9- use core:: u32;
10-
11- use crate :: c_types;
12- use crate :: error;
7+ use crate :: { c_types, error, KernelResult } ;
8+ use alloc:: { vec, vec:: Vec } ;
9+ use core:: mem:: { size_of, MaybeUninit } ;
1310
1411extern "C" {
1512 fn rust_helper_access_ok ( addr : * const c_types:: c_void , len : c_types:: c_ulong )
@@ -28,6 +25,30 @@ extern "C" {
2825 ) -> c_types:: c_ulong ;
2926}
3027
28+ /// Specifies that a type is safely readable from byte slices.
29+ ///
30+ /// Not all types can be safely read from byte slices; examples from
31+ /// <https://doc.rust-lang.org/reference/behavior-considered-undefined.html> include `bool`
32+ /// that must be either `0` or `1`, and `char` that cannot be a surrogate or above `char::MAX`.
33+ ///
34+ /// # Safety
35+ ///
36+ /// Implementers must ensure that the type is made up only of types that can be safely read from
37+ /// arbitrary byte sequences (e.g., `u32`, `u64`, etc.).
38+ pub unsafe trait ReadableFromBytes { }
39+
40+ // SAFETY: All bit patterns are acceptable values of the types below.
41+ unsafe impl ReadableFromBytes for u8 { }
42+ unsafe impl ReadableFromBytes for u16 { }
43+ unsafe impl ReadableFromBytes for u32 { }
44+ unsafe impl ReadableFromBytes for u64 { }
45+ unsafe impl ReadableFromBytes for usize { }
46+ unsafe impl ReadableFromBytes for i8 { }
47+ unsafe impl ReadableFromBytes for i16 { }
48+ unsafe impl ReadableFromBytes for i32 { }
49+ unsafe impl ReadableFromBytes for i64 { }
50+ unsafe impl ReadableFromBytes for isize { }
51+
3152/// A reference to an area in userspace memory, which can be either
3253/// read-only or read-write.
3354///
@@ -68,14 +89,18 @@ impl UserSlicePtr {
6889 /// appropriate permissions. Those checks are handled in the read
6990 /// and write methods.
7091 ///
92+ /// # Safety
93+ ///
7194 /// This is `unsafe` because if it is called within `set_fs(KERNEL_DS)`
7295 /// context then `access_ok` will not do anything. As a result the only
7396 /// place you can safely use this is with a `__user` pointer that was
7497 /// provided by the kernel.
75- pub ( crate ) unsafe fn new (
76- ptr : * mut c_types:: c_void ,
77- length : usize ,
78- ) -> error:: KernelResult < UserSlicePtr > {
98+ ///
99+ /// Callers must also be careful to avoid time-of-check-time-of-use
100+ /// (TOCTOU) issues. The simplest way is to create a single instance of
101+ /// [`UserSlicePtr`] per user memory block as it reads each byte at
102+ /// most once.
103+ pub unsafe fn new ( ptr : * mut c_types:: c_void , length : usize ) -> KernelResult < UserSlicePtr > {
79104 if rust_helper_access_ok ( ptr, length as c_types:: c_ulong ) == 0 {
80105 return Err ( error:: Error :: EFAULT ) ;
81106 }
@@ -86,7 +111,7 @@ impl UserSlicePtr {
86111 ///
87112 /// Returns `EFAULT` if the address does not currently point to
88113 /// mapped, readable memory.
89- pub fn read_all ( self ) -> error :: KernelResult < Vec < u8 > > {
114+ pub fn read_all ( self ) -> KernelResult < Vec < u8 > > {
90115 self . reader ( ) . read_all ( )
91116 }
92117
@@ -101,14 +126,22 @@ impl UserSlicePtr {
101126 /// mapped, writable memory (in which case some data from before the
102127 /// fault may be written), or `data` is larger than the user slice
103128 /// (in which case no data is written).
104- pub fn write_all ( self , data : & [ u8 ] ) -> error :: KernelResult < ( ) > {
105- self . writer ( ) . write ( data)
129+ pub fn write_all ( self , data : & [ u8 ] ) -> KernelResult < ( ) > {
130+ self . writer ( ) . write_slice ( data)
106131 }
107132
108133 /// Constructs a [`UserSlicePtrWriter`].
109134 pub fn writer ( self ) -> UserSlicePtrWriter {
110135 UserSlicePtrWriter ( self . 0 , self . 1 )
111136 }
137+
138+ /// Constructs both a [`UserSlicePtrReader`] and a [`UserSlicePtrWriter`].
139+ pub fn reader_writer ( self ) -> ( UserSlicePtrReader , UserSlicePtrWriter ) {
140+ (
141+ UserSlicePtrReader ( self . 0 , self . 1 ) ,
142+ UserSlicePtrWriter ( self . 0 , self . 1 ) ,
143+ )
144+ }
112145}
113146
114147/// A reader for [`UserSlicePtr`].
@@ -133,9 +166,10 @@ impl UserSlicePtrReader {
133166 ///
134167 /// Returns `EFAULT` if the address does not currently point to
135168 /// mapped, readable memory.
136- pub fn read_all ( & mut self ) -> error :: KernelResult < Vec < u8 > > {
169+ pub fn read_all ( & mut self ) -> KernelResult < Vec < u8 > > {
137170 let mut data = vec ! [ 0 ; self . 1 ] ;
138- self . read ( & mut data) ?;
171+ // SAFETY: The output buffer is valid as we just allocated it.
172+ unsafe { self . read_raw ( data. as_mut_ptr ( ) , data. len ( ) ) ? } ;
139173 Ok ( data)
140174 }
141175
@@ -144,27 +178,40 @@ impl UserSlicePtrReader {
144178 /// Returns `EFAULT` if the byte slice is bigger than the remaining size
145179 /// of the user slice or if the address does not currently point to mapped,
146180 /// readable memory.
147- pub fn read ( & mut self , data : & mut [ u8 ] ) -> error:: KernelResult < ( ) > {
148- if data. len ( ) > self . 1 || data. len ( ) > u32:: MAX as usize {
181+ pub fn read_slice ( & mut self , data : & mut [ u8 ] ) -> KernelResult < ( ) > {
182+ // SAFETY: The output buffer is valid as it's coming from a live reference.
183+ unsafe { self . read_raw ( data. as_mut_ptr ( ) , data. len ( ) ) }
184+ }
185+
186+ /// Reads raw data from the user slice into a raw kernel buffer.
187+ ///
188+ /// # Safety
189+ ///
190+ /// The output buffer must be valid.
191+ pub unsafe fn read_raw ( & mut self , out : * mut u8 , len : usize ) -> KernelResult < ( ) > {
192+ if len > self . 1 || len > u32:: MAX as usize {
149193 return Err ( error:: Error :: EFAULT ) ;
150194 }
151- let res = unsafe {
152- rust_helper_copy_from_user (
153- data. as_mut_ptr ( ) as * mut c_types:: c_void ,
154- self . 0 ,
155- data. len ( ) as _ ,
156- )
157- } ;
195+ let res = rust_helper_copy_from_user ( out as _ , self . 0 , len as _ ) ;
158196 if res != 0 {
159197 return Err ( error:: Error :: EFAULT ) ;
160198 }
161199 // Since this is not a pointer to a valid object in our program,
162200 // we cannot use `add`, which has C-style rules for defined
163201 // behavior.
164- self . 0 = self . 0 . wrapping_add ( data . len ( ) ) ;
165- self . 1 -= data . len ( ) ;
202+ self . 0 = self . 0 . wrapping_add ( len) ;
203+ self . 1 -= len;
166204 Ok ( ( ) )
167205 }
206+
207+ /// Reads the contents of a plain old data (POD) type from the user slice.
208+ pub fn read < T : ReadableFromBytes > ( & mut self ) -> KernelResult < T > {
209+ let mut out = MaybeUninit :: < T > :: uninit ( ) ;
210+ // SAFETY: The buffer is valid as it was just allocated.
211+ unsafe { self . read_raw ( out. as_mut_ptr ( ) as _ , size_of :: < T > ( ) ) } ?;
212+ // SAFETY: We just initialised the data.
213+ Ok ( unsafe { out. assume_init ( ) } )
214+ }
168215}
169216
170217/// A writer for [`UserSlicePtr`].
@@ -190,25 +237,35 @@ impl UserSlicePtrWriter {
190237 /// Returns `EFAULT` if the byte slice is bigger than the remaining size
191238 /// of the user slice or if the address does not currently point to mapped,
192239 /// writable memory.
193- pub fn write ( & mut self , data : & [ u8 ] ) -> error:: KernelResult < ( ) > {
194- if data. len ( ) > self . 1 || data. len ( ) > u32:: MAX as usize {
240+ pub fn write_slice ( & mut self , data : & [ u8 ] ) -> KernelResult < ( ) > {
241+ // SAFETY: The input buffer is valid as it's coming from a live reference.
242+ unsafe { self . write_raw ( data. as_ptr ( ) , data. len ( ) ) }
243+ }
244+
245+ /// Writes raw data to the user slice from a raw kernel buffer.
246+ ///
247+ /// # Safety
248+ ///
249+ /// The input buffer must be valid.
250+ unsafe fn write_raw ( & mut self , data : * const u8 , len : usize ) -> KernelResult < ( ) > {
251+ if len > self . 1 || len > u32:: MAX as usize {
195252 return Err ( error:: Error :: EFAULT ) ;
196253 }
197- let res = unsafe {
198- rust_helper_copy_to_user (
199- self . 0 ,
200- data. as_ptr ( ) as * const c_types:: c_void ,
201- data. len ( ) as _ ,
202- )
203- } ;
254+ let res = rust_helper_copy_to_user ( self . 0 , data as _ , len as _ ) ;
204255 if res != 0 {
205256 return Err ( error:: Error :: EFAULT ) ;
206257 }
207258 // Since this is not a pointer to a valid object in our program,
208259 // we cannot use `add`, which has C-style rules for defined
209260 // behavior.
210- self . 0 = self . 0 . wrapping_add ( data . len ( ) ) ;
211- self . 1 -= data . len ( ) ;
261+ self . 0 = self . 0 . wrapping_add ( len) ;
262+ self . 1 -= len;
212263 Ok ( ( ) )
213264 }
265+
266+ /// Writes the contents of a plain old data (POD) type into the user slice.
267+ pub fn write < T : Copy > ( & mut self , data : & T ) -> KernelResult < ( ) > {
268+ // SAFETY: The input buffer is valid as it's coming from a live reference.
269+ unsafe { self . write_raw ( data as * const T as _ , size_of :: < T > ( ) ) }
270+ }
214271}
0 commit comments