linux32.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /*
  2. * Conversion between 32-bit and 64-bit native system calls.
  3. *
  4. * Copyright (C) 2000 Silicon Graphics, Inc.
  5. * Written by Ulf Carlsson (ulfc@engr.sgi.com)
  6. * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com)
  7. */
  8. #include <linux/compiler.h>
  9. #include <linux/mm.h>
  10. #include <linux/errno.h>
  11. #include <linux/file.h>
  12. #include <linux/smp_lock.h>
  13. #include <linux/highuid.h>
  14. #include <linux/resource.h>
  15. #include <linux/highmem.h>
  16. #include <linux/time.h>
  17. #include <linux/times.h>
  18. #include <linux/poll.h>
  19. #include <linux/slab.h>
  20. #include <linux/skbuff.h>
  21. #include <linux/filter.h>
  22. #include <linux/shm.h>
  23. #include <linux/sem.h>
  24. #include <linux/msg.h>
  25. #include <linux/icmpv6.h>
  26. #include <linux/syscalls.h>
  27. #include <linux/sysctl.h>
  28. #include <linux/utime.h>
  29. #include <linux/utsname.h>
  30. #include <linux/personality.h>
  31. #include <linux/dnotify.h>
  32. #include <linux/module.h>
  33. #include <linux/binfmts.h>
  34. #include <linux/security.h>
  35. #include <linux/compat.h>
  36. #include <linux/vfs.h>
  37. #include <linux/ipc.h>
  38. #include <net/sock.h>
  39. #include <net/scm.h>
  40. #include <asm/compat-signal.h>
  41. #include <asm/sim.h>
  42. #include <asm/uaccess.h>
  43. #include <asm/mmu_context.h>
  44. #include <asm/mman.h>
  45. /* Use this to get at 32-bit user passed pointers. */
  46. /* A() macro should be used for places where you e.g.
  47. have some internal variable u32 and just want to get
  48. rid of a compiler warning. AA() has to be used in
  49. places where you want to convert a function argument
  50. to 32bit pointer or when you e.g. access pt_regs
  51. structure and want to consider 32bit registers only.
  52. */
  53. #define A(__x) ((unsigned long)(__x))
  54. #define AA(__x) ((unsigned long)((int)__x))
  55. #ifdef __MIPSEB__
  56. #define merge_64(r1, r2) ((((r1) & 0xffffffffUL) << 32) + ((r2) & 0xffffffffUL))
  57. #endif
  58. #ifdef __MIPSEL__
  59. #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL))
  60. #endif
  61. SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len,
  62. unsigned long, prot, unsigned long, flags, unsigned long, fd,
  63. unsigned long, pgoff)
  64. {
  65. unsigned long error;
  66. error = -EINVAL;
  67. if (pgoff & (~PAGE_MASK >> 12))
  68. goto out;
  69. error = sys_mmap_pgoff(addr, len, prot, flags, fd,
  70. pgoff >> (PAGE_SHIFT-12));
  71. out:
  72. return error;
  73. }
  74. /*
  75. * sys_execve() executes a new program.
  76. */
  77. asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)
  78. {
  79. int error;
  80. char * filename;
  81. filename = getname(compat_ptr(regs.regs[4]));
  82. error = PTR_ERR(filename);
  83. if (IS_ERR(filename))
  84. goto out;
  85. error = compat_do_execve(filename, compat_ptr(regs.regs[5]),
  86. compat_ptr(regs.regs[6]), &regs);
  87. putname(filename);
  88. out:
  89. return error;
  90. }
  91. #define RLIM_INFINITY32 0x7fffffff
  92. #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
  93. struct rlimit32 {
  94. int rlim_cur;
  95. int rlim_max;
  96. };
  97. SYSCALL_DEFINE4(32_truncate64, const char __user *, path,
  98. unsigned long, __dummy, unsigned long, a2, unsigned long, a3)
  99. {
  100. return sys_truncate(path, merge_64(a2, a3));
  101. }
  102. SYSCALL_DEFINE4(32_ftruncate64, unsigned long, fd, unsigned long, __dummy,
  103. unsigned long, a2, unsigned long, a3)
  104. {
  105. return sys_ftruncate(fd, merge_64(a2, a3));
  106. }
  107. SYSCALL_DEFINE5(32_llseek, unsigned int, fd, unsigned int, offset_high,
  108. unsigned int, offset_low, loff_t __user *, result,
  109. unsigned int, origin)
  110. {
  111. return sys_llseek(fd, offset_high, offset_low, result, origin);
  112. }
  113. /* From the Single Unix Spec: pread & pwrite act like lseek to pos + op +
  114. lseek back to original location. They fail just like lseek does on
  115. non-seekable files. */
  116. SYSCALL_DEFINE6(32_pread, unsigned long, fd, char __user *, buf, size_t, count,
  117. unsigned long, unused, unsigned long, a4, unsigned long, a5)
  118. {
  119. return sys_pread64(fd, buf, count, merge_64(a4, a5));
  120. }
  121. SYSCALL_DEFINE6(32_pwrite, unsigned int, fd, const char __user *, buf,
  122. size_t, count, u32, unused, u64, a4, u64, a5)
  123. {
  124. return sys_pwrite64(fd, buf, count, merge_64(a4, a5));
  125. }
  126. SYSCALL_DEFINE2(32_sched_rr_get_interval, compat_pid_t, pid,
  127. struct compat_timespec __user *, interval)
  128. {
  129. struct timespec t;
  130. int ret;
  131. mm_segment_t old_fs = get_fs();
  132. set_fs(KERNEL_DS);
  133. ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
  134. set_fs(old_fs);
  135. if (put_user (t.tv_sec, &interval->tv_sec) ||
  136. __put_user(t.tv_nsec, &interval->tv_nsec))
  137. return -EFAULT;
  138. return ret;
  139. }
  140. #ifdef CONFIG_SYSVIPC
  141. SYSCALL_DEFINE6(32_ipc, u32, call, long, first, long, second, long, third,
  142. unsigned long, ptr, unsigned long, fifth)
  143. {
  144. int version, err;
  145. version = call >> 16; /* hack for backward compatibility */
  146. call &= 0xffff;
  147. switch (call) {
  148. case SEMOP:
  149. /* struct sembuf is the same on 32 and 64bit :)) */
  150. err = sys_semtimedop(first, compat_ptr(ptr), second, NULL);
  151. break;
  152. case SEMTIMEDOP:
  153. err = compat_sys_semtimedop(first, compat_ptr(ptr), second,
  154. compat_ptr(fifth));
  155. break;
  156. case SEMGET:
  157. err = sys_semget(first, second, third);
  158. break;
  159. case SEMCTL:
  160. err = compat_sys_semctl(first, second, third, compat_ptr(ptr));
  161. break;
  162. case MSGSND:
  163. err = compat_sys_msgsnd(first, second, third, compat_ptr(ptr));
  164. break;
  165. case MSGRCV:
  166. err = compat_sys_msgrcv(first, second, fifth, third,
  167. version, compat_ptr(ptr));
  168. break;
  169. case MSGGET:
  170. err = sys_msgget((key_t) first, second);
  171. break;
  172. case MSGCTL:
  173. err = compat_sys_msgctl(first, second, compat_ptr(ptr));
  174. break;
  175. case SHMAT:
  176. err = compat_sys_shmat(first, second, third, version,
  177. compat_ptr(ptr));
  178. break;
  179. case SHMDT:
  180. err = sys_shmdt(compat_ptr(ptr));
  181. break;
  182. case SHMGET:
  183. err = sys_shmget(first, (unsigned)second, third);
  184. break;
  185. case SHMCTL:
  186. err = compat_sys_shmctl(first, second, compat_ptr(ptr));
  187. break;
  188. default:
  189. err = -EINVAL;
  190. break;
  191. }
  192. return err;
  193. }
  194. #else
  195. SYSCALL_DEFINE6(32_ipc, u32, call, int, first, int, second, int, third,
  196. u32, ptr, u32, fifth)
  197. {
  198. return -ENOSYS;
  199. }
  200. #endif /* CONFIG_SYSVIPC */
  201. #ifdef CONFIG_MIPS32_N32
  202. SYSCALL_DEFINE4(n32_semctl, int, semid, int, semnum, int, cmd, u32, arg)
  203. {
  204. /* compat_sys_semctl expects a pointer to union semun */
  205. u32 __user *uptr = compat_alloc_user_space(sizeof(u32));
  206. if (put_user(arg, uptr))
  207. return -EFAULT;
  208. return compat_sys_semctl(semid, semnum, cmd, uptr);
  209. }
  210. SYSCALL_DEFINE4(n32_msgsnd, int, msqid, u32, msgp, unsigned int, msgsz,
  211. int, msgflg)
  212. {
  213. return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp));
  214. }
  215. SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
  216. int, msgtyp, int, msgflg)
  217. {
  218. return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64,
  219. compat_ptr(msgp));
  220. }
  221. #endif
  222. SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name)
  223. {
  224. int ret = 0;
  225. down_read(&uts_sem);
  226. if (copy_to_user(name, utsname(), sizeof *name))
  227. ret = -EFAULT;
  228. up_read(&uts_sem);
  229. if (current->personality == PER_LINUX32 && !ret)
  230. if (copy_to_user(name->machine, "mips\0\0\0", 8))
  231. ret = -EFAULT;
  232. return ret;
  233. }
  234. SYSCALL_DEFINE1(32_personality, unsigned long, personality)
  235. {
  236. int ret;
  237. personality &= 0xffffffff;
  238. if (personality(current->personality) == PER_LINUX32 &&
  239. personality == PER_LINUX)
  240. personality = PER_LINUX32;
  241. ret = sys_personality(personality);
  242. if (ret == PER_LINUX32)
  243. ret = PER_LINUX;
  244. return ret;
  245. }
  246. SYSCALL_DEFINE4(32_sendfile, long, out_fd, long, in_fd,
  247. compat_off_t __user *, offset, s32, count)
  248. {
  249. mm_segment_t old_fs = get_fs();
  250. int ret;
  251. off_t of;
  252. if (offset && get_user(of, offset))
  253. return -EFAULT;
  254. set_fs(KERNEL_DS);
  255. ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count);
  256. set_fs(old_fs);
  257. if (offset && put_user(of, offset))
  258. return -EFAULT;
  259. return ret;
  260. }
  261. asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
  262. size_t count)
  263. {
  264. return sys_readahead(fd, merge_64(a2, a3), count);
  265. }
  266. asmlinkage long sys32_sync_file_range(int fd, int __pad,
  267. unsigned long a2, unsigned long a3,
  268. unsigned long a4, unsigned long a5,
  269. int flags)
  270. {
  271. return sys_sync_file_range(fd,
  272. merge_64(a2, a3), merge_64(a4, a5),
  273. flags);
  274. }
  275. asmlinkage long sys32_fadvise64_64(int fd, int __pad,
  276. unsigned long a2, unsigned long a3,
  277. unsigned long a4, unsigned long a5,
  278. int flags)
  279. {
  280. return sys_fadvise64_64(fd,
  281. merge_64(a2, a3), merge_64(a4, a5),
  282. flags);
  283. }
  284. asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_a2,
  285. unsigned offset_a3, unsigned len_a4, unsigned len_a5)
  286. {
  287. return sys_fallocate(fd, mode, merge_64(offset_a2, offset_a3),
  288. merge_64(len_a4, len_a5));
  289. }
  290. save_static_function(sys32_clone);
  291. static int noinline __used
  292. _sys32_clone(nabi_no_regargs struct pt_regs regs)
  293. {
  294. unsigned long clone_flags;
  295. unsigned long newsp;
  296. int __user *parent_tidptr, *child_tidptr;
  297. clone_flags = regs.regs[4];
  298. newsp = regs.regs[5];
  299. if (!newsp)
  300. newsp = regs.regs[29];
  301. parent_tidptr = (int __user *) regs.regs[6];
  302. /* Use __dummy4 instead of getting it off the stack, so that
  303. syscall() works. */
  304. child_tidptr = (int __user *) __dummy4;
  305. return do_fork(clone_flags, newsp, &regs, 0,
  306. parent_tidptr, child_tidptr);
  307. }
  308. asmlinkage long sys32_lookup_dcookie(u32 a0, u32 a1, char __user *buf,
  309. size_t len)
  310. {
  311. return sys_lookup_dcookie(merge_64(a0, a1), buf, len);
  312. }