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