sys_i386_32.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * This file contains various random system calls that
  3. * have a non-standard calling sequence on the Linux/i386
  4. * platform.
  5. */
  6. #include <linux/errno.h>
  7. #include <linux/sched.h>
  8. #include <linux/mm.h>
  9. #include <linux/fs.h>
  10. #include <linux/smp.h>
  11. #include <linux/sem.h>
  12. #include <linux/msg.h>
  13. #include <linux/shm.h>
  14. #include <linux/stat.h>
  15. #include <linux/syscalls.h>
  16. #include <linux/mman.h>
  17. #include <linux/file.h>
  18. #include <linux/utsname.h>
  19. #include <linux/ipc.h>
  20. #include <linux/uaccess.h>
  21. #include <linux/unistd.h>
  22. #include <asm/syscalls.h>
  23. /*
  24. * Perform the select(nd, in, out, ex, tv) and mmap() system
  25. * calls. Linux/i386 didn't use to be able to handle more than
  26. * 4 system call parameters, so these system calls used a memory
  27. * block for parameter passing..
  28. */
  29. struct mmap_arg_struct {
  30. unsigned long addr;
  31. unsigned long len;
  32. unsigned long prot;
  33. unsigned long flags;
  34. unsigned long fd;
  35. unsigned long offset;
  36. };
  37. asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
  38. {
  39. struct mmap_arg_struct a;
  40. int err = -EFAULT;
  41. if (copy_from_user(&a, arg, sizeof(a)))
  42. goto out;
  43. err = -EINVAL;
  44. if (a.offset & ~PAGE_MASK)
  45. goto out;
  46. err = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags,
  47. a.fd, a.offset >> PAGE_SHIFT);
  48. out:
  49. return err;
  50. }
  51. struct sel_arg_struct {
  52. unsigned long n;
  53. fd_set __user *inp, *outp, *exp;
  54. struct timeval __user *tvp;
  55. };
  56. asmlinkage int old_select(struct sel_arg_struct __user *arg)
  57. {
  58. struct sel_arg_struct a;
  59. if (copy_from_user(&a, arg, sizeof(a)))
  60. return -EFAULT;
  61. /* sys_select() does the appropriate kernel locking */
  62. return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
  63. }
  64. /*
  65. * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  66. *
  67. * This is really horribly ugly.
  68. */
  69. asmlinkage int sys_ipc(uint call, int first, int second,
  70. int third, void __user *ptr, long fifth)
  71. {
  72. int version, ret;
  73. version = call >> 16; /* hack for backward compatibility */
  74. call &= 0xffff;
  75. switch (call) {
  76. case SEMOP:
  77. return sys_semtimedop(first, (struct sembuf __user *)ptr, second, NULL);
  78. case SEMTIMEDOP:
  79. return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
  80. (const struct timespec __user *)fifth);
  81. case SEMGET:
  82. return sys_semget(first, second, third);
  83. case SEMCTL: {
  84. union semun fourth;
  85. if (!ptr)
  86. return -EINVAL;
  87. if (get_user(fourth.__pad, (void __user * __user *) ptr))
  88. return -EFAULT;
  89. return sys_semctl(first, second, third, fourth);
  90. }
  91. case MSGSND:
  92. return sys_msgsnd(first, (struct msgbuf __user *) ptr,
  93. second, third);
  94. case MSGRCV:
  95. switch (version) {
  96. case 0: {
  97. struct ipc_kludge tmp;
  98. if (!ptr)
  99. return -EINVAL;
  100. if (copy_from_user(&tmp,
  101. (struct ipc_kludge __user *) ptr,
  102. sizeof(tmp)))
  103. return -EFAULT;
  104. return sys_msgrcv(first, tmp.msgp, second,
  105. tmp.msgtyp, third);
  106. }
  107. default:
  108. return sys_msgrcv(first,
  109. (struct msgbuf __user *) ptr,
  110. second, fifth, third);
  111. }
  112. case MSGGET:
  113. return sys_msgget((key_t) first, second);
  114. case MSGCTL:
  115. return sys_msgctl(first, second, (struct msqid_ds __user *) ptr);
  116. case SHMAT:
  117. switch (version) {
  118. default: {
  119. ulong raddr;
  120. ret = do_shmat(first, (char __user *) ptr, second, &raddr);
  121. if (ret)
  122. return ret;
  123. return put_user(raddr, (ulong __user *) third);
  124. }
  125. case 1: /* iBCS2 emulator entry point */
  126. if (!segment_eq(get_fs(), get_ds()))
  127. return -EINVAL;
  128. /* The "(ulong *) third" is valid _only_ because of the kernel segment thing */
  129. return do_shmat(first, (char __user *) ptr, second, (ulong *) third);
  130. }
  131. case SHMDT:
  132. return sys_shmdt((char __user *)ptr);
  133. case SHMGET:
  134. return sys_shmget(first, second, third);
  135. case SHMCTL:
  136. return sys_shmctl(first, second,
  137. (struct shmid_ds __user *) ptr);
  138. default:
  139. return -ENOSYS;
  140. }
  141. }
  142. /*
  143. * Old cruft
  144. */
  145. asmlinkage int sys_uname(struct old_utsname __user *name)
  146. {
  147. int err;
  148. if (!name)
  149. return -EFAULT;
  150. down_read(&uts_sem);
  151. err = copy_to_user(name, utsname(), sizeof(*name));
  152. up_read(&uts_sem);
  153. return err? -EFAULT:0;
  154. }
  155. asmlinkage int sys_olduname(struct oldold_utsname __user *name)
  156. {
  157. int error;
  158. if (!name)
  159. return -EFAULT;
  160. if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
  161. return -EFAULT;
  162. down_read(&uts_sem);
  163. error = __copy_to_user(&name->sysname, &utsname()->sysname,
  164. __OLD_UTS_LEN);
  165. error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
  166. error |= __copy_to_user(&name->nodename, &utsname()->nodename,
  167. __OLD_UTS_LEN);
  168. error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
  169. error |= __copy_to_user(&name->release, &utsname()->release,
  170. __OLD_UTS_LEN);
  171. error |= __put_user(0, name->release + __OLD_UTS_LEN);
  172. error |= __copy_to_user(&name->version, &utsname()->version,
  173. __OLD_UTS_LEN);
  174. error |= __put_user(0, name->version + __OLD_UTS_LEN);
  175. error |= __copy_to_user(&name->machine, &utsname()->machine,
  176. __OLD_UTS_LEN);
  177. error |= __put_user(0, name->machine + __OLD_UTS_LEN);
  178. up_read(&uts_sem);
  179. error = error ? -EFAULT : 0;
  180. return error;
  181. }
  182. /*
  183. * Do a system call from kernel instead of calling sys_execve so we
  184. * end up with proper pt_regs.
  185. */
  186. int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  187. {
  188. long __res;
  189. asm volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx"
  190. : "=a" (__res)
  191. : "0" (__NR_execve), "ri" (filename), "c" (argv), "d" (envp) : "memory");
  192. return __res;
  193. }