xref: /DragonOS/kernel/src/syscall/user_access.rs (revision 40314b30ab2a7e1fd06a05a00f693e644e446035)
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     /// 从用户空间读取数据(到变量中)
176     ///
177     /// @param offset 字节偏移量
178     /// @return 返回用户空间数据的切片(对单个结构体就返回长度为一的切片)
179     ///
180     pub fn read_from_user<T>(&self, offset: usize) -> Result<&[T], SystemError> {
181         return self.convert_with_offset(&self.buffer, offset);
182     }
183     /// 从用户空间读取一个指定偏移量的数据(到变量中)
184     ///
185     /// @param offset 字节偏移量
186     /// @return 返回用户空间数据的引用
187     ///
188     pub fn read_one_from_user<T>(&self, offset: usize) -> Result<&T, SystemError> {
189         return self.convert_one_with_offset(&self.buffer, offset);
190     }
191 
192     /// 从用户空间拷贝数据(到指定地址中)
193     ///
194     /// @param dst 目标地址指针
195     /// @return 拷贝成功的话返回拷贝的元素数量
196     ///
197     pub fn copy_from_user<T: core::marker::Copy>(
198         &self,
199         dst: &mut [T],
200         offset: usize,
201     ) -> Result<usize, SystemError> {
202         let data = self.convert_with_offset(&self.buffer, offset)?;
203         dst.copy_from_slice(data);
204         return Ok(dst.len());
205     }
206 
207     /// 从用户空间拷贝数据(到指定地址中)
208     ///
209     /// @param dst 目标地址指针
210     /// @return 拷贝成功的话返回拷贝的元素数量
211     ///
212     pub fn copy_one_from_user<T: core::marker::Copy>(
213         &self,
214         dst: &mut T,
215         offset: usize,
216     ) -> Result<(), SystemError> {
217         let data = self.convert_one_with_offset::<T>(&self.buffer, offset)?;
218         dst.clone_from(data);
219         return Ok(());
220     }
221 
222     fn convert_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&[T], SystemError> {
223         if offset >= src.len() {
224             return Err(SystemError::EINVAL);
225         }
226         let byte_buffer: &[u8] = &src[offset..];
227         if byte_buffer.len() % core::mem::size_of::<T>() != 0 || byte_buffer.is_empty() {
228             return Err(SystemError::EINVAL);
229         }
230 
231         let chunks = unsafe {
232             from_raw_parts(
233                 byte_buffer.as_ptr() as *const T,
234                 byte_buffer.len() / core::mem::size_of::<T>(),
235             )
236         };
237         return Ok(chunks);
238     }
239 
240     fn convert_one_with_offset<T>(&self, src: &[u8], offset: usize) -> Result<&T, SystemError> {
241         if offset + core::mem::size_of::<T>() > src.len() {
242             return Err(SystemError::EINVAL);
243         }
244         let byte_buffer: &[u8] = &src[offset..offset + core::mem::size_of::<T>()];
245 
246         let chunks = unsafe { from_raw_parts(byte_buffer.as_ptr() as *const T, 1) };
247         let data = &chunks[0];
248         return Ok(data);
249     }
250 }
251 
252 #[allow(dead_code)]
253 impl<'a> UserBufferWriter<'a> {
254     /// 构造一个指向用户空间位置的BufferWriter
255     ///
256     /// @param addr 用户空间指针
257     /// @param len 缓冲区的字节长度
258     /// @return 构造成功返回UserbufferWriter实例,否则返回错误码
259     ///
260     pub fn new<U>(addr: *mut U, len: usize, from_user: bool) -> Result<Self, SystemError> {
261         if from_user && verify_area(VirtAddr::new(addr as usize), len).is_err() {
262             return Err(SystemError::EFAULT);
263         }
264         return Ok(Self {
265             buffer: unsafe { core::slice::from_raw_parts_mut(addr as *mut u8, len) },
266         });
267     }
268 
269     /// 从指定地址写入数据到用户空间
270     ///
271     /// @param data 要写入的数据地址
272     /// @param offset 在UserBuffer中的字节偏移量
273     /// @return 返回写入元素的数量
274     ///
275     pub fn copy_to_user<T: core::marker::Copy>(
276         &'a mut self,
277         src: &'a [T],
278         offset: usize,
279     ) -> Result<usize, SystemError> {
280         let dst = Self::convert_with_offset(self.buffer, offset)?;
281         dst.copy_from_slice(&src);
282         return Ok(src.len());
283     }
284 
285     /// 从指定地址写入一个数据到用户空间
286     ///
287     /// @param data 要写入的数据地址
288     /// @param offset 在UserBuffer中的字节偏移量
289     /// @return Ok/Err
290     ///
291     pub fn copy_one_to_user<T: core::marker::Copy>(
292         &'a mut self,
293         src: &'a T,
294         offset: usize,
295     ) -> Result<(), SystemError> {
296         let dst = Self::convert_one_with_offset::<T>(self.buffer, offset)?;
297         dst.clone_from(src);
298         return Ok(());
299     }
300 
301     pub fn buffer<T>(&'a mut self, offset: usize) -> Result<&mut [T], SystemError> {
302         Ok(Self::convert_with_offset::<T>(self.buffer, offset).map_err(|_| SystemError::EINVAL)?)
303     }
304 
305     fn convert_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut [T], SystemError> {
306         if offset >= src.len() {
307             return Err(SystemError::EINVAL);
308         }
309         let byte_buffer: &mut [u8] = &mut src[offset..];
310         if byte_buffer.len() % core::mem::size_of::<T>() != 0 || byte_buffer.is_empty() {
311             return Err(SystemError::EINVAL);
312         }
313 
314         let chunks = unsafe {
315             from_raw_parts_mut(
316                 byte_buffer.as_mut_ptr() as *mut T,
317                 byte_buffer.len() / core::mem::size_of::<T>(),
318             )
319         };
320         return Ok(chunks);
321     }
322 
323     fn convert_one_with_offset<T>(src: &mut [u8], offset: usize) -> Result<&mut T, SystemError> {
324         if offset + core::mem::size_of::<T>() > src.len() {
325             return Err(SystemError::EINVAL);
326         }
327         let byte_buffer: &mut [u8] = &mut src[offset..offset + core::mem::size_of::<T>()];
328 
329         let chunks = unsafe { from_raw_parts_mut(byte_buffer.as_mut_ptr() as *mut T, 1) };
330         let data = &mut chunks[0];
331         return Ok(data);
332     }
333 }
334