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:: {
10
+ clone :: Clone ,
11
+ mem :: { size_of , MaybeUninit } ,
12
+ } ;
13
13
14
14
extern "C" {
15
15
fn rust_helper_access_ok ( addr : * const c_types:: c_void , len : c_types:: c_ulong )
@@ -68,14 +68,13 @@ impl UserSlicePtr {
68
68
/// appropriate permissions. Those checks are handled in the read
69
69
/// and write methods.
70
70
///
71
+ /// # Safety
72
+ ///
71
73
/// This is `unsafe` because if it is called within `set_fs(KERNEL_DS)`
72
74
/// context then `access_ok` will not do anything. As a result the only
73
75
/// place you can safely use this is with a `__user` pointer that was
74
76
/// 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 > {
79
78
if rust_helper_access_ok ( ptr, length as c_types:: c_ulong ) == 0 {
80
79
return Err ( error:: Error :: EFAULT ) ;
81
80
}
@@ -86,7 +85,7 @@ impl UserSlicePtr {
86
85
///
87
86
/// Returns `EFAULT` if the address does not currently point to
88
87
/// mapped, readable memory.
89
- pub fn read_all ( self ) -> error :: KernelResult < Vec < u8 > > {
88
+ pub fn read_all ( self ) -> KernelResult < Vec < u8 > > {
90
89
self . reader ( ) . read_all ( )
91
90
}
92
91
@@ -101,8 +100,8 @@ impl UserSlicePtr {
101
100
/// mapped, writable memory (in which case some data from before the
102
101
/// fault may be written), or `data` is larger than the user slice
103
102
/// (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)
106
105
}
107
106
108
107
/// Constructs a [`UserSlicePtrWriter`].
@@ -111,6 +110,12 @@ impl UserSlicePtr {
111
110
}
112
111
}
113
112
113
+ impl Clone for UserSlicePtr {
114
+ fn clone ( & self ) -> Self {
115
+ UserSlicePtr ( self . 0 , self . 1 )
116
+ }
117
+ }
118
+
114
119
/// A reader for [`UserSlicePtr`].
115
120
///
116
121
/// Used to incrementally read from the user slice.
@@ -133,9 +138,10 @@ impl UserSlicePtrReader {
133
138
///
134
139
/// Returns `EFAULT` if the address does not currently point to
135
140
/// mapped, readable memory.
136
- pub fn read_all ( & mut self ) -> error :: KernelResult < Vec < u8 > > {
141
+ pub fn read_all ( & mut self ) -> KernelResult < Vec < u8 > > {
137
142
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 ( ) ) ? } ;
139
145
Ok ( data)
140
146
}
141
147
@@ -144,27 +150,40 @@ impl UserSlicePtrReader {
144
150
/// Returns `EFAULT` if the byte slice is bigger than the remaining size
145
151
/// of the user slice or if the address does not currently point to mapped,
146
152
/// 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 {
149
165
return Err ( error:: Error :: EFAULT ) ;
150
166
}
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 _ ) ;
158
168
if res != 0 {
159
169
return Err ( error:: Error :: EFAULT ) ;
160
170
}
161
171
// Since this is not a pointer to a valid object in our program,
162
172
// we cannot use `add`, which has C-style rules for defined
163
173
// 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;
166
176
Ok ( ( ) )
167
177
}
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
+ }
168
187
}
169
188
170
189
/// A writer for [`UserSlicePtr`].
@@ -190,25 +209,35 @@ impl UserSlicePtrWriter {
190
209
/// Returns `EFAULT` if the byte slice is bigger than the remaining size
191
210
/// of the user slice or if the address does not currently point to mapped,
192
211
/// 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 {
195
224
return Err ( error:: Error :: EFAULT ) ;
196
225
}
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 _ ) ;
204
227
if res != 0 {
205
228
return Err ( error:: Error :: EFAULT ) ;
206
229
}
207
230
// Since this is not a pointer to a valid object in our program,
208
231
// we cannot use `add`, which has C-style rules for defined
209
232
// 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;
212
235
Ok ( ( ) )
213
236
}
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
+ }
214
243
}
0 commit comments