sys_i386_32.c 6.1 KB

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