xref: /DragonOS/kernel/src/process/syscall.rs (revision 703ce5a77c1e4bebadc5aaa6cbb21595663d4477)
1 use core::ffi::c_void;
2 
3 use alloc::{ffi::CString, string::ToString, sync::Arc, vec::Vec};
4 use log::error;
5 use system_error::SystemError;
6 
7 use super::{
8     abi::WaitOption,
9     exit::kernel_wait4,
10     fork::{CloneFlags, KernelCloneArgs},
11     resource::{RLimit64, RLimitID, RUsage, RUsageWho},
12     KernelStack, Pid, ProcessManager,
13 };
14 use crate::{
15     arch::{interrupt::TrapFrame, MMArch},
16     filesystem::{
17         procfs::procfs_register_pid,
18         vfs::{file::FileDescriptorVec, MAX_PATHLEN},
19     },
20     mm::{ucontext::UserStack, verify_area, MemoryManagementArch, VirtAddr},
21     process::ProcessControlBlock,
22     sched::completion::Completion,
23     syscall::{
24         user_access::{check_and_clone_cstr, check_and_clone_cstr_array, UserBufferWriter},
25         Syscall,
26     },
27 };
28 
29 //参考资料:https://code.dragonos.org.cn/xref/linux-6.1.9/include/uapi/linux/utsname.h#17
30 #[repr(C)]
31 #[derive(Debug, Clone, Copy)]
32 pub struct PosixOldUtsName {
33     pub sysname: [u8; 65],
34     pub nodename: [u8; 65],
35     pub release: [u8; 65],
36     pub version: [u8; 65],
37     pub machine: [u8; 65],
38 }
39 
40 impl PosixOldUtsName {
41     pub fn new() -> Self {
42         const SYS_NAME: &[u8] = b"DragonOS";
43         const NODENAME: &[u8] = b"DragonOS";
44         const RELEASE: &[u8] = env!("CARGO_PKG_VERSION").as_bytes();
45         const VERSION: &[u8] = env!("CARGO_PKG_VERSION").as_bytes();
46 
47         #[cfg(target_arch = "x86_64")]
48         const MACHINE: &[u8] = b"x86_64";
49 
50         #[cfg(target_arch = "aarch64")]
51         const MACHINE: &[u8] = b"aarch64";
52 
53         #[cfg(target_arch = "riscv64")]
54         const MACHINE: &[u8] = b"riscv64";
55 
56         let mut r = Self {
57             sysname: [0; 65],
58             nodename: [0; 65],
59             release: [0; 65],
60             version: [0; 65],
61             machine: [0; 65],
62         };
63 
64         r.sysname[0..SYS_NAME.len()].copy_from_slice(SYS_NAME);
65         r.nodename[0..NODENAME.len()].copy_from_slice(NODENAME);
66         r.release[0..RELEASE.len()].copy_from_slice(RELEASE);
67         r.version[0..VERSION.len()].copy_from_slice(VERSION);
68         r.machine[0..MACHINE.len()].copy_from_slice(MACHINE);
69 
70         return r;
71     }
72 }
73 
74 impl Syscall {
75     pub fn fork(frame: &TrapFrame) -> Result<usize, SystemError> {
76         ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into())
77     }
78 
79     pub fn vfork(frame: &TrapFrame) -> Result<usize, SystemError> {
80         // 由于Linux vfork需要保证子进程先运行(除非子进程调用execve或者exit),
81         // 而我们目前没有实现这个特性,所以暂时使用fork代替vfork(linux文档表示这样也是也可以的)
82         Self::fork(frame)
83 
84         // 下面是以前的实现,除非我们实现了子进程先运行的特性,否则不要使用,不然会导致父进程数据损坏
85         // ProcessManager::fork(
86         //     frame,
87         //     CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
88         // )
89         // .map(|pid| pid.into())
90     }
91 
92     pub fn execve(
93         path: *const u8,
94         argv: *const *const u8,
95         envp: *const *const u8,
96         frame: &mut TrapFrame,
97     ) -> Result<(), SystemError> {
98         // debug!(
99         //     "execve path: {:?}, argv: {:?}, envp: {:?}\n",
100         //     path,
101         //     argv,
102         //     envp
103         // );
104         // debug!(
105         //     "before execve: strong count: {}",
106         //     Arc::strong_count(&ProcessManager::current_pcb())
107         // );
108 
109         if path.is_null() {
110             return Err(SystemError::EINVAL);
111         }
112 
113         let x = || {
114             let path: CString = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
115             let argv: Vec<CString> = check_and_clone_cstr_array(argv)?;
116             let envp: Vec<CString> = check_and_clone_cstr_array(envp)?;
117             Ok((path, argv, envp))
118         };
119         let (path, argv, envp) = x().inspect_err(|e: &SystemError| {
120             error!("Failed to execve: {:?}", e);
121         })?;
122 
123         let path = path.into_string().map_err(|_| SystemError::EINVAL)?;
124         ProcessManager::current_pcb()
125             .basic_mut()
126             .set_name(ProcessControlBlock::generate_name(&path, &argv));
127 
128         Self::do_execve(path, argv, envp, frame)?;
129 
130         // 关闭设置了O_CLOEXEC的文件描述符
131         let fd_table = ProcessManager::current_pcb().fd_table();
132         fd_table.write().close_on_exec();
133         // debug!(
134         //     "after execve: strong count: {}",
135         //     Arc::strong_count(&ProcessManager::current_pcb())
136         // );
137 
138         return Ok(());
139     }
140 
141     pub fn wait4(
142         pid: i64,
143         wstatus: *mut i32,
144         options: i32,
145         rusage: *mut c_void,
146     ) -> Result<usize, SystemError> {
147         let options = WaitOption::from_bits(options as u32).ok_or(SystemError::EINVAL)?;
148 
149         let wstatus_buf = if wstatus.is_null() {
150             None
151         } else {
152             Some(UserBufferWriter::new(
153                 wstatus,
154                 core::mem::size_of::<i32>(),
155                 true,
156             )?)
157         };
158 
159         let mut tmp_rusage = if rusage.is_null() {
160             None
161         } else {
162             Some(RUsage::default())
163         };
164 
165         let r = kernel_wait4(pid, wstatus_buf, options, tmp_rusage.as_mut())?;
166 
167         if !rusage.is_null() {
168             let mut rusage_buf = UserBufferWriter::new::<RUsage>(
169                 rusage as *mut RUsage,
170                 core::mem::size_of::<RUsage>(),
171                 true,
172             )?;
173             rusage_buf.copy_one_to_user(&tmp_rusage.unwrap(), 0)?;
174         }
175         return Ok(r);
176     }
177 
178     /// # 退出进程
179     ///
180     /// ## 参数
181     ///
182     /// - status: 退出状态
183     pub fn exit(status: usize) -> ! {
184         ProcessManager::exit(status);
185     }
186 
187     /// @brief 获取当前进程的pid
188     pub fn getpid() -> Result<Pid, SystemError> {
189         let current_pcb = ProcessManager::current_pcb();
190         return Ok(current_pcb.tgid());
191     }
192 
193     /// @brief 获取指定进程的pgid
194     ///
195     /// @param pid 指定一个进程号
196     ///
197     /// @return 成功,指定进程的进程组id
198     /// @return 错误,不存在该进程
199     pub fn getpgid(mut pid: Pid) -> Result<Pid, SystemError> {
200         if pid == Pid(0) {
201             let current_pcb = ProcessManager::current_pcb();
202             pid = current_pcb.pid();
203         }
204         let target_proc = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?;
205         return Ok(target_proc.basic().pgid());
206     }
207     /// @brief 获取当前进程的父进程id
208 
209     /// 若为initproc则ppid设置为0
210     pub fn getppid() -> Result<Pid, SystemError> {
211         let current_pcb = ProcessManager::current_pcb();
212         return Ok(current_pcb.basic().ppid());
213     }
214 
215     pub fn clone(
216         current_trapframe: &TrapFrame,
217         clone_args: KernelCloneArgs,
218     ) -> Result<usize, SystemError> {
219         let flags = clone_args.flags;
220 
221         let vfork = Arc::new(Completion::new());
222 
223         if flags.contains(CloneFlags::CLONE_PIDFD)
224             && flags.contains(CloneFlags::CLONE_PARENT_SETTID)
225         {
226             return Err(SystemError::EINVAL);
227         }
228 
229         let current_pcb = ProcessManager::current_pcb();
230         let new_kstack = KernelStack::new()?;
231         let name = current_pcb.basic().name().to_string();
232         let pcb = ProcessControlBlock::new(name, new_kstack);
233         // 克隆pcb
234         ProcessManager::copy_process(&current_pcb, &pcb, clone_args, current_trapframe)?;
235         ProcessManager::add_pcb(pcb.clone());
236 
237         // 向procfs注册进程
238         procfs_register_pid(pcb.pid()).unwrap_or_else(|e| {
239             panic!(
240                 "fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}",
241                 pcb.pid(),
242                 e
243             )
244         });
245 
246         if flags.contains(CloneFlags::CLONE_VFORK) {
247             pcb.thread.write_irqsave().vfork_done = Some(vfork.clone());
248         }
249 
250         if pcb.thread.read_irqsave().set_child_tid.is_some() {
251             let addr = pcb.thread.read_irqsave().set_child_tid.unwrap();
252             let mut writer =
253                 UserBufferWriter::new(addr.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?;
254             writer.copy_one_to_user(&(pcb.pid().data() as i32), 0)?;
255         }
256 
257         ProcessManager::wakeup(&pcb).unwrap_or_else(|e| {
258             panic!(
259                 "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}",
260                 pcb.pid(),
261                 e
262             )
263         });
264 
265         if flags.contains(CloneFlags::CLONE_VFORK) {
266             // 等待子进程结束或者exec;
267             vfork.wait_for_completion_interruptible()?;
268         }
269 
270         return Ok(pcb.pid().0);
271     }
272 
273     /// 设置线程地址
274     pub fn set_tid_address(ptr: usize) -> Result<usize, SystemError> {
275         verify_area(VirtAddr::new(ptr), core::mem::size_of::<i32>())
276             .map_err(|_| SystemError::EFAULT)?;
277 
278         let pcb = ProcessManager::current_pcb();
279         pcb.thread.write_irqsave().clear_child_tid = Some(VirtAddr::new(ptr));
280         Ok(pcb.pid.0)
281     }
282 
283     pub fn gettid() -> Result<Pid, SystemError> {
284         let pcb = ProcessManager::current_pcb();
285         Ok(pcb.pid)
286     }
287 
288     pub fn getuid() -> Result<usize, SystemError> {
289         // todo: 增加credit功能之后,需要修改
290         return Ok(0);
291     }
292 
293     pub fn getgid() -> Result<usize, SystemError> {
294         // todo: 增加credit功能之后,需要修改
295         return Ok(0);
296     }
297 
298     pub fn geteuid() -> Result<usize, SystemError> {
299         // todo: 增加credit功能之后,需要修改
300         return Ok(0);
301     }
302 
303     pub fn getegid() -> Result<usize, SystemError> {
304         // todo: 增加credit功能之后,需要修改
305         return Ok(0);
306     }
307 
308     pub fn get_rusage(who: i32, rusage: *mut RUsage) -> Result<usize, SystemError> {
309         let who = RUsageWho::try_from(who)?;
310         let mut writer = UserBufferWriter::new(rusage, core::mem::size_of::<RUsage>(), true)?;
311         let pcb = ProcessManager::current_pcb();
312         let rusage = pcb.get_rusage(who).ok_or(SystemError::EINVAL)?;
313 
314         let ubuf = writer.buffer::<RUsage>(0).unwrap();
315         ubuf.copy_from_slice(&[rusage]);
316 
317         return Ok(0);
318     }
319 
320     /// # 设置资源限制
321     ///
322     /// TODO: 目前暂时不支持设置资源限制,只提供读取默认值的功能
323     ///
324     /// ## 参数
325     ///
326     /// - pid: 进程号
327     /// - resource: 资源类型
328     /// - new_limit: 新的资源限制
329     /// - old_limit: 旧的资源限制
330     ///
331     /// ## 返回值
332     ///
333     /// - 成功,0
334     /// - 如果old_limit不为NULL,则返回旧的资源限制到old_limit
335     ///
336     pub fn prlimit64(
337         _pid: Pid,
338         resource: usize,
339         _new_limit: *const RLimit64,
340         old_limit: *mut RLimit64,
341     ) -> Result<usize, SystemError> {
342         let resource = RLimitID::try_from(resource)?;
343         let mut writer = None;
344 
345         if !old_limit.is_null() {
346             writer = Some(UserBufferWriter::new(
347                 old_limit,
348                 core::mem::size_of::<RLimit64>(),
349                 true,
350             )?);
351         }
352 
353         match resource {
354             RLimitID::Stack => {
355                 if let Some(mut writer) = writer {
356                     let mut rlimit = writer.buffer::<RLimit64>(0).unwrap()[0];
357                     rlimit.rlim_cur = UserStack::DEFAULT_USER_STACK_SIZE as u64;
358                     rlimit.rlim_max = UserStack::DEFAULT_USER_STACK_SIZE as u64;
359                 }
360                 return Ok(0);
361             }
362 
363             RLimitID::Nofile => {
364                 if let Some(mut writer) = writer {
365                     let mut rlimit = writer.buffer::<RLimit64>(0).unwrap()[0];
366                     rlimit.rlim_cur = FileDescriptorVec::PROCESS_MAX_FD as u64;
367                     rlimit.rlim_max = FileDescriptorVec::PROCESS_MAX_FD as u64;
368                 }
369                 return Ok(0);
370             }
371 
372             RLimitID::As | RLimitID::Rss => {
373                 if let Some(mut writer) = writer {
374                     let mut rlimit = writer.buffer::<RLimit64>(0).unwrap()[0];
375                     rlimit.rlim_cur = MMArch::USER_END_VADDR.data() as u64;
376                     rlimit.rlim_max = MMArch::USER_END_VADDR.data() as u64;
377                 }
378                 return Ok(0);
379             }
380 
381             _ => {
382                 return Err(SystemError::ENOSYS);
383             }
384         }
385     }
386 
387     pub fn uname(name: *mut PosixOldUtsName) -> Result<usize, SystemError> {
388         let mut writer =
389             UserBufferWriter::new(name, core::mem::size_of::<PosixOldUtsName>(), true)?;
390         writer.copy_one_to_user(&PosixOldUtsName::new(), 0)?;
391 
392         return Ok(0);
393     }
394 }
395