xref: /DragonOS/kernel/src/syscall/user_access.rs (revision 83ed0ebc293d5a10245089f627f52770fd5b9dd4)
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 Ok(String::new());
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     return Ok(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         // kdebug!("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                 // kdebug!("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         Ok(self
233             .convert_with_offset::<T>(self.buffer, offset)
234             .map_err(|_| SystemError::EINVAL)?)
235     }
236 
237     fn convert_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&[T], SystemError> {
238         if offset >= src.len() {
239             return Err(SystemError::EINVAL);
240         }
241         let byte_buffer: &[u8] = &src[offset..];
242         if byte_buffer.len() % core::mem::size_of::<T>() != 0 || byte_buffer.is_empty() {
243             return Err(SystemError::EINVAL);
244         }
245 
246         let chunks = unsafe {
247             from_raw_parts(
248                 byte_buffer.as_ptr() as *const T,
249                 byte_buffer.len() / core::mem::size_of::<T>(),
250             )
251         };
252         return Ok(chunks);
253     }
254 
255     fn convert_one_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&T, SystemError> {
256         if offset + core::mem::size_of::<T>() > src.len() {
257             return Err(SystemError::EINVAL);
258         }
259         let byte_buffer: &[u8] = &src[offset..offset + core::mem::size_of::<T>()];
260 
261         let chunks = unsafe { from_raw_parts(byte_buffer.as_ptr() as *const T, 1) };
262         let data = &chunks[0];
263         return Ok(data);
264     }
265 }
266 
267 #[allow(dead_code)]
268 impl<'a> UserBufferWriter<'a> {
269     /// 构造一个指向用户空间位置的BufferWriter
270     ///
271     /// @param addr 用户空间指针
272     /// @param len 缓冲区的字节长度
273     /// @return 构造成功返回UserbufferWriter实例,否则返回错误码
274     ///
275     pub fn new<U>(addr: *mut U, len: usize, from_user: bool) -> Result<Self, SystemError> {
276         if from_user && verify_area(VirtAddr::new(addr as usize), len).is_err() {
277             return Err(SystemError::EFAULT);
278         }
279         return Ok(Self {
280             buffer: unsafe { core::slice::from_raw_parts_mut(addr as *mut u8, len) },
281         });
282     }
283 
284     pub fn size(&self) -> usize {
285         return self.buffer.len();
286     }
287 
288     /// 从指定地址写入数据到用户空间
289     ///
290     /// @param data 要写入的数据地址
291     /// @param offset 在UserBuffer中的字节偏移量
292     /// @return 返回写入元素的数量
293     ///
294     pub fn copy_to_user<T: core::marker::Copy>(
295         &'a mut self,
296         src: &[T],
297         offset: usize,
298     ) -> Result<usize, SystemError> {
299         let dst = Self::convert_with_offset(self.buffer, offset)?;
300         dst.copy_from_slice(&src);
301         return Ok(src.len());
302     }
303 
304     /// 从指定地址写入一个数据到用户空间
305     ///
306     /// @param data 要写入的数据地址
307     /// @param offset 在UserBuffer中的字节偏移量
308     /// @return Ok/Err
309     ///
310     pub fn copy_one_to_user<T: core::marker::Copy>(
311         &'a mut self,
312         src: &T,
313         offset: usize,
314     ) -> Result<(), SystemError> {
315         let dst = Self::convert_one_with_offset::<T>(self.buffer, offset)?;
316         dst.clone_from(src);
317         return Ok(());
318     }
319 
320     pub fn buffer<T>(&'a mut self, offset: usize) -> Result<&mut [T], SystemError> {
321         Ok(Self::convert_with_offset::<T>(self.buffer, offset).map_err(|_| SystemError::EINVAL)?)
322     }
323 
324     fn convert_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut [T], SystemError> {
325         if offset >= src.len() {
326             return Err(SystemError::EINVAL);
327         }
328         let byte_buffer: &mut [u8] = &mut src[offset..];
329         if byte_buffer.len() % core::mem::size_of::<T>() != 0 || byte_buffer.is_empty() {
330             return Err(SystemError::EINVAL);
331         }
332 
333         let chunks = unsafe {
334             from_raw_parts_mut(
335                 byte_buffer.as_mut_ptr() as *mut T,
336                 byte_buffer.len() / core::mem::size_of::<T>(),
337             )
338         };
339         return Ok(chunks);
340     }
341 
342     fn convert_one_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut T, SystemError> {
343         if offset + core::mem::size_of::<T>() > src.len() {
344             return Err(SystemError::EINVAL);
345         }
346         let byte_buffer: &mut [u8] = &mut src[offset..offset + core::mem::size_of::<T>()];
347 
348         let chunks = unsafe { from_raw_parts_mut(byte_buffer.as_mut_ptr() as *mut T, 1) };
349         let data = &mut chunks[0];
350         return Ok(data);
351     }
352 }
353