procops.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. use alloc::borrow::ToOwned;
  2. use alloc::ffi::CString;
  3. use arch::{ExtendedContext, InterruptContext};
  4. use bindings::{EINVAL, ENOENT, ENOTDIR, ERANGE, ESRCH};
  5. use bitflags::bitflags;
  6. use crate::elf::ParsedElf32;
  7. use crate::io::Buffer;
  8. use crate::kernel::constants::{
  9. ENOSYS, PR_GET_NAME, PR_SET_NAME, RLIMIT_STACK, SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK,
  10. };
  11. use crate::kernel::mem::{Page, PageBuffer, VAddr};
  12. use crate::kernel::task::{
  13. ProcessList, Scheduler, Signal, SignalAction, Thread, UserDescriptor, WaitObject, WaitType,
  14. };
  15. use crate::kernel::user::dataflow::UserString;
  16. use crate::kernel::user::{UserPointer, UserPointerMut};
  17. use crate::kernel::vfs::dentry::Dentry;
  18. use crate::path::Path;
  19. use crate::sync::{preempt, AsRefPosition as _};
  20. use crate::{kernel::user::dataflow::UserBuffer, prelude::*};
  21. use crate::kernel::vfs::{self, FsContext};
  22. use super::sysinfo::TimeVal;
  23. use super::{define_syscall32, register_syscall};
  24. fn do_umask(mask: u32) -> KResult<u32> {
  25. let context = FsContext::get_current();
  26. let mut umask = context.umask.lock();
  27. let old = *umask;
  28. *umask = mask & 0o777;
  29. Ok(old)
  30. }
  31. fn do_getcwd(buffer: *mut u8, bufsize: usize) -> KResult<usize> {
  32. let context = FsContext::get_current();
  33. let mut user_buffer = UserBuffer::new(buffer, bufsize)?;
  34. let page = Page::alloc_one();
  35. let mut buffer = PageBuffer::new(page.clone());
  36. context.cwd.lock().get_path(&context, &mut buffer)?;
  37. user_buffer.fill(page.as_slice())?.ok_or(ERANGE)?;
  38. Ok(buffer.wrote())
  39. }
  40. fn do_chdir(path: *const u8) -> KResult<()> {
  41. let context = FsContext::get_current();
  42. let path = UserString::new(path)?;
  43. let path = Path::new(path.as_cstr().to_bytes())?;
  44. let dentry = Dentry::open(&context, path, true)?;
  45. if !dentry.is_valid() {
  46. return Err(ENOENT);
  47. }
  48. if !dentry.is_directory() {
  49. return Err(ENOTDIR);
  50. }
  51. *context.cwd.lock() = dentry;
  52. Ok(())
  53. }
  54. fn do_mount(source: *const u8, target: *const u8, fstype: *const u8, flags: usize) -> KResult<()> {
  55. let source = UserString::new(source)?;
  56. let target = UserString::new(target)?;
  57. let fstype = UserString::new(fstype)?;
  58. let context = FsContext::get_current();
  59. let mountpoint = Dentry::open(&context, Path::new(target.as_cstr().to_bytes())?, true)?;
  60. if !mountpoint.is_valid() {
  61. return Err(ENOENT);
  62. }
  63. vfs::mount::do_mount(
  64. &mountpoint,
  65. source.as_cstr().to_str().map_err(|_| EINVAL)?,
  66. target.as_cstr().to_str().map_err(|_| EINVAL)?,
  67. fstype.as_cstr().to_str().map_err(|_| EINVAL)?,
  68. flags as u64,
  69. )
  70. }
  71. /// # Return
  72. /// `(entry_ip, sp)`
  73. fn do_execve(exec: &[u8], argv: Vec<CString>, envp: Vec<CString>) -> KResult<(VAddr, VAddr)> {
  74. let dentry = Dentry::open(&FsContext::get_current(), Path::new(exec)?, true)?;
  75. if !dentry.is_valid() {
  76. return Err(ENOENT);
  77. }
  78. // TODO: When `execve` is called by one of the threads in a process, the other threads
  79. // should be terminated and `execve` is performed in the thread group leader.
  80. let elf = ParsedElf32::parse(dentry.clone())?;
  81. let result = elf.load(argv, envp);
  82. if let Ok((ip, sp, mm_list)) = result {
  83. Thread::current().process.mm_list.replace(mm_list);
  84. Thread::current().files.on_exec();
  85. Thread::current().signal_list.clear_non_ignore();
  86. Thread::current().set_name(dentry.name().clone());
  87. Ok((ip, sp))
  88. } else {
  89. drop(dentry);
  90. // We can't hold any ownership when we call `kill_current`.
  91. ProcessList::kill_current(Signal::SIGSEGV);
  92. }
  93. }
  94. fn sys_execve(int_stack: &mut InterruptContext, _: &mut ExtendedContext) -> usize {
  95. match (|| -> KResult<()> {
  96. let exec = int_stack.rbx as *const u8;
  97. let exec = UserString::new(exec)?;
  98. // TODO!!!!!: copy from user
  99. let mut argv = UserPointer::<u32>::new_vaddr(int_stack.rcx as _)?;
  100. let mut envp = UserPointer::<u32>::new_vaddr(int_stack.rdx as _)?;
  101. let mut argv_vec = Vec::new();
  102. let mut envp_vec = Vec::new();
  103. loop {
  104. let arg = argv.read()?;
  105. if arg == 0 {
  106. break;
  107. }
  108. let arg = UserString::new(arg as *const u8)?;
  109. argv_vec.push(arg.as_cstr().to_owned());
  110. argv = argv.offset(1)?;
  111. }
  112. loop {
  113. let arg = envp.read()?;
  114. if arg == 0 {
  115. break;
  116. }
  117. let arg = UserString::new(arg as *const u8)?;
  118. envp_vec.push(arg.as_cstr().to_owned());
  119. envp = envp.offset(1)?;
  120. }
  121. let (ip, sp) = do_execve(exec.as_cstr().to_bytes(), argv_vec, envp_vec)?;
  122. int_stack.rip = ip.0 as u64;
  123. int_stack.rsp = sp.0 as u64;
  124. Ok(())
  125. })() {
  126. Ok(_) => 0,
  127. Err(err) => -(err as i32) as _,
  128. }
  129. }
  130. // TODO: Find a better way.
  131. #[allow(unreachable_code)]
  132. fn do_exit(status: u32) -> KResult<()> {
  133. {
  134. let mut procs = ProcessList::get().lock();
  135. procs.do_kill_process(&Thread::current().process, WaitType::Exited(status));
  136. }
  137. Scheduler::schedule_noreturn();
  138. panic!("schedule_noreturn returned!");
  139. }
  140. bitflags! {
  141. pub struct UserWaitOptions: u32 {
  142. const WNOHANG = 1;
  143. const WUNTRACED = 2;
  144. const WCONTINUED = 8;
  145. }
  146. }
  147. fn do_waitpid(waitpid: u32, arg1: *mut u32, options: u32) -> KResult<u32> {
  148. // if waitpid != u32::MAX {
  149. // unimplemented!("waitpid with pid {waitpid}")
  150. // }
  151. let options = match UserWaitOptions::from_bits(options) {
  152. None => unimplemented!("waitpid with options {options}"),
  153. Some(options) => options,
  154. };
  155. let wait_object = Thread::current().process.wait(
  156. options.contains(UserWaitOptions::WNOHANG),
  157. options.contains(UserWaitOptions::WUNTRACED),
  158. options.contains(UserWaitOptions::WCONTINUED),
  159. )?;
  160. match wait_object {
  161. None => Ok(0),
  162. Some(WaitObject { pid, code }) => {
  163. if !arg1.is_null() {
  164. UserPointerMut::new(arg1)?.write(code.to_wstatus())?;
  165. }
  166. Ok(pid)
  167. }
  168. }
  169. }
  170. fn do_wait4(waitpid: u32, arg1: *mut u32, options: u32, rusage: *mut ()) -> KResult<u32> {
  171. if rusage.is_null() {
  172. do_waitpid(waitpid, arg1, options)
  173. } else {
  174. unimplemented!("wait4 with rusage")
  175. }
  176. }
  177. fn do_setsid() -> KResult<u32> {
  178. Thread::current().process.setsid()
  179. }
  180. fn do_setpgid(pid: u32, pgid: i32) -> KResult<()> {
  181. let pid = if pid == 0 { Thread::current().process.pid } else { pid };
  182. let pgid = match pgid {
  183. 0 => pid,
  184. 1.. => pgid as u32,
  185. _ => return Err(EINVAL),
  186. };
  187. Thread::current().process.setpgid(pid, pgid)
  188. }
  189. fn do_getsid(pid: u32) -> KResult<u32> {
  190. if pid == 0 {
  191. Ok(Thread::current().process.session_rcu().sid)
  192. } else {
  193. let procs = ProcessList::get().lock_shared();
  194. procs
  195. .try_find_process(pid)
  196. .map(|proc| proc.session(procs.as_pos()).sid)
  197. .ok_or(ESRCH)
  198. }
  199. }
  200. fn do_getpgid(pid: u32) -> KResult<u32> {
  201. if pid == 0 {
  202. Ok(Thread::current().process.pgroup_rcu().pgid)
  203. } else {
  204. let procs = ProcessList::get().lock_shared();
  205. procs
  206. .try_find_process(pid)
  207. .map(|proc| proc.pgroup(procs.as_pos()).pgid)
  208. .ok_or(ESRCH)
  209. }
  210. }
  211. fn do_getpid() -> KResult<u32> {
  212. Ok(Thread::current().process.pid)
  213. }
  214. fn do_getppid() -> KResult<u32> {
  215. Ok(Thread::current().process.parent_rcu().map_or(0, |x| x.pid))
  216. }
  217. fn do_getuid() -> KResult<u32> {
  218. // All users are root for now.
  219. Ok(0)
  220. }
  221. fn do_geteuid() -> KResult<u32> {
  222. // All users are root for now.
  223. Ok(0)
  224. }
  225. fn do_getgid() -> KResult<u32> {
  226. // All users are root for now.
  227. Ok(0)
  228. }
  229. fn do_gettid() -> KResult<u32> {
  230. Ok(Thread::current().tid)
  231. }
  232. fn do_set_thread_area(desc: *mut UserDescriptor) -> KResult<()> {
  233. let desc_pointer = UserPointerMut::new(desc)?;
  234. let mut desc = desc_pointer.read()?;
  235. Thread::current().set_thread_area(&mut desc)?;
  236. desc_pointer.write(desc)?;
  237. // SAFETY: Preemption is disabled on calling `load_thread_area32()`.
  238. unsafe {
  239. preempt::disable();
  240. Thread::current().load_thread_area32();
  241. preempt::enable();
  242. }
  243. Ok(())
  244. }
  245. fn do_set_tid_address(tidptr: *mut u32) -> KResult<u32> {
  246. // TODO!!!: Implement this. We don't use it for now.
  247. let _tidptr = UserPointerMut::new(tidptr)?;
  248. Ok(Thread::current().tid)
  249. }
  250. fn do_prctl(option: u32, arg2: usize) -> KResult<()> {
  251. match option {
  252. PR_SET_NAME => {
  253. let name = UserPointer::new(arg2 as *mut [u8; 16])?.read()?;
  254. let len = name.iter().position(|&c| c == 0).unwrap_or(15);
  255. Thread::current().set_name(name[..len].into());
  256. Ok(())
  257. }
  258. PR_GET_NAME => {
  259. let name = Thread::current().get_name();
  260. let len = name.len().min(15);
  261. let name: [u8; 16] = core::array::from_fn(|i| if i < len { name[i] } else { 0 });
  262. UserPointerMut::new(arg2 as *mut [u8; 16])?.write(name)?;
  263. Ok(())
  264. }
  265. _ => Err(EINVAL),
  266. }
  267. }
  268. fn do_kill(pid: i32, sig: u32) -> KResult<()> {
  269. let procs = ProcessList::get().lock_shared();
  270. match pid {
  271. // Send signal to every process for which the calling process has
  272. // permission to send signals.
  273. -1 => unimplemented!("kill with pid -1"),
  274. // Send signal to every process in the process group.
  275. 0 => Thread::current()
  276. .process
  277. .pgroup(procs.as_pos())
  278. .raise(Signal::try_from(sig)?, procs.as_pos()),
  279. // Send signal to the process with the specified pid.
  280. 1.. => procs
  281. .try_find_process(pid as u32)
  282. .ok_or(ESRCH)?
  283. .raise(Signal::try_from(sig)?, procs.as_pos()),
  284. // Send signal to the process group with the specified pgid equals to `-pid`.
  285. ..-1 => procs
  286. .try_find_pgroup((-pid) as u32)
  287. .ok_or(ESRCH)?
  288. .raise(Signal::try_from(sig)?, procs.as_pos()),
  289. }
  290. Ok(())
  291. }
  292. fn do_tkill(tid: u32, sig: u32) -> KResult<()> {
  293. ProcessList::get()
  294. .lock_shared()
  295. .try_find_thread(tid)
  296. .ok_or(ESRCH)?
  297. .raise(Signal::try_from(sig)?);
  298. Ok(())
  299. }
  300. fn do_rt_sigprocmask(how: u32, set: *mut u64, oldset: *mut u64, sigsetsize: usize) -> KResult<()> {
  301. if sigsetsize != size_of::<u64>() {
  302. return Err(EINVAL);
  303. }
  304. let old_mask = Thread::current().signal_list.get_mask();
  305. if !oldset.is_null() {
  306. UserPointerMut::new(oldset)?.write(old_mask)?;
  307. }
  308. let new_mask = if !set.is_null() {
  309. UserPointer::new(set)?.read()?
  310. } else {
  311. return Ok(());
  312. };
  313. match how {
  314. SIG_BLOCK => Thread::current().signal_list.mask(new_mask),
  315. SIG_UNBLOCK => Thread::current().signal_list.unmask(new_mask),
  316. SIG_SETMASK => Thread::current().signal_list.set_mask(new_mask),
  317. _ => return Err(EINVAL),
  318. }
  319. Ok(())
  320. }
  321. #[repr(C, packed)]
  322. #[derive(Debug, Clone, Copy)]
  323. struct UserSignalAction {
  324. sa_handler: u32,
  325. sa_flags: u32,
  326. sa_restorer: u32,
  327. sa_mask: u64,
  328. }
  329. impl From<UserSignalAction> for SignalAction {
  330. fn from(from: UserSignalAction) -> SignalAction {
  331. SignalAction {
  332. sa_handler: from.sa_handler as usize,
  333. sa_flags: from.sa_flags as usize,
  334. sa_mask: from.sa_mask as usize,
  335. sa_restorer: from.sa_restorer as usize,
  336. }
  337. }
  338. }
  339. impl From<SignalAction> for UserSignalAction {
  340. fn from(from: SignalAction) -> UserSignalAction {
  341. UserSignalAction {
  342. sa_handler: from.sa_handler as u32,
  343. sa_flags: from.sa_flags as u32,
  344. sa_mask: from.sa_mask as u64,
  345. sa_restorer: from.sa_restorer as u32,
  346. }
  347. }
  348. }
  349. fn do_rt_sigaction(
  350. signum: u32,
  351. act: *const UserSignalAction,
  352. oldact: *mut UserSignalAction,
  353. sigsetsize: usize,
  354. ) -> KResult<()> {
  355. let signal = Signal::try_from(signum)?;
  356. if sigsetsize != size_of::<u64>() || signal.is_now() {
  357. return Err(EINVAL);
  358. }
  359. let old_action = Thread::current().signal_list.get_handler(signal);
  360. if !oldact.is_null() {
  361. UserPointerMut::new(oldact)?.write(old_action.into())?;
  362. }
  363. if !act.is_null() {
  364. let new_action = UserPointer::new(act)?.read()?;
  365. Thread::current()
  366. .signal_list
  367. .set_handler(signal, &new_action.into())?;
  368. }
  369. Ok(())
  370. }
  371. #[repr(C)]
  372. #[derive(Debug, Clone, Copy)]
  373. struct RLimit {
  374. rlim_cur: u64,
  375. rlim_max: u64,
  376. }
  377. fn do_prlimit64(
  378. pid: u32,
  379. resource: u32,
  380. new_limit: *const RLimit,
  381. old_limit: *mut RLimit,
  382. ) -> KResult<()> {
  383. if pid != 0 {
  384. return Err(ENOSYS);
  385. }
  386. match resource {
  387. RLIMIT_STACK => {
  388. if !old_limit.is_null() {
  389. let old_limit = UserPointerMut::new(old_limit)?;
  390. let rlimit = RLimit {
  391. rlim_cur: 8 * 1024 * 1024,
  392. rlim_max: 8 * 1024 * 1024,
  393. };
  394. old_limit.write(rlimit)?;
  395. }
  396. if !new_limit.is_null() {
  397. return Err(ENOSYS);
  398. }
  399. Ok(())
  400. }
  401. _ => Err(ENOSYS),
  402. }
  403. }
  404. fn do_getrlimit(resource: u32, rlimit: *mut RLimit) -> KResult<()> {
  405. do_prlimit64(0, resource, core::ptr::null(), rlimit)
  406. }
  407. #[repr(C)]
  408. #[derive(Clone, Copy)]
  409. struct RUsage {
  410. ru_utime: TimeVal,
  411. ru_stime: TimeVal,
  412. ru_maxrss: u32,
  413. ru_ixrss: u32,
  414. ru_idrss: u32,
  415. ru_isrss: u32,
  416. ru_minflt: u32,
  417. ru_majflt: u32,
  418. ru_nswap: u32,
  419. ru_inblock: u32,
  420. ru_oublock: u32,
  421. ru_msgsnd: u32,
  422. ru_msgrcv: u32,
  423. ru_nsignals: u32,
  424. ru_nvcsw: u32,
  425. ru_nivcsw: u32,
  426. }
  427. fn do_getrusage(who: u32, rusage: *mut RUsage) -> KResult<()> {
  428. if who != 0 {
  429. return Err(ENOSYS);
  430. }
  431. let rusage = UserPointerMut::new(rusage)?;
  432. rusage.write(RUsage {
  433. ru_utime: TimeVal::default(),
  434. ru_stime: TimeVal::default(),
  435. ru_maxrss: 0,
  436. ru_ixrss: 0,
  437. ru_idrss: 0,
  438. ru_isrss: 0,
  439. ru_minflt: 0,
  440. ru_majflt: 0,
  441. ru_nswap: 0,
  442. ru_inblock: 0,
  443. ru_oublock: 0,
  444. ru_msgsnd: 0,
  445. ru_msgrcv: 0,
  446. ru_nsignals: 0,
  447. ru_nvcsw: 0,
  448. ru_nivcsw: 0,
  449. })?;
  450. Ok(())
  451. }
  452. fn do_chmod(pathname: *const u8, mode: u32) -> KResult<()> {
  453. let context = FsContext::get_current();
  454. let path = UserString::new(pathname)?;
  455. let path = Path::new(path.as_cstr().to_bytes())?;
  456. let dentry = Dentry::open(&context, path, true)?;
  457. if !dentry.is_valid() {
  458. return Err(ENOENT);
  459. }
  460. dentry.chmod(mode)
  461. }
  462. define_syscall32!(sys_chdir, do_chdir, path: *const u8);
  463. define_syscall32!(sys_umask, do_umask, mask: u32);
  464. define_syscall32!(sys_getcwd, do_getcwd, buffer: *mut u8, bufsize: usize);
  465. define_syscall32!(sys_exit, do_exit, status: u32);
  466. define_syscall32!(sys_waitpid, do_waitpid, waitpid: u32, arg1: *mut u32, options: u32);
  467. define_syscall32!(sys_wait4, do_wait4, waitpid: u32, arg1: *mut u32, options: u32, rusage: *mut ());
  468. define_syscall32!(sys_setsid, do_setsid);
  469. define_syscall32!(sys_setpgid, do_setpgid, pid: u32, pgid: i32);
  470. define_syscall32!(sys_getsid, do_getsid, pid: u32);
  471. define_syscall32!(sys_getpgid, do_getpgid, pid: u32);
  472. define_syscall32!(sys_getpid, do_getpid);
  473. define_syscall32!(sys_getppid, do_getppid);
  474. define_syscall32!(sys_getuid, do_getuid);
  475. define_syscall32!(sys_geteuid, do_geteuid);
  476. define_syscall32!(sys_getgid, do_getgid);
  477. define_syscall32!(sys_gettid, do_gettid);
  478. define_syscall32!(sys_mount, do_mount,
  479. source: *const u8, target: *const u8,fstype: *const u8, flags: usize);
  480. define_syscall32!(sys_set_thread_area, do_set_thread_area, desc: *mut UserDescriptor);
  481. define_syscall32!(sys_set_tid_address, do_set_tid_address, tidptr: *mut u32);
  482. define_syscall32!(sys_prctl, do_prctl, option: u32, arg2: usize);
  483. define_syscall32!(sys_arch_prctl, do_prctl, option: u32, arg2: usize);
  484. define_syscall32!(sys_kill, do_kill, pid: i32, sig: u32);
  485. define_syscall32!(sys_tkill, do_tkill, tid: u32, sig: u32);
  486. define_syscall32!(sys_rt_sigprocmask, do_rt_sigprocmask,
  487. how: u32, set: *mut u64, oldset: *mut u64, sigsetsize: usize);
  488. define_syscall32!(sys_rt_sigaction, do_rt_sigaction,
  489. signum: u32, act: *const UserSignalAction, oldact: *mut UserSignalAction, sigsetsize: usize);
  490. define_syscall32!(sys_prlimit64, do_prlimit64,
  491. pid: u32, resource: u32, new_limit: *const RLimit, old_limit: *mut RLimit);
  492. define_syscall32!(sys_getrlimit, do_getrlimit, resource: u32, rlimit: *mut RLimit);
  493. define_syscall32!(sys_getrusage, do_getrusage, who: u32, rlimit: *mut RUsage);
  494. define_syscall32!(sys_chmod, do_chmod, pathname: *const u8, mode: u32);
  495. fn sys_vfork(int_stack: &mut InterruptContext, ext: &mut ExtendedContext) -> usize {
  496. sys_fork(int_stack, ext)
  497. }
  498. fn sys_fork(int_stack: &mut InterruptContext, _: &mut ExtendedContext) -> usize {
  499. let mut procs = ProcessList::get().lock();
  500. let new_thread = Thread::current().new_cloned(procs.as_mut());
  501. let mut new_int_stack = int_stack.clone();
  502. new_int_stack.rax = 0;
  503. new_int_stack.eflags = 0x200;
  504. new_thread.fork_init(new_int_stack);
  505. new_thread.uwake();
  506. new_thread.process.pid as usize
  507. }
  508. fn sys_sigreturn(int_stack: &mut InterruptContext, ext_ctx: &mut ExtendedContext) -> usize {
  509. let result = Thread::current().signal_list.restore(int_stack, ext_ctx);
  510. match result {
  511. Ok(ret) => ret,
  512. Err(_) => {
  513. println_warn!("`sigreturn` failed in thread {}!", Thread::current().tid);
  514. Thread::current().raise(Signal::SIGSEGV);
  515. 0
  516. }
  517. }
  518. }
  519. pub(super) fn register() {
  520. register_syscall!(0x01, exit);
  521. register_syscall!(0x02, fork);
  522. register_syscall!(0x07, waitpid);
  523. register_syscall!(0x0b, execve);
  524. register_syscall!(0x0c, chdir);
  525. register_syscall!(0x0f, chmod);
  526. register_syscall!(0x14, getpid);
  527. register_syscall!(0x15, mount);
  528. register_syscall!(0x25, kill);
  529. register_syscall!(0x2f, getgid);
  530. register_syscall!(0x39, setpgid);
  531. register_syscall!(0x3c, umask);
  532. register_syscall!(0x40, getppid);
  533. register_syscall!(0x42, setsid);
  534. register_syscall!(0x4d, getrusage);
  535. register_syscall!(0x72, wait4);
  536. register_syscall!(0x77, sigreturn);
  537. register_syscall!(0x84, getpgid);
  538. register_syscall!(0x93, getsid);
  539. register_syscall!(0xac, prctl);
  540. register_syscall!(0xae, rt_sigaction);
  541. register_syscall!(0xaf, rt_sigprocmask);
  542. register_syscall!(0xb7, getcwd);
  543. register_syscall!(0xbe, vfork);
  544. register_syscall!(0xbf, getrlimit);
  545. register_syscall!(0xc7, getuid);
  546. register_syscall!(0xc8, getgid);
  547. register_syscall!(0xc9, geteuid);
  548. register_syscall!(0xca, geteuid);
  549. register_syscall!(0xe0, gettid);
  550. register_syscall!(0xee, tkill);
  551. register_syscall!(0xf3, set_thread_area);
  552. register_syscall!(0xfc, exit);
  553. register_syscall!(0x102, set_tid_address);
  554. register_syscall!(0x154, prlimit64);
  555. register_syscall!(0x180, arch_prctl);
  556. }