4
4
//!
5
5
//! C header: [`include/linux/uaccess.h`](../../../../include/linux/uaccess.h)
6
6
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 } ;
13
10
14
11
extern "C" {
15
12
fn rust_helper_access_ok ( addr : * const c_types:: c_void , len : c_types:: c_ulong )
@@ -28,6 +25,30 @@ extern "C" {
28
25
) -> c_types:: c_ulong ;
29
26
}
30
27
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
+
31
52
/// A reference to an area in userspace memory, which can be either
32
53
/// read-only or read-write.
33
54
///
@@ -68,14 +89,18 @@ impl UserSlicePtr {
68
89
/// appropriate permissions. Those checks are handled in the read
69
90
/// and write methods.
70
91
///
92
+ /// # Safety
93
+ ///
71
94
/// This is `unsafe` because if it is called within `set_fs(KERNEL_DS)`
72
95
/// context then `access_ok` will not do anything. As a result the only
73
96
/// place you can safely use this is with a `__user` pointer that was
74
97
/// 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 > {
79
104
if rust_helper_access_ok ( ptr, length as c_types:: c_ulong ) == 0 {
80
105
return Err ( error:: Error :: EFAULT ) ;
81
106
}
@@ -86,7 +111,7 @@ impl UserSlicePtr {
86
111
///
87
112
/// Returns `EFAULT` if the address does not currently point to
88
113
/// mapped, readable memory.
89
- pub fn read_all ( self ) -> error :: KernelResult < Vec < u8 > > {
114
+ pub fn read_all ( self ) -> KernelResult < Vec < u8 > > {
90
115
self . reader ( ) . read_all ( )
91
116
}
92
117
@@ -101,14 +126,22 @@ impl UserSlicePtr {
101
126
/// mapped, writable memory (in which case some data from before the
102
127
/// fault may be written), or `data` is larger than the user slice
103
128
/// (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)
106
131
}
107
132
108
133
/// Constructs a [`UserSlicePtrWriter`].
109
134
pub fn writer ( self ) -> UserSlicePtrWriter {
110
135
UserSlicePtrWriter ( self . 0 , self . 1 )
111
136
}
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
+ }
112
145
}
113
146
114
147
/// A reader for [`UserSlicePtr`].
@@ -133,9 +166,10 @@ impl UserSlicePtrReader {
133
166
///
134
167
/// Returns `EFAULT` if the address does not currently point to
135
168
/// mapped, readable memory.
136
- pub fn read_all ( & mut self ) -> error :: KernelResult < Vec < u8 > > {
169
+ pub fn read_all ( & mut self ) -> KernelResult < Vec < u8 > > {
137
170
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 ( ) ) ? } ;
139
173
Ok ( data)
140
174
}
141
175
@@ -144,27 +178,40 @@ impl UserSlicePtrReader {
144
178
/// Returns `EFAULT` if the byte slice is bigger than the remaining size
145
179
/// of the user slice or if the address does not currently point to mapped,
146
180
/// 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 {
149
193
return Err ( error:: Error :: EFAULT ) ;
150
194
}
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 _ ) ;
158
196
if res != 0 {
159
197
return Err ( error:: Error :: EFAULT ) ;
160
198
}
161
199
// Since this is not a pointer to a valid object in our program,
162
200
// we cannot use `add`, which has C-style rules for defined
163
201
// 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;
166
204
Ok ( ( ) )
167
205
}
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
+ }
168
215
}
169
216
170
217
/// A writer for [`UserSlicePtr`].
@@ -190,25 +237,35 @@ impl UserSlicePtrWriter {
190
237
/// Returns `EFAULT` if the byte slice is bigger than the remaining size
191
238
/// of the user slice or if the address does not currently point to mapped,
192
239
/// 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 {
195
252
return Err ( error:: Error :: EFAULT ) ;
196
253
}
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 _ ) ;
204
255
if res != 0 {
205
256
return Err ( error:: Error :: EFAULT ) ;
206
257
}
207
258
// Since this is not a pointer to a valid object in our program,
208
259
// we cannot use `add`, which has C-style rules for defined
209
260
// 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;
212
263
Ok ( ( ) )
213
264
}
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
+ }
214
271
}
0 commit comments