syscall.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2011-2018 K. Lange
  5. * Copyright (C) 2012 Markus Schober
  6. *
  7. * Syscall Tables
  8. *
  9. */
  10. #include <kernel/system.h>
  11. #include <kernel/process.h>
  12. #include <kernel/logging.h>
  13. #include <kernel/fs.h>
  14. #include <kernel/pipe.h>
  15. #include <kernel/version.h>
  16. #include <kernel/shm.h>
  17. #include <kernel/printf.h>
  18. #include <kernel/module.h>
  19. #include <sys/utsname.h>
  20. #include <syscall_nums.h>
  21. static char hostname[256];
  22. static size_t hostname_len = 0;
  23. #define FD_INRANGE(FD) \
  24. ((FD) < (int)current_process->fds->length && (FD) >= 0)
  25. #define FD_ENTRY(FD) \
  26. (current_process->fds->entries[(FD)])
  27. #define FD_CHECK(FD) \
  28. (FD_INRANGE(FD) && FD_ENTRY(FD))
  29. #define PTR_INRANGE(PTR) \
  30. ((uintptr_t)(PTR) > current_process->image.entry)
  31. #define PTR_VALIDATE(PTR) \
  32. ptr_validate((void *)(PTR), __func__)
  33. static void ptr_validate(void * ptr, const char * syscall) {
  34. if (ptr && !PTR_INRANGE(ptr)) {
  35. debug_print(ERROR, "SEGFAULT: invalid pointer passed to %s. (0x%x < 0x%x)",
  36. syscall, (uintptr_t)ptr, current_process->image.entry);
  37. HALT_AND_CATCH_FIRE("Segmentation fault", NULL);
  38. }
  39. }
  40. void validate(void * ptr) {
  41. ptr_validate(ptr, "syscall");
  42. }
  43. /*
  44. * Exit the current task.
  45. * DOES NOT RETURN!
  46. */
  47. static int __attribute__((noreturn)) sys_exit(int retval) {
  48. /* Deschedule the current task */
  49. task_exit(retval);
  50. for (;;) ;
  51. }
  52. static int sys_read(int fd, char * ptr, int len) {
  53. if (FD_CHECK(fd)) {
  54. PTR_VALIDATE(ptr);
  55. fs_node_t * node = FD_ENTRY(fd);
  56. uint32_t out = read_fs(node, node->offset, len, (uint8_t *)ptr);
  57. node->offset += out;
  58. return (int)out;
  59. }
  60. return -EBADF;
  61. }
  62. static int sys_ioctl(int fd, int request, void * argp) {
  63. if (FD_CHECK(fd)) {
  64. PTR_VALIDATE(argp);
  65. return ioctl_fs(FD_ENTRY(fd), request, argp);
  66. }
  67. return -EBADF;
  68. }
  69. static int sys_readdir(int fd, int index, struct dirent * entry) {
  70. if (FD_CHECK(fd)) {
  71. PTR_VALIDATE(entry);
  72. struct dirent * kentry = readdir_fs(FD_ENTRY(fd), (uint32_t)index);
  73. if (kentry) {
  74. memcpy(entry, kentry, sizeof *entry);
  75. free(kentry);
  76. return 1;
  77. } else {
  78. return 0;
  79. }
  80. }
  81. return -EBADF;
  82. }
  83. static int sys_write(int fd, char * ptr, int len) {
  84. if (FD_CHECK(fd)) {
  85. PTR_VALIDATE(ptr);
  86. fs_node_t * node = FD_ENTRY(fd);
  87. if (!has_permission(node, 02)) {
  88. debug_print(WARNING, "access denied (write, fd=%d)", fd);
  89. return -EACCES;
  90. }
  91. uint32_t out = write_fs(node, node->offset, len, (uint8_t *)ptr);
  92. node->offset += out;
  93. return out;
  94. }
  95. return -EBADF;
  96. }
  97. static int sys_waitpid(int pid, int * status, int options) {
  98. if (status && !PTR_INRANGE(status)) {
  99. return -EINVAL;
  100. }
  101. return waitpid(pid, status, options);
  102. }
  103. static int sys_open(const char * file, int flags, int mode) {
  104. PTR_VALIDATE(file);
  105. debug_print(NOTICE, "open(%s) flags=0x%x; mode=0x%x", file, flags, mode);
  106. fs_node_t * node = kopen((char *)file, flags);
  107. if (node && !has_permission(node, 04)) {
  108. debug_print(WARNING, "access denied (read, sys_open, file=%s)", file);
  109. close_fs(node);
  110. return -EACCES;
  111. }
  112. if (node && ((flags & O_RDWR) || (flags & O_APPEND) || (flags & O_WRONLY) || (flags & O_TRUNC))) {
  113. if (!has_permission(node, 02)) {
  114. debug_print(WARNING, "access denied (write, sys_open, file=%s)", file);
  115. close_fs(node);
  116. return -EACCES;
  117. }
  118. }
  119. if (!node && (flags & O_CREAT)) {
  120. /* TODO check directory permissions */
  121. debug_print(NOTICE, "- file does not exist and create was requested.");
  122. /* Um, make one */
  123. int result = create_file_fs((char *)file, mode);
  124. if (!result) {
  125. node = kopen((char *)file, flags);
  126. } else {
  127. return result;
  128. }
  129. }
  130. if (!node) {
  131. debug_print(NOTICE, "File does not exist; someone should be setting errno?");
  132. return -ENOENT;
  133. }
  134. if (flags & O_APPEND) {
  135. node->offset = node->length;
  136. } else {
  137. node->offset = 0;
  138. }
  139. int fd = process_append_fd((process_t *)current_process, node);
  140. debug_print(INFO, "[open] pid=%d %s -> %d", getpid(), file, fd);
  141. return fd;
  142. }
  143. static int sys_access(const char * file, int flags) {
  144. PTR_VALIDATE(file);
  145. debug_print(INFO, "access(%s, 0x%x) from pid=%d", file, flags, getpid());
  146. fs_node_t * node = kopen((char *)file, 0);
  147. if (!node) return -ENOENT;
  148. close_fs(node);
  149. return 0;
  150. }
  151. static int sys_close(int fd) {
  152. if (FD_CHECK(fd)) {
  153. close_fs(FD_ENTRY(fd));
  154. FD_ENTRY(fd) = NULL;
  155. return 0;
  156. }
  157. return -EBADF;
  158. }
  159. static int sys_sbrk(int size) {
  160. process_t * proc = (process_t *)current_process;
  161. if (proc->group != 0) {
  162. proc = process_from_pid(proc->group);
  163. }
  164. spin_lock(proc->image.lock);
  165. uintptr_t ret = proc->image.heap;
  166. uintptr_t i_ret = ret;
  167. ret = (ret + 0xfff) & ~0xfff; /* Rounds ret to 0x1000 in O(1) */
  168. proc->image.heap += (ret - i_ret) + size;
  169. while (proc->image.heap > proc->image.heap_actual) {
  170. proc->image.heap_actual += 0x1000;
  171. assert(proc->image.heap_actual % 0x1000 == 0);
  172. alloc_frame(get_page(proc->image.heap_actual, 1, current_directory), 0, 1);
  173. invalidate_tables_at(proc->image.heap_actual);
  174. }
  175. spin_unlock(proc->image.lock);
  176. return ret;
  177. }
  178. static int sys_getpid(void) {
  179. /* The user actually wants the pid of the originating thread (which can be us). */
  180. if (current_process->group) {
  181. return current_process->group;
  182. } else {
  183. /* We are the leader */
  184. return current_process->id;
  185. }
  186. }
  187. /* Actual getpid() */
  188. static int sys_gettid(void) {
  189. return getpid();
  190. }
  191. static int sys_execve(const char * filename, char *const argv[], char *const envp[]) {
  192. PTR_VALIDATE(argv);
  193. PTR_VALIDATE(filename);
  194. PTR_VALIDATE(envp);
  195. debug_print(NOTICE, "%d = exec(%s, ...)", current_process->id, filename);
  196. int argc = 0;
  197. int envc = 0;
  198. while (argv[argc]) {
  199. PTR_VALIDATE(argv[argc]);
  200. ++argc;
  201. }
  202. if (envp) {
  203. while (envp[envc]) {
  204. PTR_VALIDATE(envp[envc]);
  205. ++envc;
  206. }
  207. }
  208. debug_print(INFO, "Allocating space for arguments...");
  209. char ** argv_ = malloc(sizeof(char *) * (argc + 1));
  210. for (int j = 0; j < argc; ++j) {
  211. argv_[j] = malloc((strlen(argv[j]) + 1) * sizeof(char));
  212. memcpy(argv_[j], argv[j], strlen(argv[j]) + 1);
  213. }
  214. argv_[argc] = 0;
  215. char ** envp_;
  216. if (envp && envc) {
  217. envp_ = malloc(sizeof(char *) * (envc + 1));
  218. for (int j = 0; j < envc; ++j) {
  219. envp_[j] = malloc((strlen(envp[j]) + 1) * sizeof(char));
  220. memcpy(envp_[j], envp[j], strlen(envp[j]) + 1);
  221. }
  222. envp_[envc] = 0;
  223. } else {
  224. envp_ = malloc(sizeof(char *));
  225. envp_[0] = NULL;
  226. }
  227. debug_print(INFO,"Releasing all shmem regions...");
  228. shm_release_all((process_t *)current_process);
  229. current_process->cmdline = argv_;
  230. debug_print(INFO,"Executing...");
  231. /* Discard envp */
  232. return exec((char *)filename, argc, (char **)argv_, (char **)envp_);
  233. }
  234. static int sys_seek(int fd, int offset, int whence) {
  235. if (FD_CHECK(fd)) {
  236. if (fd < 3) {
  237. return 0;
  238. }
  239. switch (whence) {
  240. case 0:
  241. FD_ENTRY(fd)->offset = offset;
  242. break;
  243. case 1:
  244. FD_ENTRY(fd)->offset += offset;
  245. break;
  246. case 2:
  247. FD_ENTRY(fd)->offset = FD_ENTRY(fd)->length + offset;
  248. break;
  249. }
  250. return FD_ENTRY(fd)->offset;
  251. }
  252. return -EBADF;
  253. }
  254. static int stat_node(fs_node_t * fn, uintptr_t st) {
  255. struct stat * f = (struct stat *)st;
  256. PTR_VALIDATE(f);
  257. if (!fn) {
  258. memset(f, 0x00, sizeof(struct stat));
  259. debug_print(INFO, "stat: This file doesn't exist");
  260. return -1;
  261. }
  262. f->st_dev = (uint16_t)(((uint32_t)fn->device & 0xFFFF0) >> 8);
  263. f->st_ino = fn->inode;
  264. uint32_t flags = 0;
  265. if (fn->flags & FS_FILE) { flags |= _IFREG; }
  266. if (fn->flags & FS_DIRECTORY) { flags |= _IFDIR; }
  267. if (fn->flags & FS_CHARDEVICE) { flags |= _IFCHR; }
  268. if (fn->flags & FS_BLOCKDEVICE) { flags |= _IFBLK; }
  269. if (fn->flags & FS_PIPE) { flags |= _IFIFO; }
  270. if (fn->flags & FS_SYMLINK) { flags |= _IFLNK; }
  271. f->st_mode = fn->mask | flags;
  272. f->st_nlink = fn->nlink;
  273. f->st_uid = fn->uid;
  274. f->st_gid = fn->gid;
  275. f->st_rdev = 0;
  276. f->st_size = fn->length;
  277. f->st_atime = fn->atime;
  278. f->st_mtime = fn->mtime;
  279. f->st_ctime = fn->ctime;
  280. f->st_blksize = 512; /* whatever */
  281. if (fn->get_size) {
  282. f->st_size = fn->get_size(fn);
  283. }
  284. return 0;
  285. }
  286. static int sys_statf(char * file, uintptr_t st) {
  287. int result;
  288. PTR_VALIDATE(file);
  289. PTR_VALIDATE(st);
  290. fs_node_t * fn = kopen(file, 0);
  291. result = stat_node(fn, st);
  292. if (fn) {
  293. close_fs(fn);
  294. }
  295. return result;
  296. }
  297. static int sys_chmod(char * file, int mode) {
  298. int result;
  299. PTR_VALIDATE(file);
  300. fs_node_t * fn = kopen(file, 0);
  301. if (fn) {
  302. /* Can group members change bits? I think it's only owners. */
  303. if (current_process->user != 0 && current_process->user != fn->uid) {
  304. close_fs(fn);
  305. return -EPERM;
  306. }
  307. result = chmod_fs(fn, mode);
  308. close_fs(fn);
  309. return result;
  310. } else {
  311. return -ENOENT;
  312. }
  313. }
  314. static int sys_chown(char * file, int uid, int gid) {
  315. int result;
  316. PTR_VALIDATE(file);
  317. fs_node_t * fn = kopen(file, 0);
  318. if (fn) {
  319. /* TODO: Owners can change groups... */
  320. if (current_process->user != 0) {
  321. close_fs(fn);
  322. return -EPERM;
  323. }
  324. result = chown_fs(fn, uid, gid);
  325. close_fs(fn);
  326. return result;
  327. } else {
  328. return -ENOENT;
  329. }
  330. }
  331. static int sys_stat(int fd, uintptr_t st) {
  332. PTR_VALIDATE(st);
  333. if (FD_CHECK(fd)) {
  334. return stat_node(FD_ENTRY(fd), st);
  335. }
  336. return -EBADF;
  337. }
  338. static int sys_mkpipe(void) {
  339. fs_node_t * node = make_pipe(4096 * 2);
  340. open_fs(node, 0);
  341. return process_append_fd((process_t *)current_process, node);
  342. }
  343. static int sys_dup2(int old, int new) {
  344. return process_move_fd((process_t *)current_process, old, new);
  345. }
  346. static int sys_getuid(void) {
  347. return current_process->user;
  348. }
  349. static int sys_setuid(user_t new_uid) {
  350. if (current_process->user == USER_ROOT_UID) {
  351. current_process->user = new_uid;
  352. return 0;
  353. }
  354. return -EPERM;
  355. }
  356. static int sys_uname(struct utsname * name) {
  357. PTR_VALIDATE(name);
  358. char version_number[256];
  359. sprintf(version_number, __kernel_version_format,
  360. __kernel_version_major,
  361. __kernel_version_minor,
  362. __kernel_version_lower,
  363. __kernel_version_suffix);
  364. char version_string[256];
  365. sprintf(version_string, "%s %s %s",
  366. __kernel_version_codename,
  367. __kernel_build_date,
  368. __kernel_build_time);
  369. strcpy(name->sysname, __kernel_name);
  370. strcpy(name->nodename, hostname);
  371. strcpy(name->release, version_number);
  372. strcpy(name->version, version_string);
  373. strcpy(name->machine, __kernel_arch);
  374. strcpy(name->domainname, "");
  375. return 0;
  376. }
  377. static int sys_signal(uint32_t signum, uintptr_t handler) {
  378. if (signum > NUMSIGNALS) {
  379. return -EINVAL;
  380. }
  381. uintptr_t old = current_process->signals.functions[signum];
  382. current_process->signals.functions[signum] = handler;
  383. return (int)old;
  384. }
  385. /*
  386. static void inspect_memory (uintptr_t vaddr) {
  387. // Please use this scary hack of a function as infrequently as possible.
  388. shmem_debug_frame(vaddr);
  389. }
  390. */
  391. static int sys_reboot(void) {
  392. debug_print(NOTICE, "[kernel] Reboot requested from process %d by user #%d", current_process->id, current_process->user);
  393. if (current_process->user != USER_ROOT_UID) {
  394. return -EPERM;
  395. } else {
  396. debug_print(NOTICE, "[kernel] Good bye!");
  397. /* Goodbye, cruel world */
  398. IRQ_OFF;
  399. uint8_t out = 0x02;
  400. while ((out & 0x02) != 0) {
  401. out = inportb(0x64);
  402. }
  403. outportb(0x64, 0xFE); /* Reset */
  404. STOP;
  405. }
  406. return 0;
  407. }
  408. static int sys_chdir(char * newdir) {
  409. PTR_VALIDATE(newdir);
  410. char * path = canonicalize_path(current_process->wd_name, newdir);
  411. fs_node_t * chd = kopen(path, 0);
  412. if (chd) {
  413. if ((chd->flags & FS_DIRECTORY) == 0) {
  414. close_fs(chd);
  415. return -ENOTDIR;
  416. }
  417. close_fs(chd);
  418. free(current_process->wd_name);
  419. current_process->wd_name = malloc(strlen(path) + 1);
  420. memcpy(current_process->wd_name, path, strlen(path) + 1);
  421. return 0;
  422. } else {
  423. return -ENOENT;
  424. }
  425. }
  426. static int sys_getcwd(char * buf, size_t size) {
  427. if (buf) {
  428. PTR_VALIDATE(buf);
  429. size_t len = strlen(current_process->wd_name) + 1;
  430. return (int)memcpy(buf, current_process->wd_name, MIN(size, len));
  431. }
  432. return 0;
  433. }
  434. static int sys_sethostname(char * new_hostname) {
  435. if (current_process->user == USER_ROOT_UID) {
  436. PTR_VALIDATE(new_hostname);
  437. size_t len = strlen(new_hostname) + 1;
  438. if (len > 256) {
  439. return -ENAMETOOLONG;
  440. }
  441. hostname_len = len;
  442. memcpy(hostname, new_hostname, hostname_len);
  443. return 0;
  444. } else {
  445. return -EPERM;
  446. }
  447. }
  448. static int sys_gethostname(char * buffer) {
  449. PTR_VALIDATE(buffer);
  450. memcpy(buffer, hostname, hostname_len);
  451. return hostname_len;
  452. }
  453. extern int mkdir_fs(char *name, uint16_t permission);
  454. static int sys_mkdir(char * path, uint32_t mode) {
  455. return mkdir_fs(path, 0777);
  456. }
  457. /*
  458. * Yield the rest of the quantum;
  459. * useful for busy waiting and other such things
  460. */
  461. static int sys_yield(void) {
  462. switch_task(1);
  463. return 1;
  464. }
  465. /*
  466. * System Function
  467. */
  468. static int sys_sysfunc(int fn, char ** args) {
  469. /* System Functions are special debugging system calls */
  470. if (current_process->user == USER_ROOT_UID) {
  471. switch (fn) {
  472. case 3:
  473. debug_print(ERROR, "sync is currently unimplemented");
  474. //ext2_disk_sync();
  475. return 0;
  476. case 4:
  477. /* Request kernel output to file descriptor in arg0*/
  478. debug_print(NOTICE, "Setting output to file object in process %d's fd=%d!", getpid(), (int)args);
  479. debug_file = current_process->fds->entries[(int)args];
  480. break;
  481. case 5:
  482. {
  483. char *arg;
  484. PTR_VALIDATE(args);
  485. for (arg = args[0]; arg; arg++)
  486. PTR_VALIDATE(arg);
  487. debug_print(NOTICE, "Replacing process %d's file descriptors with pointers to %s", getpid(), (char *)args);
  488. fs_node_t * repdev = kopen((char *)args, 0);
  489. while (current_process->fds->length < 3) {
  490. process_append_fd((process_t *)current_process, repdev);
  491. }
  492. FD_ENTRY(0) = repdev;
  493. FD_ENTRY(1) = repdev;
  494. FD_ENTRY(2) = repdev;
  495. }
  496. break;
  497. case 6:
  498. debug_print(WARNING, "writing contents of file %s to sdb", args[0]);
  499. {
  500. PTR_VALIDATE(args);
  501. PTR_VALIDATE(args[0]);
  502. fs_node_t * file = kopen((char *)args[0], 0);
  503. if (!file) {
  504. return -EINVAL;
  505. }
  506. size_t length = file->length;
  507. uint8_t * buffer = malloc(length);
  508. read_fs(file, 0, length, (uint8_t *)buffer);
  509. close_fs(file);
  510. debug_print(WARNING, "Finished reading file, going to write it now.");
  511. fs_node_t * f = kopen("/dev/sdb", 0);
  512. if (!f) {
  513. return 1;
  514. }
  515. write_fs(f, 0, length, buffer);
  516. free(buffer);
  517. return 0;
  518. }
  519. case 7:
  520. debug_print(NOTICE, "Spawning debug hook as child of process %d.", getpid());
  521. if (debug_hook) {
  522. fs_node_t * tty = FD_ENTRY(0);
  523. return create_kernel_tasklet(debug_hook, "[kttydebug]", tty);
  524. } else {
  525. return -EINVAL;
  526. }
  527. case 8:
  528. debug_print(NOTICE, "Loading module %s.", args[0]);
  529. {
  530. /* Check file existence */
  531. fs_node_t * file = kopen(args[0], 0);
  532. if (!file) {
  533. return 1;
  534. }
  535. close_fs(file);
  536. module_data_t * mod_info = module_load(args[0]);
  537. if (!mod_info) {
  538. return 2;
  539. }
  540. return 0;
  541. }
  542. }
  543. }
  544. switch (fn) {
  545. /* The following functions are here to support the loader and are probably bad. */
  546. case 9:
  547. {
  548. process_t * proc = (process_t *)current_process;
  549. if (proc->group != 0) {
  550. proc = process_from_pid(proc->group);
  551. }
  552. spin_lock(proc->image.lock);
  553. /* Set new heap start */
  554. proc->image.heap = (uintptr_t)args[0];
  555. proc->image.heap_actual = proc->image.heap & 0xFFFFF000;
  556. assert(proc->image.heap_actual % 0x1000 == 0);
  557. alloc_frame(get_page(proc->image.heap_actual, 1, current_directory), 0, 1);
  558. invalidate_tables_at(proc->image.heap_actual);
  559. while (proc->image.heap > proc->image.heap_actual) {
  560. proc->image.heap_actual += 0x1000;
  561. alloc_frame(get_page(proc->image.heap_actual, 1, current_directory), 0, 1);
  562. invalidate_tables_at(proc->image.heap_actual);
  563. }
  564. spin_unlock(proc->image.lock);
  565. return 0;
  566. }
  567. case 10:
  568. {
  569. /* Load pages to fit region. */
  570. uintptr_t address = (uintptr_t)args[0];
  571. size_t size = (size_t)args[1];
  572. /* TODO: Other arguments for read/write? */
  573. if (address & 0xFFF) {
  574. size += address & 0xFFF;
  575. address &= 0xFFFFF000;
  576. }
  577. process_t * proc = (process_t *)current_process;
  578. if (proc->group != 0) {
  579. proc = process_from_pid(proc->group);
  580. }
  581. spin_lock(proc->image.lock);
  582. for (size_t x = 0; x < size; x += 0x1000) {
  583. alloc_frame(get_page(address + x, 1, current_directory), 0, 1);
  584. invalidate_tables_at(address + x);
  585. }
  586. spin_unlock(proc->image.lock);
  587. return 0;
  588. }
  589. case 11:
  590. {
  591. /* Set command line (meant for threads to set descriptions) */
  592. int count = 0;
  593. char **arg = args;
  594. PTR_VALIDATE(args);
  595. while (*arg) {
  596. PTR_VALIDATE(*args);
  597. count++;
  598. arg++;
  599. }
  600. /*
  601. * XXX We have a pretty obvious leak in storing command lines, since
  602. * we never free them! Unfortunately, at the moment, they are
  603. * shared between different processes, so until that gets fixed
  604. * we're going to be just as bad as the rest of the codebase and
  605. * just not free the previous value.
  606. */
  607. current_process->cmdline = malloc(sizeof(char*)*(count+1));
  608. int i = 0;
  609. while (i < count) {
  610. current_process->cmdline[i] = strdup(args[i]);
  611. i++;
  612. }
  613. current_process->cmdline[i] = NULL;
  614. return 0;
  615. }
  616. case 12:
  617. /*
  618. * Print a debug message to the kernel console
  619. * XXX: This probably should be a thing normal users can do.
  620. */
  621. PTR_VALIDATE(args);
  622. debug_print(WARNING, "0x%x 0x%x 0x%x 0x%x", args[0], args[1], args[2], args[3]);
  623. _debug_print(args[0], (uintptr_t)args[1], (uint32_t)args[2], args[3] ? args[3] : "(null)");
  624. return 0;
  625. break;
  626. case 13:
  627. /*
  628. * Set VGA text-mode cursor location
  629. * (Not actually used to place a cursor, we use this to move the cursor off screen)
  630. */
  631. PTR_VALIDATE(args);
  632. outportb(0x3D4, 14);
  633. outportb(0x3D5, (unsigned int)args[0]);
  634. outportb(0x3D4, 15);
  635. outportb(0x3D5, (unsigned int)args[1]);
  636. return 0;
  637. default:
  638. debug_print(ERROR, "Bad system function %d", fn);
  639. break;
  640. }
  641. return -EINVAL; /* Bad system function or access failure */
  642. }
  643. static int sys_sleepabs(unsigned long seconds, unsigned long subseconds) {
  644. /* Mark us as asleep until <some time period> */
  645. sleep_until((process_t *)current_process, seconds, subseconds);
  646. /* Switch without adding us to the queue */
  647. switch_task(0);
  648. if (seconds > timer_ticks || (seconds == timer_ticks && subseconds >= timer_subticks)) {
  649. return 0;
  650. } else {
  651. return 1;
  652. }
  653. }
  654. static int sys_sleep(unsigned long seconds, unsigned long subseconds) {
  655. unsigned long s, ss;
  656. relative_time(seconds, subseconds * 10, &s, &ss);
  657. return sys_sleepabs(s, ss);
  658. }
  659. static int sys_umask(int mode) {
  660. current_process->mask = mode & 0777;
  661. return 0;
  662. }
  663. static int sys_unlink(char * file) {
  664. PTR_VALIDATE(file);
  665. return unlink_fs(file);
  666. }
  667. static int sys_fork(void) {
  668. return (int)fork();
  669. }
  670. static int sys_clone(uintptr_t new_stack, uintptr_t thread_func, uintptr_t arg) {
  671. if (!new_stack || !PTR_INRANGE(new_stack)) return -EINVAL;
  672. if (!thread_func || !PTR_INRANGE(thread_func)) return -EINVAL;
  673. return (int)clone(new_stack, thread_func, arg);
  674. }
  675. static int sys_shm_obtain(char * path, size_t * size) {
  676. PTR_VALIDATE(path);
  677. PTR_VALIDATE(size);
  678. return (int)shm_obtain(path, size);
  679. }
  680. static int sys_shm_release(char * path) {
  681. PTR_VALIDATE(path);
  682. return shm_release(path);
  683. }
  684. static int sys_kill(pid_t process, uint32_t signal) {
  685. return send_signal(process, signal);
  686. }
  687. static int sys_gettimeofday(struct timeval * tv, void * tz) {
  688. PTR_VALIDATE(tv);
  689. PTR_VALIDATE(tz);
  690. return gettimeofday(tv, tz);
  691. }
  692. static int sys_openpty(int * master, int * slave, char * name, void * _ign0, void * size) {
  693. /* We require a place to put these when we are done. */
  694. if (!master || !slave) return -EINVAL;
  695. if (master && !PTR_INRANGE(master)) return -EINVAL;
  696. if (slave && !PTR_INRANGE(slave)) return -EINVAL;
  697. if (size && !PTR_INRANGE(size)) return -EINVAL;
  698. /* Create a new pseudo terminal */
  699. fs_node_t * fs_master;
  700. fs_node_t * fs_slave;
  701. pty_create(size, &fs_master, &fs_slave);
  702. /* Append the master and slave to the calling process */
  703. *master = process_append_fd((process_t *)current_process, fs_master);
  704. *slave = process_append_fd((process_t *)current_process, fs_slave);
  705. open_fs(fs_master, 0);
  706. open_fs(fs_slave, 0);
  707. /* Return success */
  708. return 0;
  709. }
  710. static int sys_pipe(int pipes[2]) {
  711. if (pipes && !PTR_INRANGE(pipes)) {
  712. return -EFAULT;
  713. }
  714. fs_node_t * outpipes[2];
  715. make_unix_pipe(outpipes);
  716. open_fs(outpipes[0], 0);
  717. open_fs(outpipes[1], 0);
  718. pipes[0] = process_append_fd((process_t *)current_process, outpipes[0]);
  719. pipes[1] = process_append_fd((process_t *)current_process, outpipes[1]);
  720. return 0;
  721. }
  722. static int sys_mount(char * arg, char * mountpoint, char * type, unsigned long flags, void * data) {
  723. /* TODO: Make use of flags and data from mount command. */
  724. (void)flags;
  725. (void)data;
  726. if (current_process->user != USER_ROOT_UID) {
  727. return -EPERM;
  728. }
  729. if (PTR_INRANGE(arg) && PTR_INRANGE(mountpoint) && PTR_INRANGE(type)) {
  730. return vfs_mount_type(type, arg, mountpoint);
  731. }
  732. return -EFAULT;
  733. }
  734. static int sys_symlink(char * target, char * name) {
  735. PTR_VALIDATE(target);
  736. PTR_VALIDATE(name);
  737. return symlink_fs(target, name);
  738. }
  739. static int sys_readlink(const char * file, char * ptr, int len) {
  740. PTR_VALIDATE(file);
  741. fs_node_t * node = kopen((char *) file, O_PATH | O_NOFOLLOW);
  742. if (!node) {
  743. return -ENOENT;
  744. }
  745. int rv = readlink_fs(node, ptr, len);
  746. close_fs(node);
  747. return rv;
  748. }
  749. static int sys_lstat(char * file, uintptr_t st) {
  750. int result;
  751. PTR_VALIDATE(file);
  752. PTR_VALIDATE(st);
  753. fs_node_t * fn = kopen(file, O_PATH | O_NOFOLLOW);
  754. result = stat_node(fn, st);
  755. if (fn) {
  756. close_fs(fn);
  757. }
  758. return result;
  759. }
  760. static int sys_fswait(int c, int fds[]) {
  761. PTR_VALIDATE(fds);
  762. for (int i = 0; i < c; ++i) {
  763. if (!FD_CHECK(fds[i])) return -EBADF;
  764. }
  765. fs_node_t ** nodes = malloc(sizeof(fs_node_t *)*(c+1));
  766. for (int i = 0; i < c; ++i) {
  767. nodes[i] = FD_ENTRY(fds[i]);
  768. }
  769. nodes[c] = NULL;
  770. int result = process_wait_nodes((process_t *)current_process, nodes, -1);
  771. free(nodes);
  772. return result;
  773. }
  774. static int sys_fswait_timeout(int c, int fds[], int timeout) {
  775. PTR_VALIDATE(fds);
  776. for (int i = 0; i < c; ++i) {
  777. if (!FD_CHECK(fds[i])) return -EBADF;
  778. }
  779. fs_node_t ** nodes = malloc(sizeof(fs_node_t *)*(c+1));
  780. for (int i = 0; i < c; ++i) {
  781. nodes[i] = FD_ENTRY(fds[i]);
  782. }
  783. nodes[c] = NULL;
  784. int result = process_wait_nodes((process_t *)current_process, nodes, timeout);
  785. free(nodes);
  786. return result;
  787. }
  788. /*
  789. * System Call Internals
  790. */
  791. static int (*syscalls[])() = {
  792. /* System Call Table */
  793. [SYS_EXT] = sys_exit,
  794. [SYS_OPEN] = sys_open,
  795. [SYS_READ] = sys_read,
  796. [SYS_WRITE] = sys_write,
  797. [SYS_CLOSE] = sys_close,
  798. [SYS_GETTIMEOFDAY] = sys_gettimeofday,
  799. [SYS_EXECVE] = sys_execve,
  800. [SYS_FORK] = sys_fork,
  801. [SYS_GETPID] = sys_getpid,
  802. [SYS_SBRK] = sys_sbrk,
  803. [SYS_UNAME] = sys_uname,
  804. [SYS_OPENPTY] = sys_openpty,
  805. [SYS_SEEK] = sys_seek,
  806. [SYS_STAT] = sys_stat,
  807. [SYS_MKPIPE] = sys_mkpipe,
  808. [SYS_DUP2] = sys_dup2,
  809. [SYS_GETUID] = sys_getuid,
  810. [SYS_SETUID] = sys_setuid,
  811. [SYS_REBOOT] = sys_reboot,
  812. [SYS_READDIR] = sys_readdir,
  813. [SYS_CHDIR] = sys_chdir,
  814. [SYS_GETCWD] = sys_getcwd,
  815. [SYS_CLONE] = sys_clone,
  816. [SYS_SETHOSTNAME] = sys_sethostname,
  817. [SYS_GETHOSTNAME] = sys_gethostname,
  818. [SYS_MKDIR] = sys_mkdir,
  819. [SYS_SHM_OBTAIN] = sys_shm_obtain,
  820. [SYS_SHM_RELEASE] = sys_shm_release,
  821. [SYS_KILL] = sys_kill,
  822. [SYS_SIGNAL] = sys_signal,
  823. [SYS_GETTID] = sys_gettid,
  824. [SYS_YIELD] = sys_yield,
  825. [SYS_SYSFUNC] = sys_sysfunc,
  826. [SYS_SLEEPABS] = sys_sleepabs,
  827. [SYS_SLEEP] = sys_sleep,
  828. [SYS_IOCTL] = sys_ioctl,
  829. [SYS_ACCESS] = sys_access,
  830. [SYS_STATF] = sys_statf,
  831. [SYS_CHMOD] = sys_chmod,
  832. [SYS_UMASK] = sys_umask,
  833. [SYS_UNLINK] = sys_unlink,
  834. [SYS_WAITPID] = sys_waitpid,
  835. [SYS_PIPE] = sys_pipe,
  836. [SYS_MOUNT] = sys_mount,
  837. [SYS_SYMLINK] = sys_symlink,
  838. [SYS_READLINK] = sys_readlink,
  839. [SYS_LSTAT] = sys_lstat,
  840. [SYS_FSWAIT] = sys_fswait,
  841. [SYS_FSWAIT2] = sys_fswait_timeout,
  842. [SYS_CHOWN] = sys_chown,
  843. };
  844. uint32_t num_syscalls = sizeof(syscalls) / sizeof(*syscalls);
  845. typedef uint32_t (*scall_func)(unsigned int, ...);
  846. pid_t trace_pid = 0;
  847. void syscall_handler(struct regs * r) {
  848. if (r->eax >= num_syscalls) {
  849. return;
  850. }
  851. uintptr_t location = (uintptr_t)syscalls[r->eax];
  852. if (!location) {
  853. return;
  854. }
  855. /* Update the syscall registers for this process */
  856. current_process->syscall_registers = r;
  857. if (trace_pid && current_process->id == trace_pid) {
  858. debug_print(WARNING, "[syscall trace] %d (0x%x) 0x%x 0x%x 0x%x 0x%x 0x%x", r->eax, location, r->ebx, r->ecx, r->edx, r->esi, r->edi);
  859. }
  860. /* Call the syscall function */
  861. scall_func func = (scall_func)location;
  862. uint32_t ret = func(r->ebx, r->ecx, r->edx, r->esi, r->edi);
  863. if ((current_process->syscall_registers == r) ||
  864. (location != (uintptr_t)&fork && location != (uintptr_t)&clone)) {
  865. r->eax = ret;
  866. }
  867. }
  868. void syscalls_install(void) {
  869. debug_print(NOTICE, "Initializing syscall table with %d functions", num_syscalls);
  870. isrs_install_handler(0x7F, &syscall_handler);
  871. }