procops.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. #include <string>
  2. #include <vector>
  3. #include <sys/prctl.h>
  4. #include <sys/utsname.h>
  5. #include <sys/wait.h>
  6. #include <types/elf.hpp>
  7. #include <kernel/async/lock.hpp>
  8. #include <kernel/log.hpp>
  9. #include <kernel/process.hpp>
  10. #include <kernel/signal.hpp>
  11. #include <kernel/syscall.hpp>
  12. #include <kernel/utsname.hpp>
  13. #include <kernel/vfs/dentry.hpp>
  14. using namespace kernel::syscall;
  15. #define NOT_IMPLEMENTED not_implemented(__FILE__, __LINE__)
  16. static inline void not_implemented(const char* pos, int line)
  17. {
  18. kmsgf("[kernel] the function at %s:%d is not implemented, killing the pid%d...",
  19. pos, line, current_process->pid);
  20. current_thread->send_signal(SIGSYS);
  21. }
  22. int kernel::syscall::do_chdir(const char __user* path)
  23. {
  24. // TODO: use copy_from_user
  25. auto [dir, ret] = fs::current_open(current_process->cwd, path);
  26. if (!dir || ret)
  27. return ret;
  28. if (!(dir->flags & fs::D_DIRECTORY))
  29. return -ENOTDIR;
  30. current_process->cwd = dir;
  31. return 0;
  32. }
  33. execve_retval kernel::syscall::do_execve(
  34. const std::string& exec,
  35. const std::vector<std::string>& args,
  36. const std::vector<std::string>& envs)
  37. {
  38. types::elf::elf32_load_data d{
  39. .exec_dent{},
  40. .argv{args},
  41. .envp{envs},
  42. .ip{}, .sp{},
  43. };
  44. if (1) {
  45. int ret;
  46. std::tie(d.exec_dent, ret) = fs::current_open(current_process->cwd, exec);
  47. if (!d.exec_dent || ret)
  48. return { 0, 0, ret };
  49. }
  50. current_process->files.onexec();
  51. async::preempt_disable();
  52. // TODO: set cs and ss to compatibility mode
  53. if (int ret = types::elf::elf32_load(d); ret != 0) {
  54. async::preempt_enable();
  55. if (ret == types::elf::ELF_LOAD_FAIL_NORETURN)
  56. kill_current(SIGSEGV);
  57. return { 0, 0, ret };
  58. }
  59. current_thread->signals.on_exec();
  60. async::preempt_enable();
  61. return { d.ip, d.sp, 0 };
  62. }
  63. int kernel::syscall::do_exit(int status)
  64. {
  65. // TODO: terminating a thread only
  66. assert(current_process->thds.size() == 1);
  67. // terminating a whole process:
  68. procs->kill(current_process->pid, (status & 0xff) << 8);
  69. // switch to new process and continue
  70. schedule_noreturn();
  71. }
  72. int kernel::syscall::do_waitpid(pid_t waitpid, int __user* arg1, int options)
  73. {
  74. if (waitpid != -1)
  75. return -EINVAL;
  76. auto& cv = current_process->waitlist;
  77. async::lock_guard lck(current_process->mtx_waitprocs);
  78. auto& waitlist = current_process->waitprocs;
  79. // TODO: check if it is waiting for stopped process
  80. if (options & ~(WNOHANG | WUNTRACED)) {
  81. NOT_IMPLEMENTED;
  82. return -EINVAL;
  83. }
  84. while (waitlist.empty()) {
  85. if (current_process->children.empty())
  86. return -ECHILD;
  87. if (options & WNOHANG)
  88. return 0;
  89. bool interrupted = cv.wait(current_process->mtx_waitprocs);
  90. if (interrupted)
  91. return -EINTR;
  92. }
  93. for (auto iter = waitlist.begin(); iter != waitlist.end(); ++iter) {
  94. if (WIFSTOPPED(iter->code) && !(options & WUNTRACED))
  95. continue;
  96. pid_t pid = iter->pid;
  97. // TODO: copy_to_user
  98. *arg1 = iter->code;
  99. procs->remove(pid);
  100. waitlist.erase(iter);
  101. return pid;
  102. }
  103. // we should never reach here
  104. freeze();
  105. return -EINVAL;
  106. }
  107. int kernel::syscall::do_getcwd(char __user* buf, size_t buf_size)
  108. {
  109. auto path = fs::d_path(current_process->cwd, current_process->fs_context.root);
  110. int len = std::min(buf_size-1, path.size());
  111. // TODO: use copy_to_user
  112. strncpy(buf, path.c_str(), len);
  113. buf[len] = 0;
  114. return len;
  115. }
  116. pid_t kernel::syscall::do_setsid()
  117. {
  118. if (current_process->pid == current_process->pgid)
  119. return -EPERM;
  120. current_process->sid = current_process->pid;
  121. current_process->pgid = current_process->pid;
  122. // TODO: get tty* from fd or block device id
  123. tty::console->set_pgrp(current_process->pid);
  124. current_process->control_tty = tty::console;
  125. return current_process->pid;
  126. }
  127. pid_t kernel::syscall::do_getsid(pid_t pid)
  128. {
  129. auto [ pproc, found ] = procs->try_find(pid);
  130. if (!found)
  131. return -ESRCH;
  132. if (pproc->sid != current_process->sid)
  133. return -EPERM;
  134. return pproc->sid;
  135. }
  136. int kernel::syscall::do_setpgid(pid_t pid, pid_t pgid)
  137. {
  138. if (pgid < 0)
  139. return -EINVAL;
  140. if (pid == 0)
  141. pid = current_process->pid;
  142. if (pgid == 0)
  143. pgid = pid;
  144. auto [ pproc, found ] = procs->try_find(pid);
  145. if (!found)
  146. return -ESRCH;
  147. // TODO: check whether pgid and the original
  148. // pgid is in the same session
  149. pproc->pgid = pgid;
  150. return 0;
  151. }
  152. int kernel::syscall::do_set_thread_area(kernel::user::user_desc __user* ptr)
  153. {
  154. auto ret = current_thread->set_thread_area(ptr);
  155. if (ret != 0)
  156. return ret;
  157. current_thread->load_thread_area32();
  158. return 0;
  159. }
  160. pid_t kernel::syscall::do_set_tid_address(int __user* tidptr)
  161. {
  162. // TODO: copy_from_user
  163. current_thread->set_child_tid = tidptr;
  164. return current_thread->tid();
  165. }
  166. int kernel::syscall::do_prctl(int option, uintptr_t arg2)
  167. {
  168. switch (option) {
  169. case PR_SET_NAME: {
  170. // TODO: copy_from_user
  171. auto* name = (const char __user*)arg2;
  172. current_thread->name.assign(name, 15);
  173. break;
  174. }
  175. case PR_GET_NAME: {
  176. auto* name = (char __user*)arg2;
  177. // TODO: copy_to_user
  178. strncpy(name, current_thread->name.c_str(), 16);
  179. name[15] = 0;
  180. break;
  181. }
  182. default:
  183. return -EINVAL;
  184. }
  185. return 0;
  186. }
  187. int kernel::syscall::do_arch_prctl(int option, uintptr_t arg2)
  188. {
  189. switch (option) {
  190. case PR_SET_NAME: {
  191. // TODO: copy_from_user
  192. auto* name = (const char __user*)arg2;
  193. current_thread->name.assign(name, 15);
  194. break;
  195. }
  196. case PR_GET_NAME: {
  197. auto* name = (char __user*)arg2;
  198. // TODO: copy_to_user
  199. strncpy(name, current_thread->name.c_str(), 16);
  200. name[15] = 0;
  201. break;
  202. }
  203. default:
  204. return -EINVAL;
  205. }
  206. return 0;
  207. }
  208. int kernel::syscall::do_umask(mode_t mask)
  209. {
  210. mode_t old = current_process->umask;
  211. current_process->umask = mask;
  212. return old;
  213. }
  214. int kernel::syscall::do_kill(pid_t pid, int sig)
  215. {
  216. auto [ pproc, found ] = procs->try_find(pid);
  217. if (!found)
  218. return -ESRCH;
  219. if (!kernel::signal_list::check_valid(sig))
  220. return -EINVAL;
  221. if (pproc->is_system())
  222. return 0;
  223. // TODO: check permission
  224. procs->send_signal(pid, sig);
  225. return 0;
  226. }
  227. int kernel::syscall::do_tkill(pid_t tid, int sig)
  228. {
  229. NOT_IMPLEMENTED;
  230. return -EINVAL;
  231. auto [ pproc, found ] = procs->try_find(tid);
  232. if (!found)
  233. return -ESRCH;
  234. if (!kernel::signal_list::check_valid(sig))
  235. return -EINVAL;
  236. if (pproc->is_system())
  237. return 0;
  238. // TODO: check permission
  239. procs->send_signal(tid, sig);
  240. return 0;
  241. }
  242. int kernel::syscall::do_rt_sigprocmask(int how, const sigmask_type __user* set,
  243. sigmask_type __user* oldset, size_t sigsetsize)
  244. {
  245. if (sigsetsize != sizeof(sigmask_type))
  246. return -EINVAL;
  247. sigmask_type sigs = current_thread->signals.get_mask();
  248. // TODO: use copy_to_user
  249. if (oldset)
  250. memcpy(oldset, &sigs, sizeof(sigmask_type));
  251. if (!set)
  252. return 0;
  253. // TODO: use copy_from_user
  254. switch (how) {
  255. case SIG_BLOCK:
  256. current_thread->signals.mask(*set);
  257. break;
  258. case SIG_UNBLOCK:
  259. current_thread->signals.unmask(*set);
  260. break;
  261. case SIG_SETMASK:
  262. current_thread->signals.set_mask(*set);
  263. break;
  264. }
  265. return 0;
  266. }
  267. int kernel::syscall::do_rt_sigaction(int signum, const sigaction __user* act,
  268. sigaction __user* oldact, size_t sigsetsize)
  269. {
  270. if (sigsetsize != sizeof(sigmask_type))
  271. return -EINVAL;
  272. if (!kernel::signal_list::check_valid(signum)
  273. || signum == SIGKILL || signum == SIGSTOP)
  274. return -EINVAL;
  275. // TODO: use copy_to_user
  276. if (oldact)
  277. current_thread->signals.get_handler(signum, *oldact);
  278. if (!act)
  279. return 0;
  280. // TODO: use copy_from_user
  281. current_thread->signals.set_handler(signum, *act);
  282. return 0;
  283. }
  284. int kernel::syscall::do_newuname(new_utsname __user* buf)
  285. {
  286. if (!buf)
  287. return -EFAULT;
  288. // TODO: use copy_to_user
  289. memcpy(buf, sys_utsname, sizeof(new_utsname));
  290. return 0;
  291. }
  292. pid_t kernel::syscall::do_getpgid(pid_t pid)
  293. {
  294. if (pid == 0)
  295. return current_process->pgid;
  296. auto [ pproc, found ] = procs->try_find(pid);
  297. if (!found)
  298. return -ESRCH;
  299. return pproc->pgid;
  300. }
  301. pid_t kernel::syscall::do_getpid()
  302. {
  303. return current_process->pid;
  304. }
  305. pid_t kernel::syscall::do_getppid()
  306. {
  307. return current_process->ppid;
  308. }
  309. uid_t kernel::syscall::do_getuid()
  310. {
  311. return 0; // all users are root for now
  312. }
  313. uid_t kernel::syscall::do_geteuid()
  314. {
  315. return 0; // all users are root for now
  316. }
  317. gid_t kernel::syscall::do_getgid()
  318. {
  319. return 0; // all users are root for now
  320. }
  321. pid_t kernel::syscall::do_gettid()
  322. {
  323. return current_thread->tid();
  324. }
  325. uintptr_t kernel::syscall::do_brk(uintptr_t addr)
  326. {
  327. return current_process->mms.set_brk(addr);
  328. }