xref: /DragonOS/kernel/src/syscall/user_access.rs (revision 1ea2daad8121b77ed704e6d7c3a09f478147441d)
1 //! 这个文件用于放置一些内核态访问用户态数据的函数
2 
3 use core::{
4     mem::size_of,
5     slice::{from_raw_parts, from_raw_parts_mut},
6 };
7 
8 use alloc::{string::String, vec::Vec};
9 
10 use crate::mm::{verify_area, VirtAddr};
11 
12 use super::SystemError;
13 
14 /// 清空用户空间指定范围内的数据
15 ///
16 /// ## 参数
17 ///
18 /// - `dest`:用户空间的目标地址
19 /// - `len`:要清空的数据长度
20 ///
21 /// ## 返回值
22 ///
23 /// 返回清空的数据长度
24 ///
25 /// ## 错误
26 ///
27 /// - `EFAULT`:目标地址不合法
28 pub unsafe fn clear_user(dest: VirtAddr, len: usize) -> Result<usize, SystemError> {
29     verify_area(dest, len).map_err(|_| SystemError::EFAULT)?;
30 
31     let p = dest.data() as *mut u8;
32     // 清空用户空间的数据
33     p.write_bytes(0, len);
34     return Ok(len);
35 }
36 
37 pub unsafe fn copy_to_user(dest: VirtAddr, src: &[u8]) -> Result<usize, SystemError> {
38     verify_area(dest, src.len()).map_err(|_| SystemError::EFAULT)?;
39 
40     let p = dest.data() as *mut u8;
41     // 拷贝数据
42     p.copy_from_nonoverlapping(src.as_ptr(), src.len());
43     return Ok(src.len());
44 }
45 
46 /// 从用户空间拷贝数据到内核空间
47 pub unsafe fn copy_from_user(dst: &mut [u8], src: VirtAddr) -> Result<usize, SystemError> {
48     verify_area(src, dst.len()).map_err(|_| SystemError::EFAULT)?;
49 
50     let src: &[u8] = core::slice::from_raw_parts(src.data() as *const u8, dst.len());
51     // 拷贝数据
52     dst.copy_from_slice(src);
53 
54     return Ok(dst.len());
55 }
56 
57 /// 检查并从用户态拷贝一个 C 字符串。
58 ///
59 /// 一旦遇到非法地址,就会返回错误
60 ///
61 /// ## 参数
62 ///
63 /// - `user`:用户态的 C 字符串指针
64 /// - `max_length`:最大拷贝长度
65 ///
66 /// ## 返回值
67 ///
68 /// 返回拷贝的 C 字符串
69 ///
70 /// ## 错误
71 ///
72 /// - `EFAULT`:用户态地址不合法
73 pub fn check_and_clone_cstr(
74     user: *const u8,
75     max_length: Option<usize>,
76 ) -> Result<String, SystemError> {
77     if user.is_null() {
78         return Err(SystemError::EFAULT);
79     }
80 
81     // 从用户态读取,直到遇到空字符 '\0' 或者达到最大长度
82     let mut buffer = Vec::new();
83     for i in 0.. {
84         if max_length.is_some() && max_length.as_ref().unwrap() <= &i {
85             break;
86         }
87 
88         let addr = unsafe { user.add(i) };
89         let mut c = [0u8; 1];
90         unsafe {
91             copy_from_user(&mut c, VirtAddr::new(addr as usize))?;
92         }
93         if c[0] == 0 {
94             break;
95         }
96         buffer.push(c[0]);
97     }
98     String::from_utf8(buffer).map_err(|_| SystemError::EFAULT)
99 }
100 
101 /// 检查并从用户态拷贝一个 C 字符串数组
102 ///
103 /// 一旦遇到空指针,就会停止拷贝. 一旦遇到非法地址,就会返回错误
104 /// ## 参数
105 ///
106 /// - `user`:用户态的 C 字符串指针数组
107 ///
108 /// ## 返回值
109 ///
110 /// 返回拷贝的 C 字符串数组
111 ///
112 /// ## 错误
113 ///
114 /// - `EFAULT`:用户态地址不合法
115 pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<String>, SystemError> {
116     if user.is_null() {
117         Ok(Vec::new())
118     } else {
119         // debug!("check_and_clone_cstr_array: {:p}\n", user);
120         let mut buffer = Vec::new();
121         for i in 0.. {
122             let addr = unsafe { user.add(i) };
123             let str_ptr: *const u8;
124             // 读取这个地址的值(这个值也是一个指针)
125             unsafe {
126                 let dst = [0usize; 1];
127                 let mut dst = core::mem::transmute::<[usize; 1], [u8; size_of::<usize>()]>(dst);
128                 copy_from_user(&mut dst, VirtAddr::new(addr as usize))?;
129                 let dst = core::mem::transmute::<[u8; size_of::<usize>()], [usize; 1]>(dst);
130                 str_ptr = dst[0] as *const u8;
131 
132                 // debug!("str_ptr: {:p}, addr:{addr:?}\n", str_ptr);
133             }
134 
135             if str_ptr.is_null() {
136                 break;
137             }
138             // 读取这个指针指向的字符串
139             let string = check_and_clone_cstr(str_ptr, None)?;
140             // 将字符串放入 buffer 中
141             buffer.push(string);
142         }
143         return Ok(buffer);
144     }
145 }
146 
147 #[derive(Debug)]
148 pub struct UserBufferWriter<'a> {
149     buffer: &'a mut [u8],
150 }
151 
152 #[derive(Debug)]
153 pub struct UserBufferReader<'a> {
154     buffer: &'a [u8],
155 }
156 
157 #[allow(dead_code)]
158 impl<'a> UserBufferReader<'a> {
159     /// 构造一个指向用户空间位置的BufferReader,为了兼容类似传入 *const u8 的情况,使用单独的泛型来进行初始化
160     ///
161     /// @param addr 用户空间指针
162     /// @param len 缓冲区的字节长度
163     /// @param frm_user 代表是否要检验地址来自用户空间
164     /// @return 构造成功返回UserbufferReader实例,否则返回错误码
165     ///
166     pub fn new<U>(addr: *const U, len: usize, from_user: bool) -> Result<Self, SystemError> {
167         if from_user && verify_area(VirtAddr::new(addr as usize), len).is_err() {
168             return Err(SystemError::EFAULT);
169         }
170         return Ok(Self {
171             buffer: unsafe { core::slice::from_raw_parts(addr as *const u8, len) },
172         });
173     }
174 
175     pub fn size(&self) -> usize {
176         return self.buffer.len();
177     }
178 
179     /// 从用户空间读取数据(到变量中)
180     ///
181     /// @param offset 字节偏移量
182     /// @return 返回用户空间数据的切片(对单个结构体就返回长度为一的切片)
183     ///
184     pub fn read_from_user<T>(&self, offset: usize) -> Result<&[T], SystemError> {
185         return self.convert_with_offset(self.buffer, offset);
186     }
187     /// 从用户空间读取一个指定偏移量的数据(到变量中)
188     ///
189     /// @param offset 字节偏移量
190     /// @return 返回用户空间数据的引用
191     ///
192     pub fn read_one_from_user<T>(&self, offset: usize) -> Result<&T, SystemError> {
193         return self.convert_one_with_offset(self.buffer, offset);
194     }
195 
196     /// 从用户空间拷贝数据(到指定地址中)
197     ///
198     /// @param dst 目标地址指针
199     /// @return 拷贝成功的话返回拷贝的元素数量
200     ///
201     pub fn copy_from_user<T: core::marker::Copy>(
202         &self,
203         dst: &mut [T],
204         offset: usize,
205     ) -> Result<usize, SystemError> {
206         let data = self.convert_with_offset(self.buffer, offset)?;
207         dst.copy_from_slice(data);
208         return Ok(dst.len());
209     }
210 
211     /// 从用户空间拷贝数据(到指定地址中)
212     ///
213     /// @param dst 目标地址指针
214     /// @return 拷贝成功的话返回拷贝的元素数量
215     ///
216     pub fn copy_one_from_user<T: core::marker::Copy>(
217         &self,
218         dst: &mut T,
219         offset: usize,
220     ) -> Result<(), SystemError> {
221         let data = self.convert_one_with_offset::<T>(self.buffer, offset)?;
222         dst.clone_from(data);
223         return Ok(());
224     }
225 
226     /// 把用户空间的数据转换成指定类型的切片
227     ///
228     /// ## 参数
229     ///
230     /// - `offset`:字节偏移量
231     pub fn buffer<T>(&self, offset: usize) -> Result<&[T], SystemError> {
232         self.convert_with_offset::<T>(self.buffer, offset)
233             .map_err(|_| SystemError::EINVAL)
234     }
235 
236     fn convert_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&[T], SystemError> {
237         if offset >= src.len() {
238             return Err(SystemError::EINVAL);
239         }
240         let byte_buffer: &[u8] = &src[offset..];
241         if byte_buffer.len() % core::mem::size_of::<T>() != 0 || byte_buffer.is_empty() {
242             return Err(SystemError::EINVAL);
243         }
244 
245         let chunks = unsafe {
246             from_raw_parts(
247                 byte_buffer.as_ptr() as *const T,
248                 byte_buffer.len() / core::mem::size_of::<T>(),
249             )
250         };
251         return Ok(chunks);
252     }
253 
254     fn convert_one_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&T, SystemError> {
255         if offset + core::mem::size_of::<T>() > src.len() {
256             return Err(SystemError::EINVAL);
257         }
258         let byte_buffer: &[u8] = &src[offset..offset + core::mem::size_of::<T>()];
259 
260         let chunks = unsafe { from_raw_parts(byte_buffer.as_ptr() as *const T, 1) };
261         let data = &chunks[0];
262         return Ok(data);
263     }
264 }
265 
266 #[allow(dead_code)]
267 impl<'a> UserBufferWriter<'a> {
268     /// 构造一个指向用户空间位置的BufferWriter
269     ///
270     /// @param addr 用户空间指针
271     /// @param len 缓冲区的字节长度
272     /// @return 构造成功返回UserbufferWriter实例,否则返回错误码
273     ///
274     pub fn new<U>(addr: *mut U, len: usize, from_user: bool) -> Result<Self, SystemError> {
275         if from_user && verify_area(VirtAddr::new(addr as usize), len).is_err() {
276             return Err(SystemError::EFAULT);
277         }
278         return Ok(Self {
279             buffer: unsafe { core::slice::from_raw_parts_mut(addr as *mut u8, len) },
280         });
281     }
282 
283     pub fn size(&self) -> usize {
284         return self.buffer.len();
285     }
286 
287     /// 从指定地址写入数据到用户空间
288     ///
289     /// @param data 要写入的数据地址
290     /// @param offset 在UserBuffer中的字节偏移量
291     /// @return 返回写入元素的数量
292     ///
293     pub fn copy_to_user<T: core::marker::Copy>(
294         &'a mut self,
295         src: &[T],
296         offset: usize,
297     ) -> Result<usize, SystemError> {
298         let dst = Self::convert_with_offset(self.buffer, offset)?;
299         dst.copy_from_slice(src);
300         return Ok(src.len());
301     }
302 
303     /// 从指定地址写入一个数据到用户空间
304     ///
305     /// @param data 要写入的数据地址
306     /// @param offset 在UserBuffer中的字节偏移量
307     /// @return Ok/Err
308     ///
309     pub fn copy_one_to_user<T: core::marker::Copy>(
310         &'a mut self,
311         src: &T,
312         offset: usize,
313     ) -> Result<(), SystemError> {
314         let dst = Self::convert_one_with_offset::<T>(self.buffer, offset)?;
315         dst.clone_from(src);
316         return Ok(());
317     }
318 
319     pub fn buffer<T>(&'a mut self, offset: usize) -> Result<&mut [T], SystemError> {
320         Self::convert_with_offset::<T>(self.buffer, offset).map_err(|_| SystemError::EINVAL)
321     }
322 
323     fn convert_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut [T], SystemError> {
324         if offset >= src.len() {
325             return Err(SystemError::EINVAL);
326         }
327         let byte_buffer: &mut [u8] = &mut src[offset..];
328         if byte_buffer.len() % core::mem::size_of::<T>() != 0 || byte_buffer.is_empty() {
329             return Err(SystemError::EINVAL);
330         }
331 
332         let chunks = unsafe {
333             from_raw_parts_mut(
334                 byte_buffer.as_mut_ptr() as *mut T,
335                 byte_buffer.len() / core::mem::size_of::<T>(),
336             )
337         };
338         return Ok(chunks);
339     }
340 
341     fn convert_one_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut T, SystemError> {
342         if offset + core::mem::size_of::<T>() > src.len() {
343             return Err(SystemError::EINVAL);
344         }
345         let byte_buffer: &mut [u8] = &mut src[offset..offset + core::mem::size_of::<T>()];
346 
347         let chunks = unsafe { from_raw_parts_mut(byte_buffer.as_mut_ptr() as *mut T, 1) };
348         let data = &mut chunks[0];
349         return Ok(data);
350     }
351 }
352