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