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:: {
10+ clone :: Clone ,
11+ mem :: { size_of , MaybeUninit } ,
12+ } ;
1313
1414extern "C" {
1515 fn rust_helper_access_ok ( addr : * const c_types:: c_void , len : c_types:: c_ulong )
@@ -68,14 +68,13 @@ impl UserSlicePtr {
6868 /// appropriate permissions. Those checks are handled in the read
6969 /// and write methods.
7070 ///
71+ /// # Safety
72+ ///
7173 /// This is `unsafe` because if it is called within `set_fs(KERNEL_DS)`
7274 /// context then `access_ok` will not do anything. As a result the only
7375 /// place you can safely use this is with a `__user` pointer that was
7476 /// provided by the kernel.
75- pub ( crate ) unsafe fn new (
76- ptr : * mut c_types:: c_void ,
77- length : usize ,
78- ) -> error:: KernelResult < UserSlicePtr > {
77+ pub unsafe fn new ( ptr : * mut c_types:: c_void , length : usize ) -> KernelResult < UserSlicePtr > {
7978 if rust_helper_access_ok ( ptr, length as c_types:: c_ulong ) == 0 {
8079 return Err ( error:: Error :: EFAULT ) ;
8180 }
@@ -86,7 +85,7 @@ impl UserSlicePtr {
8685 ///
8786 /// Returns `EFAULT` if the address does not currently point to
8887 /// mapped, readable memory.
89- pub fn read_all ( self ) -> error :: KernelResult < Vec < u8 > > {
88+ pub fn read_all ( self ) -> KernelResult < Vec < u8 > > {
9089 self . reader ( ) . read_all ( )
9190 }
9291
@@ -101,8 +100,8 @@ impl UserSlicePtr {
101100 /// mapped, writable memory (in which case some data from before the
102101 /// fault may be written), or `data` is larger than the user slice
103102 /// (in which case no data is written).
104- pub fn write_all ( self , data : & [ u8 ] ) -> error :: KernelResult < ( ) > {
105- self . writer ( ) . write ( data)
103+ pub fn write_all ( self , data : & [ u8 ] ) -> KernelResult < ( ) > {
104+ self . writer ( ) . write_slice ( data)
106105 }
107106
108107 /// Constructs a [`UserSlicePtrWriter`].
@@ -111,6 +110,12 @@ impl UserSlicePtr {
111110 }
112111}
113112
113+ impl Clone for UserSlicePtr {
114+ fn clone ( & self ) -> Self {
115+ UserSlicePtr ( self . 0 , self . 1 )
116+ }
117+ }
118+
114119/// A reader for [`UserSlicePtr`].
115120///
116121/// Used to incrementally read from the user slice.
@@ -133,9 +138,10 @@ impl UserSlicePtrReader {
133138 ///
134139 /// Returns `EFAULT` if the address does not currently point to
135140 /// mapped, readable memory.
136- pub fn read_all ( & mut self ) -> error :: KernelResult < Vec < u8 > > {
141+ pub fn read_all ( & mut self ) -> KernelResult < Vec < u8 > > {
137142 let mut data = vec ! [ 0 ; self . 1 ] ;
138- self . read ( & mut data) ?;
143+ // SAFETY: The output buffer is valid as we just allocated it.
144+ unsafe { self . read_raw ( data. as_mut_ptr ( ) , data. len ( ) ) ? } ;
139145 Ok ( data)
140146 }
141147
@@ -144,27 +150,40 @@ impl UserSlicePtrReader {
144150 /// Returns `EFAULT` if the byte slice is bigger than the remaining size
145151 /// of the user slice or if the address does not currently point to mapped,
146152 /// 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 {
153+ pub fn read_slice ( & mut self , data : & mut [ u8 ] ) -> KernelResult < ( ) > {
154+ // SAFETY: The output buffer is valid as it's coming from a live reference.
155+ unsafe { self . read_raw ( data. as_mut_ptr ( ) , data. len ( ) ) }
156+ }
157+
158+ /// Reads raw data from the user slice into a raw kernel buffer.
159+ ///
160+ /// # Safety
161+ ///
162+ /// The output buffer must be valid.
163+ pub unsafe fn read_raw ( & mut self , out : * mut u8 , len : usize ) -> KernelResult < ( ) > {
164+ if len > self . 1 || len > u32:: MAX as usize {
149165 return Err ( error:: Error :: EFAULT ) ;
150166 }
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- } ;
167+ let res = rust_helper_copy_from_user ( out as _ , self . 0 , len as _ ) ;
158168 if res != 0 {
159169 return Err ( error:: Error :: EFAULT ) ;
160170 }
161171 // Since this is not a pointer to a valid object in our program,
162172 // we cannot use `add`, which has C-style rules for defined
163173 // behavior.
164- self . 0 = self . 0 . wrapping_add ( data . len ( ) ) ;
165- self . 1 -= data . len ( ) ;
174+ self . 0 = self . 0 . wrapping_add ( len) ;
175+ self . 1 -= len;
166176 Ok ( ( ) )
167177 }
178+
179+ /// Reads the contents of a plain old data (POD) type from the user slice.
180+ pub fn read < T : Copy > ( & mut self ) -> KernelResult < T > {
181+ let mut out = MaybeUninit :: < T > :: uninit ( ) ;
182+ // SAFETY: The buffer is valid it was just allocated.
183+ unsafe { self . read_raw ( out. as_mut_ptr ( ) as _ , size_of :: < T > ( ) ) ? } ;
184+ // SAFETY: We just initialised the data.
185+ Ok ( unsafe { out. assume_init ( ) } )
186+ }
168187}
169188
170189/// A writer for [`UserSlicePtr`].
@@ -190,25 +209,35 @@ impl UserSlicePtrWriter {
190209 /// Returns `EFAULT` if the byte slice is bigger than the remaining size
191210 /// of the user slice or if the address does not currently point to mapped,
192211 /// writable memory.
193- pub fn write ( & mut self , data : & [ u8 ] ) -> error:: KernelResult < ( ) > {
194- if data. len ( ) > self . 1 || data. len ( ) > u32:: MAX as usize {
212+ pub fn write_slice ( & mut self , data : & [ u8 ] ) -> KernelResult < ( ) > {
213+ // SAFETY: The input buffer is valid as it's coming from a live reference.
214+ unsafe { self . write_raw ( data. as_ptr ( ) , data. len ( ) ) }
215+ }
216+
217+ /// Writes raw data to the user slice from a raw kernel buffer.
218+ ///
219+ /// # Safety
220+ ///
221+ /// The input buffer must be valid.
222+ unsafe fn write_raw ( & mut self , data : * const u8 , len : usize ) -> KernelResult < ( ) > {
223+ if len > self . 1 || len > u32:: MAX as usize {
195224 return Err ( error:: Error :: EFAULT ) ;
196225 }
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- } ;
226+ let res = rust_helper_copy_to_user ( self . 0 , data as _ , len as _ ) ;
204227 if res != 0 {
205228 return Err ( error:: Error :: EFAULT ) ;
206229 }
207230 // Since this is not a pointer to a valid object in our program,
208231 // we cannot use `add`, which has C-style rules for defined
209232 // behavior.
210- self . 0 = self . 0 . wrapping_add ( data . len ( ) ) ;
211- self . 1 -= data . len ( ) ;
233+ self . 0 = self . 0 . wrapping_add ( len) ;
234+ self . 1 -= len;
212235 Ok ( ( ) )
213236 }
237+
238+ /// Writes the contents of a plain old data (POD) type into the user slice.
239+ pub fn write < T : Copy > ( & mut self , data : & T ) -> KernelResult < ( ) > {
240+ // SAFETY: The input buffer is valid as it's coming from a live reference.
241+ unsafe { self . write_raw ( data as * const T as _ , size_of :: < T > ( ) ) }
242+ }
214243}
0 commit comments