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