syscalls.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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/shm.h"
  7. #include "linux/ipc.h"
  8. #include "linux/syscalls.h"
  9. #include "asm/mman.h"
  10. #include "asm/uaccess.h"
  11. #include "asm/unistd.h"
  12. /*
  13. * Perform the select(nd, in, out, ex, tv) and mmap() system
  14. * calls. Linux/i386 didn't use to be able to handle more than
  15. * 4 system call parameters, so these system calls used a memory
  16. * block for parameter passing..
  17. */
  18. struct mmap_arg_struct {
  19. unsigned long addr;
  20. unsigned long len;
  21. unsigned long prot;
  22. unsigned long flags;
  23. unsigned long fd;
  24. unsigned long offset;
  25. };
  26. extern int old_mmap(unsigned long addr, unsigned long len,
  27. unsigned long prot, unsigned long flags,
  28. unsigned long fd, unsigned long offset);
  29. long old_mmap_i386(struct mmap_arg_struct __user *arg)
  30. {
  31. struct mmap_arg_struct a;
  32. int err = -EFAULT;
  33. if (copy_from_user(&a, arg, sizeof(a)))
  34. goto out;
  35. err = old_mmap(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
  36. out:
  37. return err;
  38. }
  39. struct sel_arg_struct {
  40. unsigned long n;
  41. fd_set __user *inp;
  42. fd_set __user *outp;
  43. fd_set __user *exp;
  44. struct timeval __user *tvp;
  45. };
  46. long old_select(struct sel_arg_struct __user *arg)
  47. {
  48. struct sel_arg_struct a;
  49. if (copy_from_user(&a, arg, sizeof(a)))
  50. return -EFAULT;
  51. /* sys_select() does the appropriate kernel locking */
  52. return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
  53. }
  54. /*
  55. * The prototype on i386 is:
  56. *
  57. * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
  58. *
  59. * and the "newtls" arg. on i386 is read by copy_thread directly from the
  60. * register saved on the stack.
  61. */
  62. long sys_clone(unsigned long clone_flags, unsigned long newsp,
  63. int __user *parent_tid, void *newtls, int __user *child_tid)
  64. {
  65. long ret;
  66. if (!newsp)
  67. newsp = UPT_SP(&current->thread.regs.regs);
  68. current->thread.forking = 1;
  69. ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
  70. child_tid);
  71. current->thread.forking = 0;
  72. return ret;
  73. }
  74. /*
  75. * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  76. *
  77. * This is really horribly ugly.
  78. */
  79. long sys_ipc (uint call, int first, int second,
  80. int third, void __user *ptr, long fifth)
  81. {
  82. int version, ret;
  83. version = call >> 16; /* hack for backward compatibility */
  84. call &= 0xffff;
  85. switch (call) {
  86. case SEMOP:
  87. return sys_semtimedop(first, (struct sembuf __user *) ptr,
  88. second, NULL);
  89. case SEMTIMEDOP:
  90. return sys_semtimedop(first, (struct sembuf __user *) ptr,
  91. second,
  92. (const struct timespec __user *) fifth);
  93. case SEMGET:
  94. return sys_semget (first, second, third);
  95. case SEMCTL: {
  96. union semun fourth;
  97. if (!ptr)
  98. return -EINVAL;
  99. if (get_user(fourth.__pad, (void __user * __user *) ptr))
  100. return -EFAULT;
  101. return sys_semctl (first, second, third, fourth);
  102. }
  103. case MSGSND:
  104. return sys_msgsnd (first, (struct msgbuf *) ptr,
  105. second, third);
  106. case MSGRCV:
  107. switch (version) {
  108. case 0: {
  109. struct ipc_kludge tmp;
  110. if (!ptr)
  111. return -EINVAL;
  112. if (copy_from_user(&tmp,
  113. (struct ipc_kludge *) ptr,
  114. sizeof (tmp)))
  115. return -EFAULT;
  116. return sys_msgrcv (first, tmp.msgp, second,
  117. tmp.msgtyp, third);
  118. }
  119. default:
  120. panic("msgrcv with version != 0");
  121. return sys_msgrcv (first,
  122. (struct msgbuf *) ptr,
  123. second, fifth, third);
  124. }
  125. case MSGGET:
  126. return sys_msgget ((key_t) first, second);
  127. case MSGCTL:
  128. return sys_msgctl (first, second, (struct msqid_ds *) ptr);
  129. case SHMAT:
  130. switch (version) {
  131. default: {
  132. ulong raddr;
  133. ret = do_shmat (first, (char *) ptr, second, &raddr);
  134. if (ret)
  135. return ret;
  136. return put_user (raddr, (ulong *) third);
  137. }
  138. case 1: /* iBCS2 emulator entry point */
  139. if (!segment_eq(get_fs(), get_ds()))
  140. return -EINVAL;
  141. return do_shmat (first, (char *) ptr, second, (ulong *) third);
  142. }
  143. case SHMDT:
  144. return sys_shmdt ((char *)ptr);
  145. case SHMGET:
  146. return sys_shmget (first, second, third);
  147. case SHMCTL:
  148. return sys_shmctl (first, second,
  149. (struct shmid_ds *) ptr);
  150. default:
  151. return -ENOSYS;
  152. }
  153. }
  154. long sys_sigaction(int sig, const struct old_sigaction __user *act,
  155. struct old_sigaction __user *oact)
  156. {
  157. struct k_sigaction new_ka, old_ka;
  158. int ret;
  159. if (act) {
  160. old_sigset_t mask;
  161. if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
  162. __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
  163. __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
  164. return -EFAULT;
  165. __get_user(new_ka.sa.sa_flags, &act->sa_flags);
  166. __get_user(mask, &act->sa_mask);
  167. siginitset(&new_ka.sa.sa_mask, mask);
  168. }
  169. ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
  170. if (!ret && oact) {
  171. if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
  172. __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
  173. __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
  174. return -EFAULT;
  175. __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
  176. __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
  177. }
  178. return ret;
  179. }