syscall.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  3. * Licensed under the GPL
  4. */
  5. #include "linux/sched.h"
  6. #include "linux/file.h"
  7. #include "linux/smp_lock.h"
  8. #include "linux/mm.h"
  9. #include "linux/utsname.h"
  10. #include "linux/msg.h"
  11. #include "linux/shm.h"
  12. #include "linux/sys.h"
  13. #include "linux/syscalls.h"
  14. #include "linux/unistd.h"
  15. #include "linux/slab.h"
  16. #include "linux/utime.h"
  17. #include "asm/mman.h"
  18. #include "asm/uaccess.h"
  19. #include "kern_util.h"
  20. #include "user_util.h"
  21. #include "sysdep/syscalls.h"
  22. #include "mode_kern.h"
  23. #include "choose-mode.h"
  24. /* Unlocked, I don't care if this is a bit off */
  25. int nsyscalls = 0;
  26. long sys_fork(void)
  27. {
  28. long ret;
  29. current->thread.forking = 1;
  30. ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
  31. &current->thread.regs, 0, NULL, NULL);
  32. current->thread.forking = 0;
  33. return(ret);
  34. }
  35. long sys_vfork(void)
  36. {
  37. long ret;
  38. current->thread.forking = 1;
  39. ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
  40. UPT_SP(&current->thread.regs.regs),
  41. &current->thread.regs, 0, NULL, NULL);
  42. current->thread.forking = 0;
  43. return(ret);
  44. }
  45. /* common code for old and new mmaps */
  46. long sys_mmap2(unsigned long addr, unsigned long len,
  47. unsigned long prot, unsigned long flags,
  48. unsigned long fd, unsigned long pgoff)
  49. {
  50. long error = -EBADF;
  51. struct file * file = NULL;
  52. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  53. if (!(flags & MAP_ANONYMOUS)) {
  54. file = fget(fd);
  55. if (!file)
  56. goto out;
  57. }
  58. down_write(&current->mm->mmap_sem);
  59. error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  60. up_write(&current->mm->mmap_sem);
  61. if (file)
  62. fput(file);
  63. out:
  64. return error;
  65. }
  66. long old_mmap(unsigned long addr, unsigned long len,
  67. unsigned long prot, unsigned long flags,
  68. unsigned long fd, unsigned long offset)
  69. {
  70. long err = -EINVAL;
  71. if (offset & ~PAGE_MASK)
  72. goto out;
  73. err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
  74. out:
  75. return err;
  76. }
  77. /*
  78. * sys_pipe() is the normal C calling standard for creating
  79. * a pipe. It's not the way unix traditionally does this, though.
  80. */
  81. long sys_pipe(unsigned long __user * fildes)
  82. {
  83. int fd[2];
  84. long error;
  85. error = do_pipe(fd);
  86. if (!error) {
  87. if (copy_to_user(fildes, fd, sizeof(fd)))
  88. error = -EFAULT;
  89. }
  90. return error;
  91. }
  92. long sys_uname(struct old_utsname __user * name)
  93. {
  94. long err;
  95. if (!name)
  96. return -EFAULT;
  97. down_read(&uts_sem);
  98. err = copy_to_user(name, utsname(), sizeof (*name));
  99. up_read(&uts_sem);
  100. return err?-EFAULT:0;
  101. }
  102. long sys_olduname(struct oldold_utsname __user * name)
  103. {
  104. long error;
  105. if (!name)
  106. return -EFAULT;
  107. if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
  108. return -EFAULT;
  109. down_read(&uts_sem);
  110. error = __copy_to_user(&name->sysname, &utsname()->sysname,
  111. __OLD_UTS_LEN);
  112. error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
  113. error |= __copy_to_user(&name->nodename, &utsname()->nodename,
  114. __OLD_UTS_LEN);
  115. error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
  116. error |= __copy_to_user(&name->release, &utsname()->release,
  117. __OLD_UTS_LEN);
  118. error |= __put_user(0, name->release + __OLD_UTS_LEN);
  119. error |= __copy_to_user(&name->version, &utsname()->version,
  120. __OLD_UTS_LEN);
  121. error |= __put_user(0, name->version + __OLD_UTS_LEN);
  122. error |= __copy_to_user(&name->machine, &utsname()->machine,
  123. __OLD_UTS_LEN);
  124. error |= __put_user(0, name->machine + __OLD_UTS_LEN);
  125. up_read(&uts_sem);
  126. error = error ? -EFAULT : 0;
  127. return error;
  128. }
  129. int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  130. {
  131. mm_segment_t fs;
  132. int ret;
  133. fs = get_fs();
  134. set_fs(KERNEL_DS);
  135. ret = um_execve(filename, argv, envp);
  136. set_fs(fs);
  137. return ret;
  138. }