linux32.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:110k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  arch/s390x/kernel/linux32.c
  3.  *
  4.  *  S390 version
  5.  *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6.  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  7.  *               Gerhard Tonn (ton@de.ibm.com)   
  8.  *
  9.  *  Conversion between 31bit and 64bit native syscalls.
  10.  *
  11.  * Heavily inspired by the 32-bit Sparc compat code which is 
  12.  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  13.  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  14.  *
  15.  */
  16. #include <linux/config.h>
  17. #include <linux/kernel.h>
  18. #include <linux/sched.h>
  19. #include <linux/fs.h> 
  20. #include <linux/mm.h> 
  21. #include <linux/file.h> 
  22. #include <linux/signal.h>
  23. #include <linux/utime.h>
  24. #include <linux/resource.h>
  25. #include <linux/times.h>
  26. #include <linux/utsname.h>
  27. #include <linux/timex.h>
  28. #include <linux/smp.h>
  29. #include <linux/smp_lock.h>
  30. #include <linux/sem.h>
  31. #include <linux/msg.h>
  32. #include <linux/shm.h>
  33. #include <linux/slab.h>
  34. #include <linux/uio.h>
  35. #include <linux/nfs_fs.h>
  36. #include <linux/smb_fs.h>
  37. #include <linux/smb_mount.h>
  38. #include <linux/ncp_fs.h>
  39. #include <linux/quota.h>
  40. #include <linux/module.h>
  41. #include <linux/sunrpc/svc.h>
  42. #include <linux/nfsd/nfsd.h>
  43. #include <linux/nfsd/cache.h>
  44. #include <linux/nfsd/xdr.h>
  45. #include <linux/nfsd/syscall.h>
  46. #include <linux/poll.h>
  47. #include <linux/personality.h>
  48. #include <linux/stat.h>
  49. #include <linux/filter.h>
  50. #include <linux/highmem.h>
  51. #include <linux/highuid.h>
  52. #include <linux/mman.h>
  53. #include <linux/ipv6.h>
  54. #include <linux/in.h>
  55. #include <linux/icmpv6.h>
  56. #include <linux/sysctl.h>
  57. #include <asm/types.h>
  58. #include <asm/ipc.h>
  59. #include <asm/uaccess.h>
  60. #include <asm/semaphore.h>
  61. #include <net/scm.h>
  62. #include "linux32.h"
  63. extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
  64. extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
  65. extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
  66. extern asmlinkage long sys_setregid(gid_t, gid_t);
  67. extern asmlinkage long sys_setgid(gid_t);
  68. extern asmlinkage long sys_setreuid(uid_t, uid_t);
  69. extern asmlinkage long sys_setuid(uid_t);
  70. extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);
  71. extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);
  72. extern asmlinkage long sys_setfsuid(uid_t);
  73. extern asmlinkage long sys_setfsgid(gid_t);
  74.  
  75. /* For this source file, we want overflow handling. */
  76. #undef high2lowuid
  77. #undef high2lowgid
  78. #undef low2highuid
  79. #undef low2highgid
  80. #undef SET_UID16
  81. #undef SET_GID16
  82. #undef NEW_TO_OLD_UID
  83. #undef NEW_TO_OLD_GID
  84. #undef SET_OLDSTAT_UID
  85. #undef SET_OLDSTAT_GID
  86. #undef SET_STAT_UID
  87. #undef SET_STAT_GID
  88. #define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
  89. #define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
  90. #define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
  91. #define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
  92. #define SET_UID16(var, uid) var = high2lowuid(uid)
  93. #define SET_GID16(var, gid) var = high2lowgid(gid)
  94. #define NEW_TO_OLD_UID(uid) high2lowuid(uid)
  95. #define NEW_TO_OLD_GID(gid) high2lowgid(gid)
  96. #define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
  97. #define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
  98. #define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
  99. #define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
  100. asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
  101. {
  102. return sys_chown(filename, low2highuid(user), low2highgid(group));
  103. }
  104. asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
  105. {
  106. return sys_lchown(filename, low2highuid(user), low2highgid(group));
  107. }
  108. asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
  109. {
  110. return sys_fchown(fd, low2highuid(user), low2highgid(group));
  111. }
  112. asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
  113. {
  114. return sys_setregid(low2highgid(rgid), low2highgid(egid));
  115. }
  116. asmlinkage long sys32_setgid16(u16 gid)
  117. {
  118. return sys_setgid((gid_t)gid);
  119. }
  120. asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
  121. {
  122. return sys_setreuid(low2highuid(ruid), low2highuid(euid));
  123. }
  124. asmlinkage long sys32_setuid16(u16 uid)
  125. {
  126. return sys_setuid((uid_t)uid);
  127. }
  128. asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
  129. {
  130. return sys_setresuid(low2highuid(ruid), low2highuid(euid),
  131. low2highuid(suid));
  132. }
  133. asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid)
  134. {
  135. int retval;
  136. if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
  137.     !(retval = put_user(high2lowuid(current->euid), euid)))
  138. retval = put_user(high2lowuid(current->suid), suid);
  139. return retval;
  140. }
  141. asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
  142. {
  143. return sys_setresgid(low2highgid(rgid), low2highgid(egid),
  144. low2highgid(sgid));
  145. }
  146. asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid)
  147. {
  148. int retval;
  149. if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
  150.     !(retval = put_user(high2lowgid(current->egid), egid)))
  151. retval = put_user(high2lowgid(current->sgid), sgid);
  152. return retval;
  153. }
  154. asmlinkage long sys32_setfsuid16(u16 uid)
  155. {
  156. return sys_setfsuid((uid_t)uid);
  157. }
  158. asmlinkage long sys32_setfsgid16(u16 gid)
  159. {
  160. return sys_setfsgid((gid_t)gid);
  161. }
  162. asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
  163. {
  164. u16 groups[NGROUPS];
  165. int i,j;
  166. if (gidsetsize < 0)
  167. return -EINVAL;
  168. i = current->ngroups;
  169. if (gidsetsize) {
  170. if (i > gidsetsize)
  171. return -EINVAL;
  172. for(j=0;j<i;j++)
  173. groups[j] = current->groups[j];
  174. if (copy_to_user(grouplist, groups, sizeof(u16)*i))
  175. return -EFAULT;
  176. }
  177. return i;
  178. }
  179. asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
  180. {
  181. u16 groups[NGROUPS];
  182. int i;
  183. if (!capable(CAP_SETGID))
  184. return -EPERM;
  185. if ((unsigned) gidsetsize > NGROUPS)
  186. return -EINVAL;
  187. if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
  188. return -EFAULT;
  189. for (i = 0 ; i < gidsetsize ; i++)
  190. current->groups[i] = (gid_t)groups[i];
  191. current->ngroups = gidsetsize;
  192. return 0;
  193. }
  194. asmlinkage long sys32_getuid16(void)
  195. {
  196. return high2lowuid(current->uid);
  197. }
  198. asmlinkage long sys32_geteuid16(void)
  199. {
  200. return high2lowuid(current->euid);
  201. }
  202. asmlinkage long sys32_getgid16(void)
  203. {
  204. return high2lowgid(current->gid);
  205. }
  206. asmlinkage long sys32_getegid16(void)
  207. {
  208. return high2lowgid(current->egid);
  209. }
  210. /* 32-bit timeval and related flotsam.  */
  211. struct timeval32
  212. {
  213.     int tv_sec, tv_usec;
  214. };
  215. struct itimerval32
  216. {
  217.     struct timeval32 it_interval;
  218.     struct timeval32 it_value;
  219. };
  220. static inline long get_tv32(struct timeval *o, struct timeval32 *i)
  221. {
  222. return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||
  223. (__get_user(o->tv_sec, &i->tv_sec) |
  224.  __get_user(o->tv_usec, &i->tv_usec)));
  225. }
  226. static inline long put_tv32(struct timeval32 *o, struct timeval *i)
  227. {
  228. return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
  229. (__put_user(i->tv_sec, &o->tv_sec) |
  230.  __put_user(i->tv_usec, &o->tv_usec)));
  231. }
  232. static inline long get_it32(struct itimerval *o, struct itimerval32 *i)
  233. {
  234. return (!access_ok(VERIFY_READ, i32, sizeof(*i32)) ||
  235. (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
  236.  __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
  237.  __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
  238.  __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
  239. }
  240. static inline long put_it32(struct itimerval32 *o, struct itimerval *i)
  241. {
  242. return (!access_ok(VERIFY_WRITE, i32, sizeof(*i32)) ||
  243. (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
  244.  __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
  245.  __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
  246.  __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
  247. }
  248. struct msgbuf32 { s32 mtype; char mtext[1]; };
  249. struct ipc64_perm_ds32
  250. {
  251.         __kernel_key_t          key;
  252.         __kernel_uid32_t        uid;
  253.         __kernel_gid32_t        gid;
  254.         __kernel_uid32_t        cuid;
  255.         __kernel_gid32_t        cgid;
  256.         __kernel_mode_t32       mode;
  257.         unsigned short          __pad1;
  258.         unsigned short          seq;
  259.         unsigned short          __pad2;
  260.         unsigned int            __unused1;
  261.         unsigned int            __unused2;
  262. };
  263. struct ipc_perm32
  264. {
  265. key_t       key;
  266.         __kernel_uid_t32  uid;
  267.         __kernel_gid_t32  gid;
  268.         __kernel_uid_t32  cuid;
  269.         __kernel_gid_t32  cgid;
  270.         __kernel_mode_t32 mode;
  271.         unsigned short  seq;
  272. };
  273. struct semid_ds32 {
  274.         struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
  275.         __kernel_time_t32 sem_otime;              /* last semop time */
  276.         __kernel_time_t32 sem_ctime;              /* last change time */
  277.         u32 sem_base;              /* ptr to first semaphore in array */
  278.         u32 sem_pending;          /* pending operations to be processed */
  279.         u32 sem_pending_last;    /* last pending operation */
  280.         u32 undo;                  /* undo requests on this array */
  281.         unsigned short  sem_nsems;              /* no. of semaphores in array */
  282. };
  283. struct semid64_ds32 {
  284. struct ipc64_perm_ds32 sem_perm;
  285. unsigned int   __pad1;
  286. __kernel_time_t32 sem_otime;
  287. unsigned int   __pad2;
  288. __kernel_time_t32 sem_ctime;
  289. u32 sem_nsems;
  290. u32 __unused1;
  291. u32 __unused2;
  292. };
  293. struct msqid_ds32
  294. {
  295.         struct ipc_perm32 msg_perm;
  296.         u32 msg_first;
  297.         u32 msg_last;
  298.         __kernel_time_t32 msg_stime;
  299.         __kernel_time_t32 msg_rtime;
  300.         __kernel_time_t32 msg_ctime;
  301.         u32 wwait;
  302.         u32 rwait;
  303.         unsigned short msg_cbytes;
  304.         unsigned short msg_qnum;  
  305.         unsigned short msg_qbytes;
  306.         __kernel_ipc_pid_t32 msg_lspid;
  307.         __kernel_ipc_pid_t32 msg_lrpid;
  308. };
  309. struct msqid64_ds32 {
  310. struct ipc64_perm_ds32 msg_perm;
  311. unsigned int   __pad1;
  312. __kernel_time_t32 msg_stime;
  313. unsigned int   __pad2;
  314. __kernel_time_t32 msg_rtime;
  315. unsigned int   __pad3;
  316. __kernel_time_t32 msg_ctime;
  317. unsigned int  msg_cbytes;
  318. unsigned int  msg_qnum;
  319. unsigned int  msg_qbytes;
  320. __kernel_pid_t32 msg_lspid;
  321. __kernel_pid_t32 msg_lrpid;
  322. unsigned int  __unused1;
  323. unsigned int  __unused2;
  324. };
  325. struct shmid_ds32 {
  326. struct ipc_perm32       shm_perm;
  327. int                     shm_segsz;
  328. __kernel_time_t32       shm_atime;
  329. __kernel_time_t32       shm_dtime;
  330. __kernel_time_t32       shm_ctime;
  331. __kernel_ipc_pid_t32    shm_cpid; 
  332. __kernel_ipc_pid_t32    shm_lpid; 
  333. unsigned short          shm_nattch;
  334. };
  335. struct shmid64_ds32 {
  336. struct ipc64_perm_ds32 shm_perm;
  337. unsigned int __pad1;
  338. __kernel_time_t32 shm_atime;
  339. unsigned int __pad2;
  340. __kernel_time_t32 shm_dtime;
  341. unsigned int __pad3;
  342. __kernel_time_t32 shm_ctime;
  343. __kernel_size_t32 shm_segsz;
  344. __kernel_pid_t32 shm_cpid;
  345. __kernel_pid_t32 shm_lpid;
  346. unsigned int shm_nattch;
  347. unsigned int __unused1;
  348. unsigned int __unused2;
  349. };
  350.                                                         
  351. /*
  352.  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
  353.  *
  354.  * This is really horribly ugly.
  355.  */
  356. #define IPCOP_MASK(__x) (1UL << (__x))
  357. static int do_sys32_semctl(int first, int second, int third, void *uptr)
  358. {
  359. union semun fourth;
  360. u32 pad;
  361. int err = -EINVAL;
  362. if (!uptr)
  363. goto out;
  364. err = -EFAULT;
  365. if (get_user (pad, (u32 *)uptr))
  366. goto out;
  367. if(third == SETVAL)
  368. fourth.val = (int)pad;
  369. else
  370. fourth.__pad = (void *)A(pad);
  371. if (IPCOP_MASK (third) &
  372.     (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
  373.      IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
  374.      IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {
  375. err = sys_semctl (first, second, third, fourth);
  376. } else if (third & IPC_64) {
  377. struct semid64_ds s;
  378. struct semid64_ds32 *usp = (struct semid64_ds32 *)A(pad);
  379. mm_segment_t old_fs;
  380. int need_back_translation;
  381. if (third == (IPC_SET|IPC_64)) {
  382. err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
  383. err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
  384. err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
  385. if (err)
  386. goto out;
  387. fourth.__pad = &s;
  388. }
  389. need_back_translation =
  390. (IPCOP_MASK (third) &
  391.  (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
  392. if (need_back_translation)
  393. fourth.__pad = &s;
  394. old_fs = get_fs ();
  395. set_fs (KERNEL_DS);
  396. err = sys_semctl (first, second, third, fourth);
  397. set_fs (old_fs);
  398. if (need_back_translation) {
  399. int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
  400. err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
  401. err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
  402. err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
  403. err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
  404. err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
  405. err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
  406. err2 |= __put_user (s.sem_otime, &usp->sem_otime);
  407. err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
  408. err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
  409. if (err2) err = -EFAULT;
  410. }
  411. } else {
  412. struct semid_ds s;
  413. struct semid_ds32 *usp = (struct semid_ds32 *)A(pad);
  414. mm_segment_t old_fs;
  415. int need_back_translation;
  416. if (third == IPC_SET) {
  417. err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
  418. err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
  419. err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
  420. if (err)
  421. goto out;
  422. fourth.__pad = &s;
  423. }
  424. need_back_translation =
  425. (IPCOP_MASK (third) &
  426.  (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
  427. if (need_back_translation)
  428. fourth.__pad = &s;
  429. old_fs = get_fs ();
  430. set_fs (KERNEL_DS);
  431. err = sys_semctl (first, second, third, fourth);
  432. set_fs (old_fs);
  433. if (need_back_translation) {
  434. int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
  435. err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
  436. err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
  437. err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
  438. err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
  439. err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
  440. err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
  441. err2 |= __put_user (s.sem_otime, &usp->sem_otime);
  442. err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
  443. err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
  444. if (err2) err = -EFAULT;
  445. }
  446. }
  447. out:
  448. return err;
  449. }
  450. static int do_sys32_msgsnd (int first, int second, int third, void *uptr)
  451. {
  452. struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
  453. struct msgbuf32 *up = (struct msgbuf32 *)uptr;
  454. mm_segment_t old_fs;
  455. int err;
  456. if (!p)
  457. return -ENOMEM;
  458. err = get_user (p->mtype, &up->mtype);
  459. err |= __copy_from_user (p->mtext, &up->mtext, second);
  460. if (err)
  461. goto out;
  462. old_fs = get_fs ();
  463. set_fs (KERNEL_DS);
  464. err = sys_msgsnd (first, p, second, third);
  465. set_fs (old_fs);
  466. out:
  467. kfree (p);
  468. return err;
  469. }
  470. static int do_sys32_msgrcv (int first, int second, int msgtyp, int third,
  471.     int version, void *uptr)
  472. {
  473. struct msgbuf32 *up;
  474. struct msgbuf *p;
  475. mm_segment_t old_fs;
  476. int err;
  477. if (!version) {
  478. struct ipc_kludge_32 *uipck = (struct ipc_kludge_32 *)uptr;
  479. struct ipc_kludge_32 ipck;
  480. err = -EINVAL;
  481. if (!uptr)
  482. goto out;
  483. err = -EFAULT;
  484. if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge_32)))
  485. goto out;
  486. uptr = (void *)A(ipck.msgp);
  487. msgtyp = ipck.msgtyp;
  488. }
  489. err = -ENOMEM;
  490. p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
  491. if (!p)
  492. goto out;
  493. old_fs = get_fs ();
  494. set_fs (KERNEL_DS);
  495. err = sys_msgrcv (first, p, second + 4, msgtyp, third);
  496. set_fs (old_fs);
  497. if (err < 0)
  498. goto free_then_out;
  499. up = (struct msgbuf32 *)uptr;
  500. if (put_user (p->mtype, &up->mtype) ||
  501.     __copy_to_user (&up->mtext, p->mtext, err))
  502. err = -EFAULT;
  503. free_then_out:
  504. kfree (p);
  505. out:
  506. return err;
  507. }
  508. static int do_sys32_msgctl (int first, int second, void *uptr)
  509. {
  510. int err;
  511. if (IPCOP_MASK (second) &
  512.     (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
  513.      IPCOP_MASK (IPC_RMID))) {
  514. err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
  515. } else if (second & IPC_64) {
  516. struct msqid64_ds m;
  517. struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr;
  518. mm_segment_t old_fs;
  519. if (second == (IPC_SET|IPC_64)) {
  520. err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
  521. err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
  522. err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
  523. err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
  524. if (err)
  525. goto out;
  526. }
  527. old_fs = get_fs ();
  528. set_fs (KERNEL_DS);
  529. err = sys_msgctl (first, second, (struct msqid_ds *)&m);
  530. set_fs (old_fs);
  531. if (IPCOP_MASK (second) &
  532.     (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
  533. int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
  534. err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
  535. err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
  536. err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
  537. err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
  538. err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
  539. err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
  540. err2 |= __put_user (m.msg_stime, &up->msg_stime);
  541. err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
  542. err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
  543. err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
  544. err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
  545. err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
  546. err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
  547. err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
  548. if (err2)
  549. err = -EFAULT;
  550. }
  551. } else {
  552. struct msqid_ds m;
  553. struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
  554. mm_segment_t old_fs;
  555. if (second == IPC_SET) {
  556. err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
  557. err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
  558. err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
  559. err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
  560. if (err)
  561. goto out;
  562. }
  563. old_fs = get_fs ();
  564. set_fs (KERNEL_DS);
  565. err = sys_msgctl (first, second, &m);
  566. set_fs (old_fs);
  567. if (IPCOP_MASK (second) &
  568.     (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
  569. int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
  570. err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
  571. err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
  572. err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
  573. err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
  574. err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
  575. err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
  576. err2 |= __put_user (m.msg_stime, &up->msg_stime);
  577. err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
  578. err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
  579. err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
  580. err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
  581. err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
  582. err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
  583. err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
  584. if (err2)
  585. err = -EFAULT;
  586. }
  587. }
  588. out:
  589. return err;
  590. }
  591. static int do_sys32_shmat (int first, int second, int third, int version, void *uptr)
  592. {
  593. unsigned long raddr;
  594. u32 *uaddr = (u32 *)A((u32)third);
  595. int err = -EINVAL;
  596. if (version == 1)
  597. goto out;
  598. err = sys_shmat (first, uptr, second, &raddr);
  599. if (err)
  600. goto out;
  601. err = put_user (raddr, uaddr);
  602. out:
  603. return err;
  604. }
  605. static int do_sys32_shmctl (int first, int second, void *uptr)
  606. {
  607. int err;
  608. if (IPCOP_MASK (second) &
  609.     (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) |
  610.      IPCOP_MASK (IPC_RMID))) {
  611. if (second == (IPC_INFO|IPC_64))
  612. second = IPC_INFO; /* So that we don't have to translate it */
  613. err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
  614. } else if ((second & IPC_64) && second != (SHM_INFO|IPC_64)) {
  615. struct shmid64_ds s;
  616. struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr;
  617. mm_segment_t old_fs;
  618. if (second == (IPC_SET|IPC_64)) {
  619. err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
  620. err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
  621. err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
  622. if (err)
  623. goto out;
  624. }
  625. old_fs = get_fs ();
  626. set_fs (KERNEL_DS);
  627. err = sys_shmctl (first, second, (struct shmid_ds *)&s);
  628. set_fs (old_fs);
  629. if (err < 0)
  630. goto out;
  631. /* Mask it even in this case so it becomes a CSE. */
  632. if (IPCOP_MASK (second) &
  633.     (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
  634. int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
  635. err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
  636. err2 |= __put_user (high2lowgid(s.shm_perm.gid), &up->shm_perm.gid);
  637. err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
  638. err2 |= __put_user (high2lowgid(s.shm_perm.cgid), &up->shm_perm.cgid);
  639. err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
  640. err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
  641. err2 |= __put_user (s.shm_atime, &up->shm_atime);
  642. err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
  643. err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
  644. err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
  645. err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
  646. err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
  647. err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
  648. if (err2)
  649. err = -EFAULT;
  650. }
  651. } else {
  652. struct shmid_ds s;
  653. struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
  654. mm_segment_t old_fs;
  655. second &= ~IPC_64;
  656. if (second == IPC_SET) {
  657. err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
  658. err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
  659. err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
  660. if (err)
  661. goto out;
  662. }
  663. old_fs = get_fs ();
  664. set_fs (KERNEL_DS);
  665. err = sys_shmctl (first, second, &s);
  666. set_fs (old_fs);
  667. if (err < 0)
  668. goto out;
  669. /* Mask it even in this case so it becomes a CSE. */
  670. if (second == SHM_INFO) {
  671. struct shm_info32 {
  672. int used_ids;
  673. u32 shm_tot, shm_rss, shm_swp;
  674. u32 swap_attempts, swap_successes;
  675. } *uip = (struct shm_info32 *)uptr;
  676. struct shm_info *kp = (struct shm_info *)&s;
  677. int err2 = put_user (kp->used_ids, &uip->used_ids);
  678. err2 |= __put_user (kp->shm_tot, &uip->shm_tot);
  679. err2 |= __put_user (kp->shm_rss, &uip->shm_rss);
  680. err2 |= __put_user (kp->shm_swp, &uip->shm_swp);
  681. err2 |= __put_user (kp->swap_attempts, &uip->swap_attempts);
  682. err2 |= __put_user (kp->swap_successes, &uip->swap_successes);
  683. if (err2)
  684. err = -EFAULT;
  685. } else if (IPCOP_MASK (second) &
  686.    (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
  687. int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
  688. err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
  689. err2 |= __put_user (high2lowgid(s.shm_perm.gid), &up->shm_perm.gid);
  690. err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
  691. err2 |= __put_user (high2lowgid(s.shm_perm.cgid), &up->shm_perm.cgid);
  692. err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
  693. err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
  694. err2 |= __put_user (s.shm_atime, &up->shm_atime);
  695. err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
  696. err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
  697. err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
  698. err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
  699. err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
  700. err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
  701. if (err2)
  702. err = -EFAULT;
  703. }
  704. }
  705. out:
  706. return err;
  707. }
  708. asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
  709. {
  710. int version, err;
  711. version = call >> 16; /* hack for backward compatibility */
  712. call &= 0xffff;
  713. if(version)
  714. return -EINVAL;
  715. if (call <= SEMCTL)
  716. switch (call) {
  717. case SEMOP:
  718. /* struct sembuf is the same on 32 and 64bit :)) */
  719. err = sys_semop (first, (struct sembuf *)AA(ptr), second);
  720. goto out;
  721. case SEMGET:
  722. err = sys_semget (first, second, third);
  723. goto out;
  724. case SEMCTL:
  725. err = do_sys32_semctl (first, second, third, (void *)AA(ptr));
  726. goto out;
  727. default:
  728. err = -EINVAL;
  729. goto out;
  730. };
  731. if (call <= MSGCTL) 
  732. switch (call) {
  733. case MSGSND:
  734. err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr));
  735. goto out;
  736. case MSGRCV:
  737. err = do_sys32_msgrcv (first, second, 0, third,
  738.        version, (void *)AA(ptr));
  739. goto out;
  740. case MSGGET:
  741. err = sys_msgget ((key_t) first, second);
  742. goto out;
  743. case MSGCTL:
  744. err = do_sys32_msgctl (first, second, (void *)AA(ptr));
  745. goto out;
  746. default:
  747. err = -EINVAL;
  748. goto out;
  749. }
  750. if (call <= SHMCTL) 
  751. switch (call) {
  752. case SHMAT:
  753. err = do_sys32_shmat (first, second, third,
  754.       version, (void *)AA(ptr));
  755. goto out;
  756. case SHMDT: 
  757. err = sys_shmdt ((char *)AA(ptr));
  758. goto out;
  759. case SHMGET:
  760. err = sys_shmget (first, second, third);
  761. goto out;
  762. case SHMCTL:
  763. err = do_sys32_shmctl (first, second, (void *)AA(ptr));
  764. goto out;
  765. default:
  766. err = -EINVAL;
  767. goto out;
  768. }
  769. err = -EINVAL;
  770. out:
  771. return err;
  772. }
  773. static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
  774. {
  775. int err;
  776. err = get_user(kfl->l_type, &ufl->l_type);
  777. err |= __get_user(kfl->l_whence, &ufl->l_whence);
  778. err |= __get_user(kfl->l_start, &ufl->l_start);
  779. err |= __get_user(kfl->l_len, &ufl->l_len);
  780. err |= __get_user(kfl->l_pid, &ufl->l_pid);
  781. return err;
  782. }
  783. static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
  784. {
  785. int err;
  786. err = __put_user(kfl->l_type, &ufl->l_type);
  787. err |= __put_user(kfl->l_whence, &ufl->l_whence);
  788. err |= __put_user(kfl->l_start, &ufl->l_start);
  789. err |= __put_user(kfl->l_len, &ufl->l_len);
  790. err |= __put_user(kfl->l_pid, &ufl->l_pid);
  791. return err;
  792. }
  793. extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
  794. asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
  795. {
  796. switch (cmd) {
  797. case F_GETLK:
  798. case F_SETLK:
  799. case F_SETLKW:
  800. {
  801. struct flock f;
  802. mm_segment_t old_fs;
  803. long ret;
  804. if(get_flock(&f, (struct flock32 *)arg))
  805. return -EFAULT;
  806. old_fs = get_fs(); set_fs (KERNEL_DS);
  807. ret = sys_fcntl(fd, cmd, (unsigned long)&f);
  808. set_fs (old_fs);
  809. if (ret) return ret;
  810. if (f.l_start >= 0x7fffffffUL ||
  811.     f.l_len >= 0x7fffffffUL ||
  812.     f.l_start + f.l_len >= 0x7fffffffUL)
  813. return -EOVERFLOW;
  814. if(put_flock(&f, (struct flock32 *)arg))
  815. return -EFAULT;
  816. return 0;
  817. }
  818. default:
  819. return sys_fcntl(fd, cmd, (unsigned long)arg);
  820. }
  821. }
  822. asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
  823. {
  824. if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
  825. return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg);
  826. return sys32_fcntl(fd, cmd, arg);
  827. }
  828. struct dqblk32 {
  829.     __u32 dqb_bhardlimit;
  830.     __u32 dqb_bsoftlimit;
  831.     __u32 dqb_curblocks;
  832.     __u32 dqb_ihardlimit;
  833.     __u32 dqb_isoftlimit;
  834.     __u32 dqb_curinodes;
  835.     __kernel_time_t32 dqb_btime;
  836.     __kernel_time_t32 dqb_itime;
  837. };
  838.                                 
  839. extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
  840. asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned long addr)
  841. {
  842. int cmds = cmd >> SUBCMDSHIFT;
  843. int err;
  844. struct dqblk d;
  845. mm_segment_t old_fs;
  846. char *spec;
  847. switch (cmds) {
  848. case Q_GETQUOTA:
  849. break;
  850. case Q_SETQUOTA:
  851. case Q_SETUSE:
  852. case Q_SETQLIM:
  853. if (copy_from_user (&d, (struct dqblk32 *)addr,
  854.     sizeof (struct dqblk32)))
  855. return -EFAULT;
  856. d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
  857. d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
  858. break;
  859. default:
  860. return sys_quotactl(cmd, special,
  861.     id, (caddr_t)addr);
  862. }
  863. spec = getname (special);
  864. err = PTR_ERR(spec);
  865. if (IS_ERR(spec)) return err;
  866. old_fs = get_fs ();
  867. set_fs (KERNEL_DS);
  868. err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
  869. set_fs (old_fs);
  870. putname (spec);
  871. if (err)
  872. return err;
  873. if (cmds == Q_GETQUOTA) {
  874. __kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
  875. ((struct dqblk32 *)&d)->dqb_itime = i;
  876. ((struct dqblk32 *)&d)->dqb_btime = b;
  877. if (copy_to_user ((struct dqblk32 *)addr, &d,
  878.   sizeof (struct dqblk32)))
  879. return -EFAULT;
  880. }
  881. return 0;
  882. }
  883. static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
  884. {
  885. int err;
  886. err = put_user (kbuf->f_type, &ubuf->f_type);
  887. err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
  888. err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
  889. err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
  890. err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
  891. err |= __put_user (kbuf->f_files, &ubuf->f_files);
  892. err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
  893. err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
  894. err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
  895. err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
  896. return err;
  897. }
  898. extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
  899. asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf)
  900. {
  901. int ret;
  902. struct statfs s;
  903. mm_segment_t old_fs = get_fs();
  904. char *pth;
  905. pth = getname (path);
  906. ret = PTR_ERR(pth);
  907. if (!IS_ERR(pth)) {
  908. set_fs (KERNEL_DS);
  909. ret = sys_statfs((const char *)pth, &s);
  910. set_fs (old_fs);
  911. putname (pth);
  912. if (put_statfs(buf, &s))
  913. return -EFAULT;
  914. }
  915. return ret;
  916. }
  917. extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
  918. asmlinkage int sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
  919. {
  920. int ret;
  921. struct statfs s;
  922. mm_segment_t old_fs = get_fs();
  923. set_fs (KERNEL_DS);
  924. ret = sys_fstatfs(fd, &s);
  925. set_fs (old_fs);
  926. if (put_statfs(buf, &s))
  927. return -EFAULT;
  928. return ret;
  929. }
  930. extern asmlinkage long sys_truncate(const char * path, unsigned long length);
  931. extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
  932. asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low)
  933. {
  934. if ((int)high < 0)
  935. return -EINVAL;
  936. else
  937. return sys_truncate(path, (high << 32) | low);
  938. }
  939. asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
  940. {
  941. if ((int)high < 0)
  942. return -EINVAL;
  943. else
  944. return sys_ftruncate(fd, (high << 32) | low);
  945. }
  946. extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
  947. struct utimbuf32 {
  948. __kernel_time_t32 actime, modtime;
  949. };
  950. asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times)
  951. {
  952. struct utimbuf t;
  953. mm_segment_t old_fs;
  954. int ret;
  955. char *filenam;
  956. if (!times)
  957. return sys_utime(filename, NULL);
  958. if (get_user (t.actime, &times->actime) ||
  959.     __get_user (t.modtime, &times->modtime))
  960. return -EFAULT;
  961. filenam = getname (filename);
  962. ret = PTR_ERR(filenam);
  963. if (!IS_ERR(filenam)) {
  964. old_fs = get_fs();
  965. set_fs (KERNEL_DS); 
  966. ret = sys_utime(filenam, &t);
  967. set_fs (old_fs);
  968. putname (filenam);
  969. }
  970. return ret;
  971. }
  972. struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
  973. typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
  974. typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
  975. static long do_readv_writev32(int type, struct file *file,
  976.       const struct iovec32 *vector, u32 count)
  977. {
  978. unsigned long tot_len;
  979. struct iovec iovstack[UIO_FASTIOV];
  980. struct iovec *iov=iovstack, *ivp;
  981. struct inode *inode;
  982. long retval, i;
  983. io_fn_t fn;
  984. iov_fn_t fnv;
  985. /* First get the "struct iovec" from user memory and
  986.  * verify all the pointers
  987.  */
  988. if (!count)
  989. return 0;
  990. if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
  991. return -EFAULT;
  992. if (count > UIO_MAXIOV)
  993. return -EINVAL;
  994. if (count > UIO_FASTIOV) {
  995. iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
  996. if (!iov)
  997. return -ENOMEM;
  998. }
  999. tot_len = 0;
  1000. i = count;
  1001. ivp = iov;
  1002. while(i > 0) {
  1003. u32 len;
  1004. u32 buf;
  1005. __get_user(len, &vector->iov_len);
  1006. __get_user(buf, &vector->iov_base);
  1007. tot_len += len;
  1008. ivp->iov_base = (void *)A(buf);
  1009. ivp->iov_len = (__kernel_size_t) len;
  1010. vector++;
  1011. ivp++;
  1012. i--;
  1013. }
  1014. inode = file->f_dentry->d_inode;
  1015. /* VERIFY_WRITE actually means a read, as we write to user space */
  1016. retval = locks_verify_area((type == VERIFY_WRITE
  1017.     ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
  1018.    inode, file, file->f_pos, tot_len);
  1019. if (retval)
  1020. goto out;
  1021. /* VERIFY_WRITE actually means a read, as we write to user space */
  1022. fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev);
  1023. if (fnv) {
  1024. retval = fnv(file, iov, count, &file->f_pos);
  1025. goto out;
  1026. }
  1027. fn = (type == VERIFY_WRITE ? file->f_op->read :
  1028.       (io_fn_t) file->f_op->write);
  1029. ivp = iov;
  1030. while (count > 0) {
  1031. void * base;
  1032. int len, nr;
  1033. base = ivp->iov_base;
  1034. len = ivp->iov_len;
  1035. ivp++;
  1036. count--;
  1037. nr = fn(file, base, len, &file->f_pos);
  1038. if (nr < 0) {
  1039. if (!retval)
  1040. retval = nr;
  1041. break;
  1042. }
  1043. retval += nr;
  1044. if (nr != len)
  1045. break;
  1046. }
  1047. out:
  1048. if (iov != iovstack)
  1049. kfree(iov);
  1050. return retval;
  1051. }
  1052. asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
  1053. {
  1054. struct file *file;
  1055. long ret = -EBADF;
  1056. file = fget(fd);
  1057. if(!file)
  1058. goto bad_file;
  1059. if (file->f_op && (file->f_mode & FMODE_READ) &&
  1060.     (file->f_op->readv || file->f_op->read))
  1061. ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
  1062. fput(file);
  1063. bad_file:
  1064. return ret;
  1065. }
  1066. asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
  1067. {
  1068. struct file *file;
  1069. int ret = -EBADF;
  1070. file = fget(fd);
  1071. if(!file)
  1072. goto bad_file;
  1073. if (file->f_op && (file->f_mode & FMODE_WRITE) &&
  1074.     (file->f_op->writev || file->f_op->write))
  1075. ret = do_readv_writev32(VERIFY_READ, file, vector, count);
  1076. fput(file);
  1077. bad_file:
  1078. return ret;
  1079. }
  1080. /* readdir & getdents */
  1081. #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
  1082. #define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
  1083. struct old_linux_dirent32 {
  1084. u32 d_ino;
  1085. u32 d_offset;
  1086. unsigned short d_namlen;
  1087. char d_name[1];
  1088. };
  1089. struct readdir_callback32 {
  1090. struct old_linux_dirent32 * dirent;
  1091. int count;
  1092. };
  1093. static int fillonedir(void * __buf, const char * name, int namlen,
  1094.       loff_t offset, ino_t ino, unsigned int d_type)
  1095. {
  1096. struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
  1097. struct old_linux_dirent32 * dirent;
  1098. if (buf->count)
  1099. return -EINVAL;
  1100. buf->count++;
  1101. dirent = buf->dirent;
  1102. put_user(ino, &dirent->d_ino);
  1103. put_user(offset, &dirent->d_offset);
  1104. put_user(namlen, &dirent->d_namlen);
  1105. copy_to_user(dirent->d_name, name, namlen);
  1106. put_user(0, dirent->d_name + namlen);
  1107. return 0;
  1108. }
  1109. asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count)
  1110. {
  1111. int error = -EBADF;
  1112. struct file * file;
  1113. struct readdir_callback32 buf;
  1114. file = fget(fd);
  1115. if (!file)
  1116. goto out;
  1117. buf.count = 0;
  1118. buf.dirent = dirent;
  1119. error = vfs_readdir(file, fillonedir, &buf);
  1120. if (error < 0)
  1121. goto out_putf;
  1122. error = buf.count;
  1123. out_putf:
  1124. fput(file);
  1125. out:
  1126. return error;
  1127. }
  1128. struct linux_dirent32 {
  1129. u32 d_ino;
  1130. u32 d_off;
  1131. unsigned short d_reclen;
  1132. char d_name[1];
  1133. };
  1134. struct getdents_callback32 {
  1135. struct linux_dirent32 * current_dir;
  1136. struct linux_dirent32 * previous;
  1137. int count;
  1138. int error;
  1139. };
  1140. static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
  1141.    unsigned int d_type)
  1142. {
  1143. struct linux_dirent32 * dirent;
  1144. struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
  1145. int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
  1146. buf->error = -EINVAL; /* only used if we fail.. */
  1147. if (reclen > buf->count)
  1148. return -EINVAL;
  1149. dirent = buf->previous;
  1150. if (dirent)
  1151. put_user(offset, &dirent->d_off);
  1152. dirent = buf->current_dir;
  1153. buf->previous = dirent;
  1154. put_user(ino, &dirent->d_ino);
  1155. put_user(reclen, &dirent->d_reclen);
  1156. copy_to_user(dirent->d_name, name, namlen);
  1157. put_user(0, dirent->d_name + namlen);
  1158. ((char *) dirent) += reclen;
  1159. buf->current_dir = dirent;
  1160. buf->count -= reclen;
  1161. return 0;
  1162. }
  1163. asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count)
  1164. {
  1165. struct file * file;
  1166. struct linux_dirent32 * lastdirent;
  1167. struct getdents_callback32 buf;
  1168. int error = -EBADF;
  1169. file = fget(fd);
  1170. if (!file)
  1171. goto out;
  1172. buf.current_dir = dirent;
  1173. buf.previous = NULL;
  1174. buf.count = count;
  1175. buf.error = 0;
  1176. error = vfs_readdir(file, filldir, &buf);
  1177. if (error < 0)
  1178. goto out_putf;
  1179. lastdirent = buf.previous;
  1180. error = buf.error;
  1181. if(lastdirent) {
  1182. put_user(file->f_pos, &lastdirent->d_off);
  1183. error = count - buf.count;
  1184. }
  1185. out_putf:
  1186. fput(file);
  1187. out:
  1188. return error;
  1189. }
  1190. /* end of readdir & getdents */
  1191. /*
  1192.  * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
  1193.  * 64-bit unsigned longs.
  1194.  */
  1195. static inline int
  1196. get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
  1197. {
  1198. if (ufdset) {
  1199. unsigned long odd;
  1200. if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
  1201. return -EFAULT;
  1202. odd = n & 1UL;
  1203. n &= ~1UL;
  1204. while (n) {
  1205. unsigned long h, l;
  1206. __get_user(l, ufdset);
  1207. __get_user(h, ufdset+1);
  1208. ufdset += 2;
  1209. *fdset++ = h << 32 | l;
  1210. n -= 2;
  1211. }
  1212. if (odd)
  1213. __get_user(*fdset, ufdset);
  1214. } else {
  1215. /* Tricky, must clear full unsigned long in the
  1216.  * kernel fdset at the end, this makes sure that
  1217.  * actually happens.
  1218.  */
  1219. memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
  1220. }
  1221. return 0;
  1222. }
  1223. static inline void
  1224. set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
  1225. {
  1226. unsigned long odd;
  1227. if (!ufdset)
  1228. return;
  1229. odd = n & 1UL;
  1230. n &= ~1UL;
  1231. while (n) {
  1232. unsigned long h, l;
  1233. l = *fdset++;
  1234. h = l >> 32;
  1235. __put_user(l, ufdset);
  1236. __put_user(h, ufdset+1);
  1237. ufdset += 2;
  1238. n -= 2;
  1239. }
  1240. if (odd)
  1241. __put_user(*fdset, ufdset);
  1242. }
  1243. #define MAX_SELECT_SECONDS 
  1244. ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
  1245. asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x)
  1246. {
  1247. fd_set_bits fds;
  1248. struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x);
  1249. char *bits;
  1250. unsigned long nn;
  1251. long timeout;
  1252. int ret, size;
  1253. timeout = MAX_SCHEDULE_TIMEOUT;
  1254. if (tvp) {
  1255. int sec, usec;
  1256. if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
  1257.     || (ret = __get_user(sec, &tvp->tv_sec))
  1258.     || (ret = __get_user(usec, &tvp->tv_usec)))
  1259. goto out_nofds;
  1260. ret = -EINVAL;
  1261. if(sec < 0 || usec < 0)
  1262. goto out_nofds;
  1263. if ((unsigned long) sec < MAX_SELECT_SECONDS) {
  1264. timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
  1265. timeout += sec * (unsigned long) HZ;
  1266. }
  1267. }
  1268. ret = -EINVAL;
  1269. if (n < 0)
  1270. goto out_nofds;
  1271. if (n > current->files->max_fdset)
  1272. n = current->files->max_fdset;
  1273. /*
  1274.  * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
  1275.  * since we used fdset we need to allocate memory in units of
  1276.  * long-words. 
  1277.  */
  1278. ret = -ENOMEM;
  1279. size = FDS_BYTES(n);
  1280. bits = kmalloc(6 * size, GFP_KERNEL);
  1281. if (!bits)
  1282. goto out_nofds;
  1283. fds.in      = (unsigned long *)  bits;
  1284. fds.out     = (unsigned long *) (bits +   size);
  1285. fds.ex      = (unsigned long *) (bits + 2*size);
  1286. fds.res_in  = (unsigned long *) (bits + 3*size);
  1287. fds.res_out = (unsigned long *) (bits + 4*size);
  1288. fds.res_ex  = (unsigned long *) (bits + 5*size);
  1289. nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
  1290. if ((ret = get_fd_set32(nn, fds.in, inp)) ||
  1291.     (ret = get_fd_set32(nn, fds.out, outp)) ||
  1292.     (ret = get_fd_set32(nn, fds.ex, exp)))
  1293. goto out;
  1294. zero_fd_set(n, fds.res_in);
  1295. zero_fd_set(n, fds.res_out);
  1296. zero_fd_set(n, fds.res_ex);
  1297. ret = do_select(n, &fds, &timeout);
  1298. if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
  1299. int sec = 0, usec = 0;
  1300. if (timeout) {
  1301. sec = timeout / HZ;
  1302. usec = timeout % HZ;
  1303. usec *= (1000000/HZ);
  1304. }
  1305. put_user(sec, &tvp->tv_sec);
  1306. put_user(usec, &tvp->tv_usec);
  1307. }
  1308. if (ret < 0)
  1309. goto out;
  1310. if (!ret) {
  1311. ret = -ERESTARTNOHAND;
  1312. if (signal_pending(current))
  1313. goto out;
  1314. ret = 0;
  1315. }
  1316. set_fd_set32(nn, inp, fds.res_in);
  1317. set_fd_set32(nn, outp, fds.res_out);
  1318. set_fd_set32(nn, exp, fds.res_ex);
  1319. out:
  1320. kfree(bits);
  1321. out_nofds:
  1322. return ret;
  1323. }
  1324. static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
  1325. {
  1326. unsigned long ino, blksize, blocks;
  1327. kdev_t dev, rdev;
  1328. umode_t mode;
  1329. nlink_t nlink;
  1330. uid_t uid;
  1331. gid_t gid;
  1332. off_t size;
  1333. time_t atime, mtime, ctime;
  1334. int err;
  1335. /* Stream the loads of inode data into the load buffer,
  1336.  * then we push it all into the store buffer below.  This
  1337.  * should give optimal cache performance.
  1338.  */
  1339. ino = inode->i_ino;
  1340. dev = inode->i_dev;
  1341. mode = inode->i_mode;
  1342. nlink = inode->i_nlink;
  1343. uid = inode->i_uid;
  1344. gid = inode->i_gid;
  1345. rdev = inode->i_rdev;
  1346. size = inode->i_size;
  1347. atime = inode->i_atime;
  1348. mtime = inode->i_mtime;
  1349. ctime = inode->i_ctime;
  1350. blksize = inode->i_blksize;
  1351. blocks = inode->i_blocks;
  1352. err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
  1353. err |= put_user(ino, &statbuf->st_ino);
  1354. err |= put_user(mode, &statbuf->st_mode);
  1355. err |= put_user(nlink, &statbuf->st_nlink);
  1356. err |= put_user(high2lowuid(uid), &statbuf->st_uid);
  1357. err |= put_user(high2lowgid(gid), &statbuf->st_gid);
  1358. err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
  1359. err |= put_user(size, &statbuf->st_size);
  1360. err |= put_user(atime, &statbuf->st_atime);
  1361. err |= put_user(0, &statbuf->__unused1);
  1362. err |= put_user(mtime, &statbuf->st_mtime);
  1363. err |= put_user(0, &statbuf->__unused2);
  1364. err |= put_user(ctime, &statbuf->st_ctime);
  1365. err |= put_user(0, &statbuf->__unused3);
  1366. if (blksize) {
  1367. err |= put_user(blksize, &statbuf->st_blksize);
  1368. err |= put_user(blocks, &statbuf->st_blocks);
  1369. } else {
  1370. unsigned int tmp_blocks;
  1371. #define D_B   7
  1372. #define I_B   (BLOCK_SIZE / sizeof(unsigned short))
  1373. tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
  1374. if (tmp_blocks > D_B) {
  1375. unsigned int indirect;
  1376. indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
  1377. tmp_blocks += indirect;
  1378. if (indirect > 1) {
  1379. indirect = (indirect - 1 + I_B - 1) / I_B;
  1380. tmp_blocks += indirect;
  1381. if (indirect > 1)
  1382. tmp_blocks++;
  1383. }
  1384. }
  1385. err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
  1386. err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
  1387. #undef D_B
  1388. #undef I_B
  1389. }
  1390. /* fixme
  1391. err |= put_user(0, &statbuf->__unused4[0]);
  1392. err |= put_user(0, &statbuf->__unused4[1]);
  1393. */
  1394. return err;
  1395. }
  1396. /* Perhaps this belongs in fs.h or similar. -DaveM */
  1397. static __inline__ int
  1398. do_revalidate(struct dentry *dentry)
  1399. {
  1400. struct inode * inode = dentry->d_inode;
  1401. if (inode->i_op && inode->i_op->revalidate)
  1402. return inode->i_op->revalidate(dentry);
  1403. return 0;
  1404. }
  1405. asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
  1406. {
  1407. struct nameidata nd;
  1408. int error;
  1409. error = user_path_walk(filename, &nd);
  1410. if (!error) {
  1411. error = do_revalidate(nd.dentry);
  1412. if (!error)
  1413. error = cp_new_stat32(nd.dentry->d_inode, statbuf);
  1414. path_release(&nd);
  1415. }
  1416. return error;
  1417. }
  1418. asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
  1419. {
  1420. struct nameidata nd;
  1421. int error;
  1422. error = user_path_walk_link(filename, &nd);
  1423. if (!error) {
  1424. error = do_revalidate(nd.dentry);
  1425. if (!error)
  1426. error = cp_new_stat32(nd.dentry->d_inode, statbuf);
  1427. path_release(&nd);
  1428. }
  1429. return error;
  1430. }
  1431. asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
  1432. {
  1433. struct file *f;
  1434. int err = -EBADF;
  1435. f = fget(fd);
  1436. if (f) {
  1437. struct dentry * dentry = f->f_dentry;
  1438. err = do_revalidate(dentry);
  1439. if (!err)
  1440. err = cp_new_stat32(dentry->d_inode, statbuf);
  1441. fput(f);
  1442. }
  1443. return err;
  1444. }
  1445. extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
  1446. asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
  1447. {
  1448. return sys_sysfs(option, arg1, arg2);
  1449. }
  1450. struct ncp_mount_data32 {
  1451.         int version;
  1452.         unsigned int ncp_fd;
  1453.         __kernel_uid_t32 mounted_uid;
  1454.         __kernel_pid_t32 wdog_pid;
  1455.         unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
  1456.         unsigned int time_out;
  1457.         unsigned int retry_count;
  1458.         unsigned int flags;
  1459.         __kernel_uid_t32 uid;
  1460.         __kernel_gid_t32 gid;
  1461.         __kernel_mode_t32 file_mode;
  1462.         __kernel_mode_t32 dir_mode;
  1463. };
  1464. static void *do_ncp_super_data_conv(void *raw_data)
  1465. {
  1466. struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
  1467. struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
  1468. n->dir_mode = n32->dir_mode;
  1469. n->file_mode = n32->file_mode;
  1470. n->gid = low2highgid(n32->gid);
  1471. n->uid = low2highuid(n32->uid);
  1472. memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
  1473. n->wdog_pid = n32->wdog_pid;
  1474. n->mounted_uid = low2highuid(n32->mounted_uid);
  1475. return raw_data;
  1476. }
  1477. struct smb_mount_data32 {
  1478.         int version;
  1479.         __kernel_uid_t32 mounted_uid;
  1480.         __kernel_uid_t32 uid;
  1481.         __kernel_gid_t32 gid;
  1482.         __kernel_mode_t32 file_mode;
  1483.         __kernel_mode_t32 dir_mode;
  1484. };
  1485. static void *do_smb_super_data_conv(void *raw_data)
  1486. {
  1487. struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
  1488. struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
  1489. s->version = s32->version;
  1490. s->mounted_uid = low2highuid(s32->mounted_uid);
  1491. s->uid = low2highuid(s32->uid);
  1492. s->gid = low2highgid(s32->gid);
  1493. s->file_mode = s32->file_mode;
  1494. s->dir_mode = s32->dir_mode;
  1495. return raw_data;
  1496. }
  1497. static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
  1498. {
  1499. int i;
  1500. unsigned long page;
  1501. struct vm_area_struct *vma;
  1502. *kernel = 0;
  1503. if(!user)
  1504. return 0;
  1505. vma = find_vma(current->mm, (unsigned long)user);
  1506. if(!vma || (unsigned long)user < vma->vm_start)
  1507. return -EFAULT;
  1508. if(!(vma->vm_flags & VM_READ))
  1509. return -EFAULT;
  1510. i = vma->vm_end - (unsigned long) user;
  1511. if(PAGE_SIZE <= (unsigned long) i)
  1512. i = PAGE_SIZE - 1;
  1513. if(!(page = __get_free_page(GFP_KERNEL)))
  1514. return -ENOMEM;
  1515. if(copy_from_user((void *) page, user, i)) {
  1516. free_page(page);
  1517. return -EFAULT;
  1518. }
  1519. *kernel = page;
  1520. return 0;
  1521. }
  1522. #define SMBFS_NAME "smbfs"
  1523. #define NCPFS_NAME "ncpfs"
  1524. asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data)
  1525. {
  1526. unsigned long type_page = 0;
  1527. unsigned long data_page = 0;
  1528. unsigned long dev_page = 0;
  1529. unsigned long dir_page = 0;
  1530. int err, is_smb, is_ncp;
  1531. is_smb = is_ncp = 0;
  1532. err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
  1533. if (err)
  1534. goto out;
  1535. if (!type_page) {
  1536. err = -EINVAL;
  1537. goto out;
  1538. }
  1539. is_smb = !strcmp((char *)type_page, SMBFS_NAME);
  1540. is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
  1541. err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page);
  1542. if (err)
  1543. goto type_out;
  1544. err = copy_mount_stuff_to_kernel(dev_name, &dev_page);
  1545. if (err)
  1546. goto data_out;
  1547. err = copy_mount_stuff_to_kernel(dir_name, &dir_page);
  1548. if (err)
  1549. goto dev_out;
  1550. if (!is_smb && !is_ncp) {
  1551. lock_kernel();
  1552. err = do_mount((char*)dev_page, (char*)dir_page,
  1553. (char*)type_page, new_flags, (char*)data_page);
  1554. unlock_kernel();
  1555. } else {
  1556. if (is_ncp)
  1557. do_ncp_super_data_conv((void *)data_page);
  1558. else
  1559. do_smb_super_data_conv((void *)data_page);
  1560. lock_kernel();
  1561. err = do_mount((char*)dev_page, (char*)dir_page,
  1562. (char*)type_page, new_flags, (char*)data_page);
  1563. unlock_kernel();
  1564. }
  1565. free_page(dir_page);
  1566. dev_out:
  1567. free_page(dev_page);
  1568. data_out:
  1569. free_page(data_page);
  1570. type_out:
  1571. free_page(type_page);
  1572. out:
  1573. return err;
  1574. }
  1575. struct rusage32 {
  1576.         struct timeval32 ru_utime;
  1577.         struct timeval32 ru_stime;
  1578.         s32    ru_maxrss;
  1579.         s32    ru_ixrss;
  1580.         s32    ru_idrss;
  1581.         s32    ru_isrss;
  1582.         s32    ru_minflt;
  1583.         s32    ru_majflt;
  1584.         s32    ru_nswap;
  1585.         s32    ru_inblock;
  1586.         s32    ru_oublock;
  1587.         s32    ru_msgsnd; 
  1588.         s32    ru_msgrcv; 
  1589.         s32    ru_nsignals;
  1590.         s32    ru_nvcsw;
  1591.         s32    ru_nivcsw;
  1592. };
  1593. static int put_rusage (struct rusage32 *ru, struct rusage *r)
  1594. {
  1595. int err;
  1596. err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
  1597. err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
  1598. err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
  1599. err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
  1600. err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
  1601. err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
  1602. err |= __put_user (r->ru_idrss, &ru->ru_idrss);
  1603. err |= __put_user (r->ru_isrss, &ru->ru_isrss);
  1604. err |= __put_user (r->ru_minflt, &ru->ru_minflt);
  1605. err |= __put_user (r->ru_majflt, &ru->ru_majflt);
  1606. err |= __put_user (r->ru_nswap, &ru->ru_nswap);
  1607. err |= __put_user (r->ru_inblock, &ru->ru_inblock);
  1608. err |= __put_user (r->ru_oublock, &ru->ru_oublock);
  1609. err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
  1610. err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
  1611. err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
  1612. err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
  1613. err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
  1614. return err;
  1615. }
  1616. asmlinkage int sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
  1617. {
  1618. if (!ru)
  1619. return sys_wait4(pid, stat_addr, options, NULL);
  1620. else {
  1621. struct rusage r;
  1622. int ret;
  1623. unsigned int status;
  1624. mm_segment_t old_fs = get_fs();
  1625. set_fs (KERNEL_DS);
  1626. ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
  1627. set_fs (old_fs);
  1628. if (put_rusage (ru, &r)) return -EFAULT;
  1629. if (stat_addr && put_user (status, stat_addr))
  1630. return -EFAULT;
  1631. return ret;
  1632. }
  1633. }
  1634. struct sysinfo32 {
  1635.         s32 uptime;
  1636.         u32 loads[3];
  1637.         u32 totalram;
  1638.         u32 freeram;
  1639.         u32 sharedram;
  1640.         u32 bufferram;
  1641.         u32 totalswap;
  1642.         u32 freeswap;
  1643.         unsigned short procs;
  1644.         char _f[22];
  1645. };
  1646. extern asmlinkage int sys_sysinfo(struct sysinfo *info);
  1647. asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
  1648. {
  1649. struct sysinfo s;
  1650. int ret, err;
  1651. mm_segment_t old_fs = get_fs ();
  1652. set_fs (KERNEL_DS);
  1653. ret = sys_sysinfo(&s);
  1654. set_fs (old_fs);
  1655. err = put_user (s.uptime, &info->uptime);
  1656. err |= __put_user (s.loads[0], &info->loads[0]);
  1657. err |= __put_user (s.loads[1], &info->loads[1]);
  1658. err |= __put_user (s.loads[2], &info->loads[2]);
  1659. err |= __put_user (s.totalram, &info->totalram);
  1660. err |= __put_user (s.freeram, &info->freeram);
  1661. err |= __put_user (s.sharedram, &info->sharedram);
  1662. err |= __put_user (s.bufferram, &info->bufferram);
  1663. err |= __put_user (s.totalswap, &info->totalswap);
  1664. err |= __put_user (s.freeswap, &info->freeswap);
  1665. err |= __put_user (s.procs, &info->procs);
  1666. if (err)
  1667. return -EFAULT;
  1668. return ret;
  1669. }
  1670. struct timespec32 {
  1671. s32    tv_sec;
  1672. s32    tv_nsec;
  1673. };
  1674.                 
  1675. extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
  1676. asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
  1677. {
  1678. struct timespec t;
  1679. int ret;
  1680. mm_segment_t old_fs = get_fs ();
  1681. set_fs (KERNEL_DS);
  1682. ret = sys_sched_rr_get_interval(pid, &t);
  1683. set_fs (old_fs);
  1684. if (put_user (t.tv_sec, &interval->tv_sec) ||
  1685.     __put_user (t.tv_nsec, &interval->tv_nsec))
  1686. return -EFAULT;
  1687. return ret;
  1688. }
  1689. extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
  1690. asmlinkage int sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
  1691. {
  1692. struct timespec t;
  1693. int ret;
  1694. mm_segment_t old_fs = get_fs ();
  1695. if (get_user (t.tv_sec, &rqtp->tv_sec) ||
  1696.     __get_user (t.tv_nsec, &rqtp->tv_nsec))
  1697. return -EFAULT;
  1698. set_fs (KERNEL_DS);
  1699. ret = sys_nanosleep(&t, rmtp ? &t : NULL);
  1700. set_fs (old_fs);
  1701. if (rmtp && ret == -EINTR) {
  1702. if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
  1703.          __put_user (t.tv_nsec, &rmtp->tv_nsec))
  1704. return -EFAULT;
  1705. }
  1706. return ret;
  1707. }
  1708. extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset);
  1709. asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, old_sigset_t32 *oset)
  1710. {
  1711. old_sigset_t s;
  1712. int ret;
  1713. mm_segment_t old_fs = get_fs();
  1714. if (set && get_user (s, set)) return -EFAULT;
  1715. set_fs (KERNEL_DS);
  1716. ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
  1717. set_fs (old_fs);
  1718. if (ret) return ret;
  1719. if (oset && put_user (s, oset)) return -EFAULT;
  1720. return 0;
  1721. }
  1722. extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize);
  1723. asmlinkage int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset, __kernel_size_t32 sigsetsize)
  1724. {
  1725. sigset_t s;
  1726. sigset_t32 s32;
  1727. int ret;
  1728. mm_segment_t old_fs = get_fs();
  1729. if (set) {
  1730. if (copy_from_user (&s32, set, sizeof(sigset_t32)))
  1731. return -EFAULT;
  1732. switch (_NSIG_WORDS) {
  1733. case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
  1734. case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
  1735. case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
  1736. case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
  1737. }
  1738. }
  1739. set_fs (KERNEL_DS);
  1740. ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sigsetsize);
  1741. set_fs (old_fs);
  1742. if (ret) return ret;
  1743. if (oset) {
  1744. switch (_NSIG_WORDS) {
  1745. case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
  1746. case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
  1747. case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
  1748. case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
  1749. }
  1750. if (copy_to_user (oset, &s32, sizeof(sigset_t32)))
  1751. return -EFAULT;
  1752. }
  1753. return 0;
  1754. }
  1755. extern asmlinkage int sys_sigpending(old_sigset_t *set);
  1756. asmlinkage int sys32_sigpending(old_sigset_t32 *set)
  1757. {
  1758. old_sigset_t s;
  1759. int ret;
  1760. mm_segment_t old_fs = get_fs();
  1761. set_fs (KERNEL_DS);
  1762. ret = sys_sigpending(&s);
  1763. set_fs (old_fs);
  1764. if (put_user (s, set)) return -EFAULT;
  1765. return ret;
  1766. }
  1767. extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
  1768. asmlinkage int sys32_rt_sigpending(sigset_t32 *set, __kernel_size_t32 sigsetsize)
  1769. {
  1770. sigset_t s;
  1771. sigset_t32 s32;
  1772. int ret;
  1773. mm_segment_t old_fs = get_fs();
  1774. set_fs (KERNEL_DS);
  1775. ret = sys_rt_sigpending(&s, sigsetsize);
  1776. set_fs (old_fs);
  1777. if (!ret) {
  1778. switch (_NSIG_WORDS) {
  1779. case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
  1780. case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
  1781. case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
  1782. case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
  1783. }
  1784. if (copy_to_user (set, &s32, sizeof(sigset_t32)))
  1785. return -EFAULT;
  1786. }
  1787. return ret;
  1788. }
  1789. extern int
  1790. copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from);
  1791. asmlinkage int
  1792. sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
  1793.       struct timespec32 *uts, __kernel_size_t32 sigsetsize)
  1794. {
  1795. int ret, sig;
  1796. sigset_t these;
  1797. sigset_t32 these32;
  1798. struct timespec ts;
  1799. siginfo_t info;
  1800. long timeout = 0;
  1801. /* XXX: Don't preclude handling different sized sigset_t's.  */
  1802. if (sigsetsize != sizeof(sigset_t))
  1803. return -EINVAL;
  1804. if (copy_from_user (&these32, uthese, sizeof(sigset_t32)))
  1805. return -EFAULT;
  1806. switch (_NSIG_WORDS) {
  1807. case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
  1808. case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
  1809. case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
  1810. case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
  1811. }
  1812. /*
  1813.  * Invert the set of allowed signals to get those we
  1814.  * want to block.
  1815.  */
  1816. sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
  1817. signotset(&these);
  1818. if (uts) {
  1819. if (get_user (ts.tv_sec, &uts->tv_sec) ||
  1820.     get_user (ts.tv_nsec, &uts->tv_nsec))
  1821. return -EINVAL;
  1822. if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
  1823.     || ts.tv_sec < 0)
  1824. return -EINVAL;
  1825. }
  1826. spin_lock_irq(&current->sigmask_lock);
  1827. sig = dequeue_signal(&these, &info);
  1828. if (!sig) {
  1829. /* None ready -- temporarily unblock those we're interested
  1830.    in so that we'll be awakened when they arrive.  */
  1831. sigset_t oldblocked = current->blocked;
  1832. sigandsets(&current->blocked, &current->blocked, &these);
  1833. recalc_sigpending(current);
  1834. spin_unlock_irq(&current->sigmask_lock);
  1835. timeout = MAX_SCHEDULE_TIMEOUT;
  1836. if (uts)
  1837. timeout = (timespec_to_jiffies(&ts)
  1838.    + (ts.tv_sec || ts.tv_nsec));
  1839. current->state = TASK_INTERRUPTIBLE;
  1840. timeout = schedule_timeout(timeout);
  1841. spin_lock_irq(&current->sigmask_lock);
  1842. sig = dequeue_signal(&these, &info);
  1843. current->blocked = oldblocked;
  1844. recalc_sigpending(current);
  1845. }
  1846. spin_unlock_irq(&current->sigmask_lock);
  1847. if (sig) {
  1848. ret = sig;
  1849. if (uinfo) {
  1850. if (copy_siginfo_to_user32(uinfo, &info))
  1851. ret = -EFAULT;
  1852. }
  1853. } else {
  1854. ret = -EAGAIN;
  1855. if (timeout)
  1856. ret = -EINTR;
  1857. }
  1858. return ret;
  1859. }
  1860. extern asmlinkage int
  1861. sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
  1862. asmlinkage int
  1863. sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
  1864. {
  1865. siginfo_t info;
  1866. int ret;
  1867. mm_segment_t old_fs = get_fs();
  1868. if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
  1869.     copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
  1870. return -EFAULT;
  1871. set_fs (KERNEL_DS);
  1872. ret = sys_rt_sigqueueinfo(pid, sig, &info);
  1873. set_fs (old_fs);
  1874. return ret;
  1875. }
  1876. struct tms32 {
  1877. __kernel_clock_t32 tms_utime;
  1878. __kernel_clock_t32 tms_stime;
  1879. __kernel_clock_t32 tms_cutime;
  1880. __kernel_clock_t32 tms_cstime;
  1881. };
  1882.                                 
  1883. extern asmlinkage long sys_times(struct tms * tbuf);
  1884. asmlinkage long sys32_times(struct tms32 *tbuf)
  1885. {
  1886. struct tms t;
  1887. long ret;
  1888. mm_segment_t old_fs = get_fs ();
  1889. int err;
  1890. set_fs (KERNEL_DS);
  1891. ret = sys_times(tbuf ? &t : NULL);
  1892. set_fs (old_fs);
  1893. if (tbuf) {
  1894. err = put_user (t.tms_utime, &tbuf->tms_utime);
  1895. err |= __put_user (t.tms_stime, &tbuf->tms_stime);
  1896. err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
  1897. err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
  1898. if (err)
  1899. ret = -EFAULT;
  1900. }
  1901. return ret;
  1902. }
  1903. #define RLIM_INFINITY32 0x7fffffff
  1904. #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
  1905. struct rlimit32 {
  1906. u32 rlim_cur;
  1907. u32 rlim_max;
  1908. };
  1909. extern asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim);
  1910. asmlinkage int sys32_old_getrlimit(unsigned int resource, struct rlimit32 *rlim)
  1911. {
  1912. struct rlimit r;
  1913. int ret;
  1914. mm_segment_t old_fs = get_fs ();
  1915. set_fs (KERNEL_DS);
  1916. ret = sys_old_getrlimit(resource, &r);
  1917. set_fs (old_fs);
  1918. if (!ret) {
  1919. ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
  1920. ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
  1921. }
  1922. return ret;
  1923. }
  1924. extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
  1925. asmlinkage int sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
  1926. {
  1927. struct rlimit r;
  1928. int ret;
  1929. mm_segment_t old_fs = get_fs ();
  1930. if (resource >= RLIM_NLIMITS) return -EINVAL;
  1931. if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
  1932.     __get_user (r.rlim_max, &rlim->rlim_max))
  1933. return -EFAULT;
  1934. if (r.rlim_cur == RLIM_INFINITY32)
  1935. r.rlim_cur = RLIM_INFINITY;
  1936. if (r.rlim_max == RLIM_INFINITY32)
  1937. r.rlim_max = RLIM_INFINITY;
  1938. set_fs (KERNEL_DS);
  1939. ret = sys_setrlimit(resource, &r);
  1940. set_fs (old_fs);
  1941. return ret;
  1942. }
  1943. extern asmlinkage int sys_getrusage(int who, struct rusage *ru);
  1944. asmlinkage int sys32_getrusage(int who, struct rusage32 *ru)
  1945. {
  1946. struct rusage r;
  1947. int ret;
  1948. mm_segment_t old_fs = get_fs();
  1949. set_fs (KERNEL_DS);
  1950. ret = sys_getrusage(who, &r);
  1951. set_fs (old_fs);
  1952. if (put_rusage (ru, &r)) return -EFAULT;
  1953. return ret;
  1954. }
  1955. /* XXX This really belongs in some header file... -DaveM */
  1956. #define MAX_SOCK_ADDR 128 /* 108 for Unix domain - 
  1957.    16 for IP, 16 for IPX,
  1958.    24 for IPv6,
  1959.    about 80 for AX.25 */
  1960. extern struct socket *sockfd_lookup(int fd, int *err);
  1961. /* XXX This as well... */
  1962. extern __inline__ void sockfd_put(struct socket *sock)
  1963. {
  1964. fput(sock->file);
  1965. }
  1966. struct msghdr32 {
  1967.         u32               msg_name;
  1968.         int               msg_namelen;
  1969.         u32               msg_iov;
  1970.         __kernel_size_t32 msg_iovlen;
  1971.         u32               msg_control;
  1972.         __kernel_size_t32 msg_controllen;
  1973.         unsigned          msg_flags;
  1974. };
  1975. struct cmsghdr32 {
  1976.         __kernel_size_t32 cmsg_len;
  1977.         int               cmsg_level;
  1978.         int               cmsg_type;
  1979. };
  1980. /* Bleech... */
  1981. #define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
  1982. #define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
  1983. #define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
  1984. #define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
  1985. #define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
  1986. #define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
  1987. #define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? 
  1988.     (struct cmsghdr32 *)(ctl) : 
  1989.     (struct cmsghdr32 *)NULL)
  1990. #define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
  1991. __inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
  1992.       struct cmsghdr32 *__cmsg, int __cmsg_len)
  1993. {
  1994. struct cmsghdr32 * __ptr;
  1995. __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
  1996.      CMSG32_ALIGN(__cmsg_len));
  1997. if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
  1998. return NULL;
  1999. return __ptr;
  2000. }
  2001. __inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
  2002.     struct cmsghdr32 *__cmsg,
  2003.     int __cmsg_len)
  2004. {
  2005. return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
  2006.        __cmsg, __cmsg_len);
  2007. }
  2008. static inline int iov_from_user32_to_kern(struct iovec *kiov,
  2009.   struct iovec32 *uiov32,
  2010.   int niov)
  2011. {
  2012. int tot_len = 0;
  2013. while(niov > 0) {
  2014. u32 len, buf;
  2015. if(get_user(len, &uiov32->iov_len) ||
  2016.    get_user(buf, &uiov32->iov_base)) {
  2017. tot_len = -EFAULT;
  2018. break;
  2019. }
  2020. tot_len += len;
  2021. kiov->iov_base = (void *)A(buf);
  2022. kiov->iov_len = (__kernel_size_t) len;
  2023. uiov32++;
  2024. kiov++;
  2025. niov--;
  2026. }
  2027. return tot_len;
  2028. }
  2029. static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
  2030.      struct msghdr32 *umsg)
  2031. {
  2032. u32 tmp1, tmp2, tmp3;
  2033. int err;
  2034. err = get_user(tmp1, &umsg->msg_name);
  2035. err |= __get_user(tmp2, &umsg->msg_iov);
  2036. err |= __get_user(tmp3, &umsg->msg_control);
  2037. if (err)
  2038. return -EFAULT;
  2039. kmsg->msg_name = (void *)A(tmp1);
  2040. kmsg->msg_iov = (struct iovec *)A(tmp2);
  2041. kmsg->msg_control = (void *)A(tmp3);
  2042. err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
  2043. err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
  2044. err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
  2045. err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
  2046. return err;
  2047. }
  2048. /* I've named the args so it is easy to tell whose space the pointers are in. */
  2049. static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
  2050.   char *kern_address, int mode)
  2051. {
  2052. int tot_len;
  2053. if(kern_msg->msg_namelen) {
  2054. if(mode==VERIFY_READ) {
  2055. int err = move_addr_to_kernel(kern_msg->msg_name,
  2056.       kern_msg->msg_namelen,
  2057.       kern_address);
  2058. if(err < 0)
  2059. return err;
  2060. }
  2061. kern_msg->msg_name = kern_address;
  2062. } else
  2063. kern_msg->msg_name = NULL;
  2064. if(kern_msg->msg_iovlen > UIO_FASTIOV) {
  2065. kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
  2066.    GFP_KERNEL);
  2067. if(!kern_iov)
  2068. return -ENOMEM;
  2069. }
  2070. tot_len = iov_from_user32_to_kern(kern_iov,
  2071.   (struct iovec32 *)kern_msg->msg_iov,
  2072.   kern_msg->msg_iovlen);
  2073. if(tot_len >= 0)
  2074. kern_msg->msg_iov = kern_iov;
  2075. else if(kern_msg->msg_iovlen > UIO_FASTIOV)
  2076. kfree(kern_iov);
  2077. return tot_len;
  2078. }
  2079. /* There is a lot of hair here because the alignment rules (and
  2080.  * thus placement) of cmsg headers and length are different for
  2081.  * 32-bit apps.  -DaveM
  2082.  */
  2083. static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
  2084.        unsigned char *stackbuf, int stackbuf_size)
  2085. {
  2086. struct cmsghdr32 *ucmsg;
  2087. struct cmsghdr *kcmsg, *kcmsg_base;
  2088. __kernel_size_t32 ucmlen;
  2089. __kernel_size_t kcmlen, tmp;
  2090. kcmlen = 0;
  2091. kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
  2092. ucmsg = CMSG32_FIRSTHDR(kmsg);
  2093. while(ucmsg != NULL) {
  2094. if(get_user(ucmlen, &ucmsg->cmsg_len))
  2095. return -EFAULT;
  2096. /* Catch bogons. */
  2097. if(CMSG32_ALIGN(ucmlen) <
  2098.    CMSG32_ALIGN(sizeof(struct cmsghdr32)))
  2099. return -EINVAL;
  2100. if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
  2101.    + ucmlen) > kmsg->msg_controllen)
  2102. return -EINVAL;
  2103. tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
  2104.        CMSG_ALIGN(sizeof(struct cmsghdr)));
  2105. kcmlen += tmp;
  2106. ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
  2107. }
  2108. if(kcmlen == 0)
  2109. return -EINVAL;
  2110. /* The kcmlen holds the 64-bit version of the control length.
  2111.  * It may not be modified as we do not stick it into the kmsg
  2112.  * until we have successfully copied over all of the data
  2113.  * from the user.
  2114.  */
  2115. if(kcmlen > stackbuf_size)
  2116. kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
  2117. if(kcmsg == NULL)
  2118. return -ENOBUFS;
  2119. /* Now copy them over neatly. */
  2120. memset(kcmsg, 0, kcmlen);
  2121. ucmsg = CMSG32_FIRSTHDR(kmsg);
  2122. while(ucmsg != NULL) {
  2123. __get_user(ucmlen, &ucmsg->cmsg_len);
  2124. tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
  2125.        CMSG_ALIGN(sizeof(struct cmsghdr)));
  2126. kcmsg->cmsg_len = tmp;
  2127. __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
  2128. __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
  2129. /* Copy over the data. */
  2130. if(copy_from_user(CMSG_DATA(kcmsg),
  2131.   CMSG32_DATA(ucmsg),
  2132.   (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
  2133. goto out_free_efault;
  2134. /* Advance. */
  2135. kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
  2136. ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
  2137. }
  2138. /* Ok, looks like we made it.  Hook it up and return success. */
  2139. kmsg->msg_control = kcmsg_base;
  2140. kmsg->msg_controllen = kcmlen;
  2141. return 0;
  2142. out_free_efault:
  2143. if(kcmsg_base != (struct cmsghdr *)stackbuf)
  2144. kfree(kcmsg_base);
  2145. return -EFAULT;
  2146. }
  2147. static void put_cmsg32(struct msghdr *kmsg, int level, int type,
  2148.        int len, void *data)
  2149. {
  2150. struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
  2151. struct cmsghdr32 cmhdr;
  2152. int cmlen = CMSG32_LEN(len);
  2153. if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
  2154. kmsg->msg_flags |= MSG_CTRUNC;
  2155. return;
  2156. }
  2157. if(kmsg->msg_controllen < cmlen) {
  2158. kmsg->msg_flags |= MSG_CTRUNC;
  2159. cmlen = kmsg->msg_controllen;
  2160. }
  2161. cmhdr.cmsg_level = level;
  2162. cmhdr.cmsg_type = type;
  2163. cmhdr.cmsg_len = cmlen;
  2164. if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
  2165. return;
  2166. if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
  2167. return;
  2168. cmlen = CMSG32_SPACE(len);
  2169. kmsg->msg_control += cmlen;
  2170. kmsg->msg_controllen -= cmlen;
  2171. }
  2172. static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
  2173. {
  2174. struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
  2175. int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
  2176. int fdnum = scm->fp->count;
  2177. struct file **fp = scm->fp->fp;
  2178. int *cmfptr;
  2179. int err = 0, i;
  2180. if (fdnum < fdmax)
  2181. fdmax = fdnum;
  2182. for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
  2183. int new_fd;
  2184. err = get_unused_fd();
  2185. if (err < 0)
  2186. break;
  2187. new_fd = err;
  2188. err = put_user(new_fd, cmfptr);
  2189. if (err) {
  2190. put_unused_fd(new_fd);
  2191. break;
  2192. }
  2193. /* Bump the usage count and install the file. */
  2194. get_file(fp[i]);
  2195. fd_install(new_fd, fp[i]);
  2196. }
  2197. if (i > 0) {
  2198. int cmlen = CMSG32_LEN(i * sizeof(int));
  2199. if (!err)
  2200. err = put_user(SOL_SOCKET, &cm->cmsg_level);
  2201. if (!err)
  2202. err = put_user(SCM_RIGHTS, &cm->cmsg_type);
  2203. if (!err)
  2204. err = put_user(cmlen, &cm->cmsg_len);
  2205. if (!err) {
  2206. cmlen = CMSG32_SPACE(i * sizeof(int));
  2207. kmsg->msg_control += cmlen;
  2208. kmsg->msg_controllen -= cmlen;
  2209. }
  2210. }
  2211. if (i < fdnum)
  2212. kmsg->msg_flags |= MSG_CTRUNC;
  2213. /*
  2214.  * All of the files that fit in the message have had their
  2215.  * usage counts incremented, so we just free the list.
  2216.  */
  2217. __scm_destroy(scm);
  2218. }
  2219. /* In these cases we (currently) can just copy to data over verbatim
  2220.  * because all CMSGs created by the kernel have well defined types which
  2221.  * have the same layout in both the 32-bit and 64-bit API.  One must add
  2222.  * some special cased conversions here if we start sending control messages
  2223.  * with incompatible types.
  2224.  *
  2225.  * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
  2226.  * we do our work.  The remaining cases are:
  2227.  *
  2228.  * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean
  2229.  * IP_TTL int 32-bit clean
  2230.  * IP_TOS __u8 32-bit clean
  2231.  * IP_RECVOPTS variable length 32-bit clean
  2232.  * IP_RETOPTS variable length 32-bit clean
  2233.  * (these last two are clean because the types are defined
  2234.  *  by the IPv4 protocol)
  2235.  * IP_RECVERR struct sock_extended_err +
  2236.  * struct sockaddr_in 32-bit clean
  2237.  * SOL_IPV6 IPV6_RECVERR struct sock_extended_err +
  2238.  * struct sockaddr_in6 32-bit clean
  2239.  * IPV6_PKTINFO struct in6_pktinfo 32-bit clean
  2240.  * IPV6_HOPLIMIT int 32-bit clean
  2241.  * IPV6_FLOWINFO u32 32-bit clean
  2242.  * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean
  2243.  * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean
  2244.  * IPV6_RTHDR ipv6 routing exthdr 32-bit clean
  2245.  * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean
  2246.  */
  2247. static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
  2248. {
  2249. unsigned char *workbuf, *wp;
  2250. unsigned long bufsz, space_avail;
  2251. struct cmsghdr *ucmsg;
  2252. bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
  2253. space_avail = kmsg->msg_controllen + bufsz;
  2254. wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
  2255. if(workbuf == NULL)
  2256. goto fail;
  2257. /* To make this more sane we assume the kernel sends back properly
  2258.  * formatted control messages.  Because of how the kernel will truncate
  2259.  * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
  2260.  */
  2261. ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
  2262. while(((unsigned long)ucmsg) <=
  2263.       (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
  2264. struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
  2265. int clen64, clen32;
  2266. /* UCMSG is the 64-bit format CMSG entry in user-space.
  2267.  * KCMSG32 is within the kernel space temporary buffer
  2268.  * we use to convert into a 32-bit style CMSG.
  2269.  */
  2270. __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
  2271. __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
  2272. __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
  2273. clen64 = kcmsg32->cmsg_len;
  2274. copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
  2275.        clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
  2276. clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
  2277.   CMSG32_ALIGN(sizeof(struct cmsghdr32)));
  2278. kcmsg32->cmsg_len = clen32;
  2279. ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
  2280. wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
  2281. }
  2282. /* Copy back fixed up data, and adjust pointers. */
  2283. bufsz = (wp - workbuf);
  2284. copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
  2285. kmsg->msg_control = (struct cmsghdr *)
  2286. (((char *)orig_cmsg_uptr) + bufsz);
  2287. kmsg->msg_controllen = space_avail - bufsz;
  2288. kfree(workbuf);
  2289. return;
  2290. fail:
  2291. /* If we leave the 64-bit format CMSG chunks in there,
  2292.  * the application could get confused and crash.  So to
  2293.  * ensure greater recovery, we report no CMSGs.
  2294.  */
  2295. kmsg->msg_controllen += bufsz;
  2296. kmsg->msg_control = (void *) orig_cmsg_uptr;
  2297. }
  2298. asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
  2299. {
  2300. struct socket *sock;
  2301. char address[MAX_SOCK_ADDR];
  2302. struct iovec iov[UIO_FASTIOV];
  2303. unsigned char ctl[sizeof(struct cmsghdr) + 20];
  2304. unsigned char *ctl_buf = ctl;
  2305. struct msghdr kern_msg;
  2306. int err, total_len;
  2307. if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
  2308. return -EFAULT;
  2309. if(kern_msg.msg_iovlen > UIO_MAXIOV)
  2310. return -EINVAL;
  2311. err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
  2312. if (err < 0)
  2313. goto out;
  2314. total_len = err;
  2315. if(kern_msg.msg_controllen) {
  2316. err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
  2317. if(err)
  2318. goto out_freeiov;
  2319. ctl_buf = kern_msg.msg_control;
  2320. }
  2321. kern_msg.msg_flags = user_flags;
  2322. sock = sockfd_lookup(fd, &err);
  2323. if (sock != NULL) {
  2324. if (sock->file->f_flags & O_NONBLOCK)
  2325. kern_msg.msg_flags |= MSG_DONTWAIT;
  2326. err = sock_sendmsg(sock, &kern_msg, total_len);
  2327. sockfd_put(sock);
  2328. }
  2329. /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
  2330. if(ctl_buf != ctl)
  2331. kfree(ctl_buf);
  2332. out_freeiov:
  2333. if(kern_msg.msg_iov != iov)
  2334. kfree(kern_msg.msg_iov);
  2335. out:
  2336. return err;
  2337. }
  2338. asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
  2339. {
  2340. struct iovec iovstack[UIO_FASTIOV];
  2341. struct msghdr kern_msg;
  2342. char addr[MAX_SOCK_ADDR];
  2343. struct socket *sock;
  2344. struct iovec *iov = iovstack;
  2345. struct sockaddr *uaddr;
  2346. int *uaddr_len;
  2347. unsigned long cmsg_ptr;
  2348. int err, total_len, len = 0;
  2349. if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
  2350. return -EFAULT;
  2351. if(kern_msg.msg_iovlen > UIO_MAXIOV)
  2352. return -EINVAL;
  2353. uaddr = kern_msg.msg_name;
  2354. uaddr_len = &user_msg->msg_namelen;
  2355. err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
  2356. if (err < 0)
  2357. goto out;
  2358. total_len = err;
  2359. cmsg_ptr = (unsigned long) kern_msg.msg_control;
  2360. kern_msg.msg_flags = 0;
  2361. sock = sockfd_lookup(fd, &err);
  2362. if (sock != NULL) {
  2363. struct scm_cookie scm;
  2364. if (sock->file->f_flags & O_NONBLOCK)
  2365. user_flags |= MSG_DONTWAIT;
  2366. memset(&scm, 0, sizeof(scm));
  2367. err = sock->ops->recvmsg(sock, &kern_msg, total_len,
  2368.  user_flags, &scm);
  2369. if(err >= 0) {
  2370. len = err;
  2371. if(!kern_msg.msg_control) {
  2372. if(sock->passcred || scm.fp)
  2373. kern_msg.msg_flags |= MSG_CTRUNC;
  2374. if(scm.fp)
  2375. __scm_destroy(&scm);
  2376. } else {
  2377. /* If recvmsg processing itself placed some
  2378.  * control messages into user space, it's is
  2379.  * using 64-bit CMSG processing, so we need
  2380.  * to fix it up before we tack on more stuff.
  2381.  */
  2382. if((unsigned long) kern_msg.msg_control != cmsg_ptr)
  2383. cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
  2384. /* Wheee... */
  2385. if(sock->passcred)
  2386. put_cmsg32(&kern_msg,
  2387.    SOL_SOCKET, SCM_CREDENTIALS,
  2388.    sizeof(scm.creds), &scm.creds);
  2389. if(scm.fp != NULL)
  2390. scm_detach_fds32(&kern_msg, &scm);
  2391. }
  2392. }
  2393. sockfd_put(sock);
  2394. }
  2395. if(uaddr != NULL && err >= 0)
  2396. err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
  2397. if(cmsg_ptr != 0 && err >= 0) {
  2398. unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
  2399. __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr);
  2400. err |= __put_user(uclen, &user_msg->msg_controllen);
  2401. }
  2402. if(err >= 0)
  2403. err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
  2404. if(kern_msg.msg_iov != iov)
  2405. kfree(kern_msg.msg_iov);
  2406. out:
  2407. if(err < 0)
  2408. return err;
  2409. return len;
  2410. }
  2411. extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
  2412.      char *optval, int optlen);
  2413. static int do_set_attach_filter(int fd, int level, int optname,
  2414. char *optval, int optlen)
  2415. {
  2416. struct sock_fprog32 {
  2417. __u16 len;
  2418. __u32 filter;
  2419. } *fprog32 = (struct sock_fprog32 *)optval;
  2420. struct sock_fprog kfprog;
  2421. struct sock_filter *kfilter;
  2422. unsigned int fsize;
  2423. mm_segment_t old_fs;
  2424. __u32 uptr;
  2425. int ret;
  2426. if (get_user(kfprog.len, &fprog32->len) ||
  2427.     __get_user(uptr, &fprog32->filter))
  2428. return -EFAULT;
  2429. kfprog.filter = (struct sock_filter *)A(uptr);
  2430. fsize = kfprog.len * sizeof(struct sock_filter);
  2431. kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
  2432. if (kfilter == NULL)
  2433. return -ENOMEM;
  2434. if (copy_from_user(kfilter, kfprog.filter, fsize)) {
  2435. kfree(kfilter);
  2436. return -EFAULT;
  2437. }
  2438. kfprog.filter = kfilter;
  2439. old_fs = get_fs();
  2440. set_fs(KERNEL_DS);
  2441. ret = sys_setsockopt(fd, level, optname,
  2442.      (char *)&kfprog, sizeof(kfprog));
  2443. set_fs(old_fs);
  2444. kfree(kfilter);
  2445. return ret;
  2446. }
  2447. static int do_set_icmpv6_filter(int fd, int level, int optname,
  2448. char *optval, int optlen)
  2449. {
  2450. struct icmp6_filter kfilter;
  2451. mm_segment_t old_fs;
  2452. int ret, i;
  2453. if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
  2454. return -EFAULT;
  2455. for (i = 0; i < 8; i += 2) {
  2456. u32 tmp = kfilter.data[i];
  2457. kfilter.data[i] = kfilter.data[i + 1];
  2458. kfilter.data[i + 1] = tmp;
  2459. }
  2460. old_fs = get_fs();
  2461. set_fs(KERNEL_DS);
  2462. ret = sys_setsockopt(fd, level, optname,
  2463.      (char *) &kfilter, sizeof(kfilter));
  2464. set_fs(old_fs);
  2465. return ret;
  2466. }
  2467. asmlinkage int sys32_setsockopt(int fd, int level, int optname,
  2468. char *optval, int optlen)
  2469. {
  2470. if (optname == SO_ATTACH_FILTER)
  2471. return do_set_attach_filter(fd, level, optname,
  2472.     optval, optlen);
  2473. if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
  2474. return do_set_icmpv6_filter(fd, level, optname,
  2475.     optval, optlen);
  2476. return sys_setsockopt(fd, level, optname, optval, optlen);
  2477. }
  2478. extern void check_pending(int signum);
  2479. /*
  2480.  * count32() counts the number of arguments/envelopes
  2481.  */
  2482. static int count32(u32 * argv)
  2483. {
  2484. int i = 0;
  2485. if (argv != NULL) {
  2486. for (;;) {
  2487. u32 p; int error;
  2488. error = get_user(p,argv);
  2489. if (error) return error;
  2490. if (!p) break;
  2491. argv++; i++;
  2492. }
  2493. }
  2494. return i;
  2495. }
  2496. /*
  2497.  * 'copy_string32()' copies argument/envelope strings from user
  2498.  * memory to free pages in kernel mem. These are in a format ready
  2499.  * to be put directly into the top of new user memory.
  2500.  */
  2501. static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
  2502. {
  2503. while (argc-- > 0) {
  2504. u32 str;
  2505. int len;
  2506. unsigned long pos;
  2507. if (get_user(str, argv + argc) ||
  2508.     !str ||
  2509.     !(len = strnlen_user((char *)A(str), bprm->p)))
  2510. return -EFAULT;
  2511. if (bprm->p < len)
  2512. return -E2BIG;
  2513. bprm->p -= len;
  2514. pos = bprm->p;
  2515. while (len) {
  2516. char *kaddr;
  2517. struct page *page;
  2518. int offset, bytes_to_copy, new, err;
  2519. offset = pos % PAGE_SIZE;
  2520. page = bprm->page[pos / PAGE_SIZE];
  2521. new = 0;
  2522. if (!page) {
  2523. page = alloc_page(GFP_USER);
  2524. bprm->page[pos / PAGE_SIZE] = page;
  2525. if (!page)
  2526. return -ENOMEM;
  2527. new = 1;
  2528. }
  2529. kaddr = (char *)kmap(page);
  2530. if (new && offset)
  2531. memset(kaddr, 0, offset);
  2532. bytes_to_copy = PAGE_SIZE - offset;
  2533. if (bytes_to_copy > len) {
  2534. bytes_to_copy = len;
  2535. if (new)
  2536. memset(kaddr+offset+len, 0,
  2537.        PAGE_SIZE-offset-len);
  2538. }
  2539. err = copy_from_user(kaddr + offset, (char *)A(str),
  2540.      bytes_to_copy);
  2541. flush_page_to_ram(page);
  2542. kunmap(page);
  2543. if (err)
  2544. return -EFAULT;
  2545. pos += bytes_to_copy;
  2546. str += bytes_to_copy;
  2547. len -= bytes_to_copy;
  2548. }
  2549. }
  2550. return 0;
  2551. }
  2552. /*
  2553.  * sys32_execve() executes a new program.
  2554.  */
  2555. static inline int 
  2556. do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
  2557. {
  2558. struct linux_binprm bprm;
  2559. struct file * file;
  2560. int retval;
  2561. int i;
  2562. bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
  2563. memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
  2564. file = open_exec(filename);
  2565. retval = PTR_ERR(file);
  2566. if (IS_ERR(file))
  2567. return retval;
  2568. bprm.file = file;
  2569. bprm.filename = filename;
  2570. bprm.sh_bang = 0;
  2571. bprm.loader = 0;
  2572. bprm.exec = 0;
  2573. if ((bprm.argc = count32(argv)) < 0) {
  2574. allow_write_access(file);
  2575. fput(file);
  2576. return bprm.argc;
  2577. }
  2578. if ((bprm.envc = count32(envp)) < 0) {
  2579. allow_write_access(file);
  2580. fput(file);
  2581. return bprm.envc;
  2582. }
  2583. retval = prepare_binprm(&bprm);
  2584. if (retval < 0)
  2585. goto out;
  2586. retval = copy_strings_kernel(1, &bprm.filename, &bprm);
  2587. if (retval < 0)
  2588. goto out;
  2589. bprm.exec = bprm.p;
  2590. retval = copy_strings32(bprm.envc, envp, &bprm);
  2591. if (retval < 0)
  2592. goto out;
  2593. retval = copy_strings32(bprm.argc, argv, &bprm);
  2594. if (retval < 0)
  2595. goto out;
  2596. retval = search_binary_handler(&bprm, regs);
  2597. if (retval >= 0)
  2598. /* execve success */
  2599. return retval;
  2600. out:
  2601. /* Something went wrong, return the inode and free the argument pages*/
  2602. allow_write_access(bprm.file);
  2603. if (bprm.file)
  2604. fput(bprm.file);
  2605. for (i=0 ; i<MAX_ARG_PAGES ; i++)
  2606. if (bprm.page[i])
  2607. __free_page(bprm.page[i]);
  2608. return retval;
  2609. }
  2610. /*
  2611.  * sys32_execve() executes a new program after the asm stub has set
  2612.  * things up for us.  This should basically do what I want it to.
  2613.  */
  2614. asmlinkage int
  2615. sys32_execve(struct pt_regs regs)
  2616. {
  2617.         int error;
  2618.         char * filename;
  2619.         filename = getname((char *)A(regs.orig_gpr2));
  2620.         error = PTR_ERR(filename);
  2621.         if (IS_ERR(filename))
  2622.                 goto out;
  2623.         error = do_execve32(filename, (u32 *)A(regs.gprs[3]), (u32 *)A(regs.gprs[4]), &regs);
  2624. if (error == 0)
  2625. {
  2626. current->ptrace &= ~PT_DTRACE;
  2627. current->thread.fp_regs.fpc=0;
  2628. __asm__ __volatile__
  2629.         ("sr  0,0nt"
  2630.          "sfpc 0,0nt"
  2631.  : : :"0");
  2632. }
  2633.         putname(filename);
  2634. out:
  2635.         return error;
  2636. }
  2637. #ifdef CONFIG_MODULES
  2638. extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
  2639. asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size)
  2640. {
  2641. return sys_create_module(name_user, (size_t)size);
  2642. }
  2643. extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user);
  2644. /* Hey, when you're trying to init module, take time and prepare us a nice 64bit
  2645.  * module structure, even if from 32bit modutils... Why to pollute kernel... :))
  2646.  */
  2647. asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user)
  2648. {
  2649. return sys_init_module(name_user, mod_user);
  2650. }
  2651. extern asmlinkage int sys_delete_module(const char *name_user);
  2652. asmlinkage int sys32_delete_module(const char *name_user)
  2653. {
  2654. return sys_delete_module(name_user);
  2655. }
  2656. struct module_info32 {
  2657. u32 addr;
  2658. u32 size;
  2659. u32 flags;
  2660. s32 usecount;
  2661. };
  2662. /* Query various bits about modules.  */
  2663. static inline long
  2664. get_mod_name(const char *user_name, char **buf)
  2665. {
  2666. unsigned long page;
  2667. long retval;
  2668. if ((unsigned long)user_name >= TASK_SIZE
  2669.     && !segment_eq(get_fs (), KERNEL_DS))
  2670. return -EFAULT;
  2671. page = __get_free_page(GFP_KERNEL);
  2672. if (!page)
  2673. return -ENOMEM;
  2674. retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
  2675. if (retval > 0) {
  2676. if (retval < PAGE_SIZE) {
  2677. *buf = (char *)page;
  2678. return retval;
  2679. }
  2680. retval = -ENAMETOOLONG;
  2681. } else if (!retval)
  2682. retval = -EINVAL;
  2683. free_page(page);
  2684. return retval;
  2685. }
  2686. static inline void
  2687. put_mod_name(char *buf)
  2688. {
  2689. free_page((unsigned long)buf);
  2690. }
  2691. static __inline__ struct module *find_module(const char *name)
  2692. {
  2693. struct module *mod;
  2694. for (mod = module_list; mod ; mod = mod->next) {
  2695. if (mod->flags & MOD_DELETED)
  2696. continue;
  2697. if (!strcmp(mod->name, name))
  2698. break;
  2699. }
  2700. return mod;
  2701. }
  2702. static int
  2703. qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
  2704. {
  2705. struct module *mod;
  2706. size_t nmod, space, len;
  2707. nmod = space = 0;
  2708. for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
  2709. len = strlen(mod->name)+1;
  2710. if (len > bufsize)
  2711. goto calc_space_needed;
  2712. if (copy_to_user(buf, mod->name, len))
  2713. return -EFAULT;
  2714. buf += len;
  2715. bufsize -= len;
  2716. space += len;
  2717. }
  2718. if (put_user(nmod, ret))
  2719. return -EFAULT;
  2720. else
  2721. return 0;
  2722. calc_space_needed:
  2723. space += len;
  2724. while ((mod = mod->next)->next != NULL)
  2725. space += strlen(mod->name)+1;
  2726. if (put_user(space, ret))
  2727. return -EFAULT;
  2728. else
  2729. return -ENOSPC;
  2730. }
  2731. static int
  2732. qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
  2733. {
  2734. size_t i, space, len;
  2735. if (mod->next == NULL)
  2736. return -EINVAL;
  2737. if (!MOD_CAN_QUERY(mod))
  2738. return put_user(0, ret);
  2739. space = 0;
  2740. for (i = 0; i < mod->ndeps; ++i) {
  2741. const char *dep_name = mod->deps[i].dep->name;
  2742. len = strlen(dep_name)+1;
  2743. if (len > bufsize)
  2744. goto calc_space_needed;
  2745. if (copy_to_user(buf, dep_name, len))
  2746. return -EFAULT;
  2747. buf += len;
  2748. bufsize -= len;
  2749. space += len;
  2750. }
  2751. return put_user(i, ret);
  2752. calc_space_needed:
  2753. space += len;
  2754. while (++i < mod->ndeps)
  2755. space += strlen(mod->deps[i].dep->name)+1;
  2756. if (put_user(space, ret))
  2757. return -EFAULT;
  2758. else
  2759. return -ENOSPC;
  2760. }
  2761. static int
  2762. qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
  2763. {
  2764. size_t nrefs, space, len;
  2765. struct module_ref *ref;
  2766. if (mod->next == NULL)
  2767. return -EINVAL;
  2768. if (!MOD_CAN_QUERY(mod))
  2769. if (put_user(0, ret))
  2770. return -EFAULT;
  2771. else
  2772. return 0;
  2773. space = 0;
  2774. for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
  2775. const char *ref_name = ref->ref->name;
  2776. len = strlen(ref_name)+1;
  2777. if (len > bufsize)
  2778. goto calc_space_needed;
  2779. if (copy_to_user(buf, ref_name, len))
  2780. return -EFAULT;
  2781. buf += len;
  2782. bufsize -= len;
  2783. space += len;
  2784. }
  2785. if (put_user(nrefs, ret))
  2786. return -EFAULT;
  2787. else
  2788. return 0;
  2789. calc_space_needed:
  2790. space += len;
  2791. while ((ref = ref->next_ref) != NULL)
  2792. space += strlen(ref->ref->name)+1;
  2793. if (put_user(space, ret))
  2794. return -EFAULT;
  2795. else
  2796. return -ENOSPC;
  2797. }
  2798. static inline int
  2799. qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
  2800. {
  2801. size_t i, space, len;
  2802. struct module_symbol *s;
  2803. char *strings;
  2804. unsigned *vals;
  2805. if (!MOD_CAN_QUERY(mod))
  2806. if (put_user(0, ret))
  2807. return -EFAULT;
  2808. else
  2809. return 0;
  2810. space = mod->nsyms * 2*sizeof(u32);
  2811. i = len = 0;
  2812. s = mod->syms;
  2813. if (space > bufsize)
  2814. goto calc_space_needed;
  2815. if (!access_ok(VERIFY_WRITE, buf, space))
  2816. return -EFAULT;
  2817. bufsize -= space;
  2818. vals = (unsigned *)buf;
  2819. strings = buf+space;
  2820. for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
  2821. len = strlen(s->name)+1;
  2822. if (len > bufsize)
  2823. goto calc_space_needed;
  2824. if (copy_to_user(strings, s->name, len)
  2825.     || __put_user(s->value, vals+0)
  2826.     || __put_user(space, vals+1))
  2827. return -EFAULT;
  2828. strings += len;
  2829. bufsize -= len;
  2830. space += len;
  2831. }
  2832. if (put_user(i, ret))
  2833. return -EFAULT;
  2834. else
  2835. return 0;
  2836. calc_space_needed:
  2837. for (; i < mod->nsyms; ++i, ++s)
  2838. space += strlen(s->name)+1;
  2839. if (put_user(space, ret))
  2840. return -EFAULT;
  2841. else
  2842. return -ENOSPC;
  2843. }
  2844. static inline int
  2845. qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
  2846. {
  2847. int error = 0;
  2848. if (mod->next == NULL)
  2849. return -EINVAL;
  2850. if (sizeof(struct module_info32) <= bufsize) {
  2851. struct module_info32 info;
  2852. info.addr = (unsigned long)mod;
  2853. info.size = mod->size;
  2854. info.flags = mod->flags;
  2855. info.usecount =
  2856. ((mod_member_present(mod, can_unload)
  2857.   && mod->can_unload)
  2858.  ? -1 : atomic_read(&mod->uc.usecount));
  2859. if (copy_to_user(buf, &info, sizeof(struct module_info32)))
  2860. return -EFAULT;
  2861. } else
  2862. error = -ENOSPC;
  2863. if (put_user(sizeof(struct module_info32), ret))
  2864. return -EFAULT;
  2865. return error;
  2866. }
  2867. asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret)
  2868. {
  2869. struct module *mod;
  2870. int err;
  2871. lock_kernel();
  2872. if (name_user == 0) {
  2873. /* This finds "kernel_module" which is not exported. */
  2874. for(mod = module_list; mod->next != NULL; mod = mod->next)
  2875. ;
  2876. } else {
  2877. long namelen;
  2878. char *name;
  2879. if ((namelen = get_mod_name(name_user, &name)) < 0) {
  2880. err = namelen;
  2881. goto out;
  2882. }
  2883. err = -ENOENT;
  2884. if (namelen == 0) {
  2885. /* This finds "kernel_module" which is not exported. */
  2886. for(mod = module_list; mod->next != NULL; mod = mod->next)
  2887. ;
  2888. } else if ((mod = find_module(name)) == NULL) {
  2889. put_mod_name(name);
  2890. goto out;
  2891. }
  2892. put_mod_name(name);
  2893. }
  2894. switch (which)
  2895. {
  2896. case 0:
  2897. err = 0;
  2898. break;
  2899. case QM_MODULES:
  2900. err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
  2901. break;
  2902. case QM_DEPS:
  2903. err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
  2904. break;
  2905. case QM_REFS:
  2906. err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
  2907. break;
  2908. case QM_SYMBOLS:
  2909. err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
  2910. break;
  2911. case QM_INFO:
  2912. err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
  2913. break;
  2914. default:
  2915. err = -EINVAL;
  2916. break;
  2917. }
  2918. out:
  2919. unlock_kernel();
  2920. return err;
  2921. }
  2922. struct kernel_sym32 {
  2923. u32 value;
  2924. char name[60];
  2925. };
  2926.  
  2927. extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
  2928. asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table)
  2929. {
  2930. int len, i;
  2931. struct kernel_sym *tbl;
  2932. mm_segment_t old_fs;
  2933. len = sys_get_kernel_syms(NULL);
  2934. if (!table) return len;
  2935. tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
  2936. if (!tbl) return -ENOMEM;
  2937. old_fs = get_fs();
  2938. set_fs (KERNEL_DS);
  2939. sys_get_kernel_syms(tbl);
  2940. set_fs (old_fs);
  2941. for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) {
  2942. if (put_user (tbl[i].value, &table->value) ||
  2943.     copy_to_user (table->name, tbl[i].name, 60))
  2944. break;
  2945. }
  2946. kfree (tbl);
  2947. return i;
  2948. }
  2949. #else /* CONFIG_MODULES */
  2950. asmlinkage unsigned long
  2951. sys32_create_module(const char *name_user, size_t size)
  2952. {
  2953. return -ENOSYS;
  2954. }
  2955. asmlinkage int
  2956. sys32_init_module(const char *name_user, struct module *mod_user)
  2957. {
  2958. return -ENOSYS;
  2959. }
  2960. asmlinkage int
  2961. sys32_delete_module(const char *name_user)
  2962. {
  2963. return -ENOSYS;
  2964. }
  2965. asmlinkage int
  2966. sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
  2967.  size_t *ret)
  2968. {
  2969. /* Let the program know about the new interface.  Not that
  2970.    it'll do them much good.  */
  2971. if (which == 0)
  2972. return 0;
  2973. return -ENOSYS;
  2974. }
  2975. asmlinkage int
  2976. sys32_get_kernel_syms(struct kernel_sym *table)
  2977. {
  2978. return -ENOSYS;
  2979. }
  2980. #endif  /* CONFIG_MODULES */
  2981. /* Stuff for NFS server syscalls... */
  2982. struct nfsctl_svc32 {
  2983. u16 svc32_port;
  2984. s32 svc32_nthreads;
  2985. };
  2986. struct nfsctl_client32 {
  2987. s8 cl32_ident[NFSCLNT_IDMAX+1];
  2988. s32 cl32_naddr;
  2989. struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX];
  2990. s32 cl32_fhkeytype;
  2991. s32 cl32_fhkeylen;
  2992. u8 cl32_fhkey[NFSCLNT_KEYMAX];
  2993. };
  2994. struct nfsctl_export32 {
  2995. s8 ex32_client[NFSCLNT_IDMAX+1];
  2996. s8 ex32_path[NFS_MAXPATHLEN+1];
  2997. __kernel_dev_t32 ex32_dev;
  2998. __kernel_ino_t32 ex32_ino;
  2999. s32 ex32_flags;
  3000. __kernel_uid_t32 ex32_anon_uid;
  3001. __kernel_gid_t32 ex32_anon_gid;
  3002. };
  3003. struct nfsctl_uidmap32 {
  3004. u32 ug32_ident;   /* char * */
  3005. __kernel_uid_t32 ug32_uidbase;
  3006. s32 ug32_uidlen;
  3007. u32 ug32_udimap;  /* uid_t * */
  3008. __kernel_uid_t32 ug32_gidbase;
  3009. s32 ug32_gidlen;
  3010. u32 ug32_gdimap;  /* gid_t * */
  3011. };
  3012. struct nfsctl_fhparm32 {
  3013. struct sockaddr gf32_addr;
  3014. __kernel_dev_t32 gf32_dev;
  3015. __kernel_ino_t32 gf32_ino;
  3016. s32 gf32_version;
  3017. };
  3018. struct nfsctl_fdparm32 {
  3019. struct sockaddr gd32_addr;
  3020. s8 gd32_path[NFS_MAXPATHLEN+1];
  3021. s32 gd32_version;
  3022. };
  3023. struct nfsctl_fsparm32 {
  3024. struct sockaddr gd32_addr;
  3025. s8 gd32_path[NFS_MAXPATHLEN+1];
  3026. s32 gd32_maxlen;
  3027. };
  3028. struct nfsctl_arg32 {
  3029. s32 ca32_version; /* safeguard */
  3030. union {
  3031. struct nfsctl_svc32 u32_svc;
  3032. struct nfsctl_client32 u32_client;
  3033. struct nfsctl_export32 u32_export;
  3034. struct nfsctl_uidmap32 u32_umap;
  3035. struct nfsctl_fhparm32 u32_getfh;
  3036. struct nfsctl_fdparm32 u32_getfd;
  3037. struct nfsctl_fsparm32 u32_getfs;
  3038. } u;
  3039. #define ca32_svc u.u32_svc
  3040. #define ca32_client u.u32_client
  3041. #define ca32_export u.u32_export
  3042. #define ca32_umap u.u32_umap
  3043. #define ca32_getfh u.u32_getfh
  3044. #define ca32_getfd u.u32_getfd
  3045. #define ca32_getfs u.u32_getfs
  3046. #define ca32_authd u.u32_authd
  3047. };
  3048. union nfsctl_res32 {
  3049. __u8 cr32_getfh[NFS_FHSIZE];
  3050. struct knfsd_fh cr32_getfs;
  3051. };
  3052. static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
  3053. {
  3054. int err;
  3055. err = __get_user(karg->ca_version, &arg32->ca32_version);
  3056. err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
  3057. err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
  3058. return err;
  3059. }
  3060. static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
  3061. {
  3062. int err;
  3063. err = __get_user(karg->ca_version, &arg32->ca32_version);
  3064. err |= copy_from_user(&karg->ca_client.cl_ident[0],
  3065.   &arg32->ca32_client.cl32_ident[0],
  3066.   NFSCLNT_IDMAX);
  3067. err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
  3068. err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
  3069.   &arg32->ca32_client.cl32_addrlist[0],
  3070.   (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
  3071. err |= __get_user(karg->ca_client.cl_fhkeytype,
  3072.       &arg32->ca32_client.cl32_fhkeytype);
  3073. err |= __get_user(karg->ca_client.cl_fhkeylen,
  3074.       &arg32->ca32_client.cl32_fhkeylen);
  3075. err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
  3076.   &arg32->ca32_client.cl32_fhkey[0],
  3077.   NFSCLNT_KEYMAX);
  3078. return err;
  3079. }
  3080. static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
  3081. {
  3082. int err;
  3083. err = __get_user(karg->ca_version, &arg32->ca32_version);
  3084. err |= copy_from_user(&karg->ca_export.ex_client[0],
  3085.   &arg32->ca32_export.ex32_client[0],
  3086.   NFSCLNT_IDMAX);
  3087. err |= copy_from_user(&karg->ca_export.ex_path[0],
  3088.   &arg32->ca32_export.ex32_path[0],
  3089.   NFS_MAXPATHLEN);
  3090. err |= __get_user(karg->ca_export.ex_dev,
  3091.       &arg32->ca32_export.ex32_dev);
  3092. err |= __get_user(karg->ca_export.ex_ino,
  3093.       &arg32->ca32_export.ex32_ino);
  3094. err |= __get_user(karg->ca_export.ex_flags,
  3095.       &arg32->ca32_export.ex32_flags);
  3096. err |= __get_user(karg->ca_export.ex_anon_uid,
  3097.       &arg32->ca32_export.ex32_anon_uid);
  3098. err |= __get_user(karg->ca_export.ex_anon_gid,
  3099.       &arg32->ca32_export.ex32_anon_gid);
  3100. karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
  3101. karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
  3102. return err;
  3103. }
  3104. static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
  3105. {
  3106. u32 uaddr;
  3107. int i;
  3108. int err;
  3109. memset(karg, 0, sizeof(*karg));
  3110. if(__get_user(karg->ca_version, &arg32->ca32_version))
  3111. return -EFAULT;
  3112. karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
  3113. if(!karg->ca_umap.ug_ident)
  3114. return -ENOMEM;
  3115. err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
  3116. if(strncpy_from_user(karg->ca_umap.ug_ident,
  3117.      (char *)A(uaddr), PAGE_SIZE) <= 0)
  3118. return -EFAULT;
  3119. err |= __get_user(karg->ca_umap.ug_uidbase,
  3120.       &arg32->ca32_umap.ug32_uidbase);
  3121. err |= __get_user(karg->ca_umap.ug_uidlen,
  3122.       &arg32->ca32_umap.ug32_uidlen);
  3123. err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
  3124. if (err)
  3125. return -EFAULT;
  3126. karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
  3127.   GFP_USER);
  3128. if(!karg->ca_umap.ug_udimap)
  3129. return -ENOMEM;
  3130. for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
  3131. err |= __get_user(karg->ca_umap.ug_udimap[i],
  3132.       &(((__kernel_uid_t32 *)A(uaddr))[i]));
  3133. err |= __get_user(karg->ca_umap.ug_gidbase,
  3134.       &arg32->ca32_umap.ug32_gidbase);
  3135. err |= __get_user(karg->ca_umap.ug_uidlen,
  3136.       &arg32->ca32_umap.ug32_gidlen);
  3137. err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
  3138. if (err)
  3139. return -EFAULT;
  3140. karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
  3141.   GFP_USER);
  3142. if(!karg->ca_umap.ug_gdimap)
  3143. return -ENOMEM;
  3144. for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
  3145. err |= __get_user(karg->ca_umap.ug_gdimap[i],
  3146.       &(((__kernel_gid_t32 *)A(uaddr))[i]));
  3147. return err;
  3148. }
  3149. static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
  3150. {
  3151. int err;
  3152. err = __get_user(karg->ca_version, &arg32->ca32_version);
  3153. err |= copy_from_user(&karg->ca_getfh.gf_addr,
  3154.   &arg32->ca32_getfh.gf32_addr,
  3155.   (sizeof(struct sockaddr)));
  3156. err |= __get_user(karg->ca_getfh.gf_dev,
  3157.       &arg32->ca32_getfh.gf32_dev);
  3158. err |= __get_user(karg->ca_getfh.gf_ino,
  3159.       &arg32->ca32_getfh.gf32_ino);
  3160. err |= __get_user(karg->ca_getfh.gf_version,
  3161.       &arg32->ca32_getfh.gf32_version);
  3162. return err;
  3163. }
  3164. static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
  3165. {
  3166. int err;
  3167. err = __get_user(karg->ca_version, &arg32->ca32_version);
  3168. err |= copy_from_user(&karg->ca_getfd.gd_addr,
  3169.   &arg32->ca32_getfd.gd32_addr,
  3170.   (sizeof(struct sockaddr)));
  3171. err |= copy_from_user(&karg->ca_getfd.gd_path,
  3172.   &arg32->ca32_getfd.gd32_path,
  3173.   (NFS_MAXPATHLEN+1));
  3174. err |= __get_user(karg->ca_getfd.gd_version,
  3175.       &arg32->ca32_getfd.gd32_version);
  3176. return err;
  3177. }
  3178. static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
  3179. {
  3180. int err;
  3181. err = __get_user(karg->ca_version, &arg32->ca32_version);
  3182. err |= copy_from_user(&karg->ca_getfs.gd_addr,
  3183.   &arg32->ca32_getfs.gd32_addr,
  3184.   (sizeof(struct sockaddr)));
  3185. err |= copy_from_user(&karg->ca_getfs.gd_path,
  3186.   &arg32->ca32_getfs.gd32_path,
  3187.   (NFS_MAXPATHLEN+1));
  3188. err |= __get_user(karg->ca_getfs.gd_maxlen,
  3189.       &arg32->ca32_getfs.gd32_maxlen);
  3190. return err;
  3191. }
  3192. /* This really doesn't need translations, we are only passing
  3193.  * back a union which contains opaque nfs file handle data.
  3194.  */
  3195. static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
  3196. {
  3197. return copy_to_user(res32, kres, sizeof(*res32));
  3198. }
  3199. /*
  3200. asmlinkage long sys_ni_syscall(void); 
  3201. */
  3202. int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
  3203. {
  3204. struct nfsctl_arg *karg = NULL;
  3205. union nfsctl_res *kres = NULL;
  3206. mm_segment_t oldfs;
  3207. int err;
  3208. karg = kmalloc(sizeof(*karg), GFP_USER);
  3209. if(!karg)
  3210. return -ENOMEM;
  3211. if(res32) {
  3212. kres = kmalloc(sizeof(*kres), GFP_USER);
  3213. if(!kres) {
  3214. kfree(karg);
  3215. return -ENOMEM;
  3216. }
  3217. }
  3218. switch(cmd) {
  3219. case NFSCTL_SVC:
  3220. err = nfs_svc32_trans(karg, arg32);
  3221. break;
  3222. case NFSCTL_ADDCLIENT:
  3223. err = nfs_clnt32_trans(karg, arg32);
  3224. break;
  3225. case NFSCTL_DELCLIENT:
  3226. err = nfs_clnt32_trans(karg, arg32);
  3227. break;
  3228. case NFSCTL_EXPORT:
  3229. case NFSCTL_UNEXPORT:
  3230. err = nfs_exp32_trans(karg, arg32);
  3231. break;
  3232. /* This one is unimplemented, be we're ready for it. */
  3233. case NFSCTL_UGIDUPDATE:
  3234. err = nfs_uud32_trans(karg, arg32);
  3235. break;
  3236. case NFSCTL_GETFH:
  3237. err = nfs_getfh32_trans(karg, arg32);
  3238. break;
  3239. case NFSCTL_GETFD:
  3240. err = nfs_getfd32_trans(karg, arg32);
  3241. break;
  3242. case NFSCTL_GETFS:
  3243. err = nfs_getfs32_trans(karg, arg32);
  3244. break;
  3245. default:
  3246. err = -EINVAL;
  3247. break;
  3248. }
  3249. if(err)
  3250. goto done;
  3251. oldfs = get_fs();
  3252. set_fs(KERNEL_DS);
  3253. err = sys_nfsservctl(cmd, karg, kres);
  3254. set_fs(oldfs);
  3255. if (err)
  3256. goto done;
  3257. if((cmd == NFSCTL_GETFH) ||
  3258.    (cmd == NFSCTL_GETFD) ||
  3259.    (cmd == NFSCTL_GETFS))
  3260. err = nfs_getfh32_res_trans(kres, res32);
  3261. done:
  3262. if(karg) {
  3263. if(cmd == NFSCTL_UGIDUPDATE) {
  3264. if(karg->ca_umap.ug_ident)
  3265. kfree(karg->ca_umap.ug_ident);
  3266. if(karg->ca_umap.ug_udimap)
  3267. kfree(karg->ca_umap.ug_udimap);
  3268. if(karg->ca_umap.ug_gdimap)
  3269. kfree(karg->ca_umap.ug_gdimap);
  3270. }
  3271. kfree(karg);
  3272. }
  3273. if(kres)
  3274. kfree(kres);
  3275. return err;
  3276. }
  3277. /* Translations due to time_t size differences.  Which affects all
  3278.    sorts of things, like timeval and itimerval.  */
  3279. extern struct timezone sys_tz;
  3280. extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
  3281. asmlinkage int sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
  3282. {
  3283. if (tv) {
  3284. struct timeval ktv;
  3285. do_gettimeofday(&ktv);
  3286. if (put_tv32(tv, &ktv))
  3287. return -EFAULT;
  3288. }
  3289. if (tz) {
  3290. if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
  3291. return -EFAULT;
  3292. }
  3293. return 0;
  3294. }
  3295. asmlinkage int sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
  3296. {
  3297. struct timeval ktv;
  3298. struct timezone ktz;
  3299.   if (tv) {
  3300. if (get_tv32(&ktv, tv))
  3301. return -EFAULT;
  3302. }
  3303. if (tz) {
  3304. if (copy_from_user(&ktz, tz, sizeof(ktz)))
  3305. return -EFAULT;
  3306. }
  3307. return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
  3308. }
  3309. extern int do_getitimer(int which, struct itimerval *value);
  3310. asmlinkage int sys32_getitimer(int which, struct itimerval32 *it)
  3311. {
  3312. struct itimerval kit;
  3313. int error;
  3314. error = do_getitimer(which, &kit);
  3315. if (!error && put_it32(it, &kit))
  3316. error = -EFAULT;
  3317. return error;
  3318. }
  3319. extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
  3320. asmlinkage int sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
  3321. {
  3322. struct itimerval kin, kout;
  3323. int error;
  3324. if (in) {
  3325. if (get_it32(&kin, in))
  3326. return -EFAULT;
  3327. } else
  3328. memset(&kin, 0, sizeof(kin));
  3329. error = do_setitimer(which, &kin, out ? &kout : NULL);
  3330. if (error || !out)
  3331. return error;
  3332. if (put_it32(out, &kout))
  3333. return -EFAULT;
  3334. return 0;
  3335. }
  3336. asmlinkage int sys_utimes(char *, struct timeval *);
  3337. asmlinkage int sys32_utimes(char *filename, struct timeval32 *tvs)
  3338. {
  3339. char *kfilename;
  3340. struct timeval ktvs[2];
  3341. mm_segment_t old_fs;
  3342. int ret;
  3343. kfilename = getname(filename);
  3344. ret = PTR_ERR(kfilename);
  3345. if (!IS_ERR(kfilename)) {
  3346. if (tvs) {
  3347. if (get_tv32(&ktvs[0], tvs) ||
  3348.     get_tv32(&ktvs[1], 1+tvs))
  3349. return -EFAULT;
  3350. }
  3351. old_fs = get_fs();
  3352. set_fs(KERNEL_DS);
  3353. ret = sys_utimes(kfilename, &ktvs[0]);
  3354. set_fs(old_fs);
  3355. putname(kfilename);
  3356. }
  3357. return ret;
  3358. }
  3359. /* These are here just in case some old sparc32 binary calls it. */
  3360. asmlinkage int sys32_pause(void)
  3361. {
  3362. current->state = TASK_INTERRUPTIBLE;
  3363. schedule();
  3364. return -ERESTARTNOHAND;
  3365. }
  3366. extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
  3367. unsigned long arg4, unsigned long arg5);
  3368. asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
  3369. {
  3370. return sys_prctl(option,
  3371.  (unsigned long) arg2,
  3372.  (unsigned long) arg3,
  3373.  (unsigned long) arg4,
  3374.  (unsigned long) arg5);
  3375. }
  3376. extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
  3377.     size_t count, loff_t pos);
  3378. extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
  3379.      size_t count, loff_t pos);
  3380. typedef __kernel_ssize_t32 ssize_t32;
  3381. asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
  3382.  __kernel_size_t32 count, u32 poshi, u32 poslo)
  3383. {
  3384. return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
  3385. }
  3386. asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
  3387.   __kernel_size_t32 count, u32 poshi, u32 poslo)
  3388. {
  3389. return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
  3390. }
  3391. extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
  3392. asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
  3393. {
  3394. mm_segment_t old_fs = get_fs();
  3395. int ret;
  3396. off_t of;
  3397. if (offset && get_user(of, offset))
  3398. return -EFAULT;
  3399. set_fs(KERNEL_DS);
  3400. ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
  3401. set_fs(old_fs);
  3402. if (!ret && offset && put_user(of, offset))
  3403. return -EFAULT;
  3404. return ret;
  3405. }
  3406. /* Handle adjtimex compatability. */
  3407. struct timex32 {
  3408. u32 modes;
  3409. s32 offset, freq, maxerror, esterror;
  3410. s32 status, constant, precision, tolerance;
  3411. struct timeval32 time;
  3412. s32 tick;
  3413. s32 ppsfreq, jitter, shift, stabil;
  3414. s32 jitcnt, calcnt, errcnt, stbcnt;
  3415. s32  :32; s32  :32; s32  :32; s32  :32;
  3416. s32  :32; s32  :32; s32  :32; s32  :32;
  3417. s32  :32; s32  :32; s32  :32; s32  :32;
  3418. };
  3419. extern int do_adjtimex(struct timex *);
  3420. asmlinkage int sys32_adjtimex(struct timex32 *utp)
  3421. {
  3422. struct timex txc;
  3423. int ret;
  3424. memset(&txc, 0, sizeof(struct timex));
  3425. if(get_user(txc.modes, &utp->modes) ||
  3426.    __get_user(txc.offset, &utp->offset) ||
  3427.    __get_user(txc.freq, &utp->freq) ||
  3428.    __get_user(txc.maxerror, &utp->maxerror) ||
  3429.    __get_user(txc.esterror, &utp->esterror) ||
  3430.    __get_user(txc.status, &utp->status) ||
  3431.    __get_user(txc.constant, &utp->constant) ||
  3432.    __get_user(txc.precision, &utp->precision) ||
  3433.    __get_user(txc.tolerance, &utp->tolerance) ||
  3434.    __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
  3435.    __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
  3436.    __get_user(txc.tick, &utp->tick) ||
  3437.    __get_user(txc.ppsfreq, &utp->ppsfreq) ||
  3438.    __get_user(txc.jitter, &utp->jitter) ||
  3439.    __get_user(txc.shift, &utp->shift) ||
  3440.    __get_user(txc.stabil, &utp->stabil) ||
  3441.    __get_user(txc.jitcnt, &utp->jitcnt) ||
  3442.    __get_user(txc.calcnt, &utp->calcnt) ||
  3443.    __get_user(txc.errcnt, &utp->errcnt) ||
  3444.    __get_user(txc.stbcnt, &utp->stbcnt))
  3445. return -EFAULT;
  3446. ret = do_adjtimex(&txc);
  3447. if(put_user(txc.modes, &utp->modes) ||
  3448.    __put_user(txc.offset, &utp->offset) ||
  3449.    __put_user(txc.freq, &utp->freq) ||
  3450.    __put_user(txc.maxerror, &utp->maxerror) ||
  3451.    __put_user(txc.esterror, &utp->esterror) ||
  3452.    __put_user(txc.status, &utp->status) ||
  3453.    __put_user(txc.constant, &utp->constant) ||
  3454.    __put_user(txc.precision, &utp->precision) ||
  3455.    __put_user(txc.tolerance, &utp->tolerance) ||
  3456.    __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
  3457.    __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
  3458.    __put_user(txc.tick, &utp->tick) ||
  3459.    __put_user(txc.ppsfreq, &utp->ppsfreq) ||
  3460.    __put_user(txc.jitter, &utp->jitter) ||
  3461.    __put_user(txc.shift, &utp->shift) ||
  3462.    __put_user(txc.stabil, &utp->stabil) ||
  3463.    __put_user(txc.jitcnt, &utp->jitcnt) ||
  3464.    __put_user(txc.calcnt, &utp->calcnt) ||
  3465.    __put_user(txc.errcnt, &utp->errcnt) ||
  3466.    __put_user(txc.stbcnt, &utp->stbcnt))
  3467. ret = -EFAULT;
  3468. return ret;
  3469. }
  3470. extern asmlinkage long sys_setpriority(int which, int who, int niceval);
  3471. asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
  3472. {
  3473. return sys_setpriority((int) which,
  3474.        (int) who,
  3475.        (int) niceval);
  3476. }
  3477. struct __sysctl_args32 {
  3478. u32 name;
  3479. int nlen;
  3480. u32 oldval;
  3481. u32 oldlenp;
  3482. u32 newval;
  3483. u32 newlen;
  3484. u32 __unused[4];
  3485. };
  3486. extern asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
  3487. {
  3488. struct __sysctl_args32 tmp;
  3489. int error;
  3490. size_t oldlen, *oldlenp = NULL;
  3491. unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
  3492. if (copy_from_user(&tmp, args, sizeof(tmp)))
  3493. return -EFAULT;
  3494. if (tmp.oldval && tmp.oldlenp) {
  3495. /* Duh, this is ugly and might not work if sysctl_args
  3496.    is in read-only memory, but do_sysctl does indirectly
  3497.    a lot of uaccess in both directions and we'd have to
  3498.    basically copy the whole sysctl.c here, and
  3499.    glibc's __sysctl uses rw memory for the structure
  3500.    anyway.  */
  3501. if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
  3502.     put_user(oldlen, (size_t *)addr))
  3503. return -EFAULT;
  3504. oldlenp = (size_t *)addr;
  3505. }
  3506. lock_kernel();
  3507. error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
  3508.   oldlenp, (void *)A(tmp.newval), tmp.newlen);
  3509. unlock_kernel();
  3510. if (oldlenp) {
  3511. if (!error) {
  3512. if (get_user(oldlen, (size_t *)addr) ||
  3513.     put_user(oldlen, (u32 *)A(tmp.oldlenp)))
  3514. error = -EFAULT;
  3515. }
  3516. copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
  3517. }
  3518. return error;
  3519. }
  3520. struct stat64_emu31 {
  3521. unsigned char   __pad0[6];
  3522. unsigned short  st_dev;
  3523. unsigned int    __pad1;
  3524. #define STAT64_HAS_BROKEN_ST_INO        1
  3525. u32             __st_ino;
  3526. unsigned int    st_mode;
  3527. unsigned int    st_nlink;
  3528. u32             st_uid;
  3529. u32             st_gid;
  3530. unsigned char   __pad2[6];
  3531. unsigned short  st_rdev;
  3532. unsigned int    __pad3;
  3533. long            st_size;
  3534. u32             st_blksize;
  3535. unsigned char   __pad4[4];
  3536. u32             __pad5;     /* future possible st_blocks high bits */
  3537. u32             st_blocks;  /* Number 512-byte blocks allocated. */
  3538. u32             st_atime;
  3539. u32             __pad6;
  3540. u32             st_mtime;
  3541. u32             __pad7;
  3542. u32             st_ctime;
  3543. u32             __pad8;     /* will be high 32 bits of ctime someday */
  3544. unsigned long   st_ino;
  3545. };
  3546. static inline int
  3547. putstat64 (struct stat64_emu31 *ubuf, struct stat *kbuf)
  3548. {
  3549.     struct stat64_emu31 tmp;
  3550.    
  3551.     memset(&tmp, 0, sizeof(tmp));
  3552.     tmp.st_dev = (unsigned short)kbuf->st_dev;
  3553.     tmp.st_ino = kbuf->st_ino;
  3554.     tmp.__st_ino = (u32)kbuf->st_ino;
  3555.     tmp.st_mode = kbuf->st_mode;
  3556.     tmp.st_nlink = (unsigned int)kbuf->st_nlink;
  3557.     tmp.st_uid = kbuf->st_uid;
  3558.     tmp.st_gid = kbuf->st_gid;
  3559.     tmp.st_rdev = (unsigned short)kbuf->st_rdev;
  3560.     tmp.st_size = kbuf->st_size;
  3561.     tmp.st_blksize = (u32)kbuf->st_blksize;
  3562.     tmp.st_blocks = (u32)kbuf->st_blocks;
  3563.     tmp.st_atime = (u32)kbuf->st_atime;
  3564.     tmp.st_mtime = (u32)kbuf->st_mtime;
  3565.     tmp.st_ctime = (u32)kbuf->st_ctime;
  3566.     return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 
  3567. }
  3568. extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
  3569. asmlinkage long sys32_stat64(char * filename, struct stat64_emu31 * statbuf, long flags)
  3570. {
  3571.     int ret;
  3572.     struct stat s;
  3573.     char * tmp;
  3574.     int err;
  3575.     mm_segment_t old_fs = get_fs();
  3576.     
  3577.     tmp = getname(filename);
  3578.     err = PTR_ERR(tmp);
  3579.     if (IS_ERR(tmp))   
  3580.     return err;
  3581.     set_fs (KERNEL_DS);
  3582.     ret = sys_newstat(tmp, &s);
  3583.     set_fs (old_fs);
  3584.     putname(tmp);
  3585.     if (putstat64 (statbuf, &s)) 
  3586.     return -EFAULT;
  3587.     return ret;
  3588. }
  3589. extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
  3590. asmlinkage long sys32_lstat64(char * filename, struct stat64_emu31 * statbuf, long flags)
  3591. {
  3592.     int ret;
  3593.     struct stat s;
  3594.     char * tmp;
  3595.     int err;
  3596.     mm_segment_t old_fs = get_fs();
  3597.     
  3598.     tmp = getname(filename);
  3599.     err = PTR_ERR(tmp);
  3600.     if (IS_ERR(tmp))   
  3601.     return err;
  3602.     set_fs (KERNEL_DS);
  3603.     ret = sys_newlstat(tmp, &s);
  3604.     set_fs (old_fs);
  3605.     putname(tmp);
  3606.     if (putstat64 (statbuf, &s)) 
  3607.     return -EFAULT;
  3608.     return ret;
  3609. }
  3610. extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
  3611. asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 * statbuf, long flags)
  3612. {
  3613.     int ret;
  3614.     struct stat s;
  3615.     mm_segment_t old_fs = get_fs();
  3616.     
  3617.     set_fs (KERNEL_DS);
  3618.     ret = sys_newfstat(fd, &s);
  3619.     set_fs (old_fs);
  3620.     if (putstat64 (statbuf, &s))
  3621.     return -EFAULT;
  3622.     return ret;
  3623. }
  3624. /*
  3625.  * Linux/i386 didn't use to be able to handle more than
  3626.  * 4 system call parameters, so these system calls used a memory
  3627.  * block for parameter passing..
  3628.  */
  3629. struct mmap_arg_struct_emu31 {
  3630. u32 addr;
  3631. u32 len;
  3632. u32 prot;
  3633. u32 flags;
  3634. u32 fd;
  3635. u32 offset;
  3636. };
  3637. /* common code for old and new mmaps */
  3638. static inline long do_mmap2(
  3639. unsigned long addr, unsigned long len,
  3640. unsigned long prot, unsigned long flags,
  3641. unsigned long fd, unsigned long pgoff)
  3642. {
  3643. struct file * file = NULL;
  3644. unsigned long error = -EBADF;
  3645. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  3646. if (!(flags & MAP_ANONYMOUS)) {
  3647. file = fget(fd);
  3648. if (!file)
  3649. goto out;
  3650. }
  3651. down_write(&current->mm->mmap_sem);
  3652. error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  3653. if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) {
  3654. /* Result is out of bounds.  */
  3655. do_munmap(current->mm, addr, len);
  3656. error = -ENOMEM;
  3657. }
  3658. up_write(&current->mm->mmap_sem);
  3659. if (file)
  3660. fput(file);
  3661. out:    
  3662. return error;
  3663. }
  3664. asmlinkage unsigned long
  3665. old32_mmap(struct mmap_arg_struct_emu31 *arg)
  3666. {
  3667. struct mmap_arg_struct_emu31 a;
  3668. int error = -EFAULT;
  3669. if (copy_from_user(&a, arg, sizeof(a)))
  3670. goto out;
  3671. error = -EINVAL;
  3672. if (a.offset & ~PAGE_MASK)
  3673. goto out;
  3674. error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); 
  3675. out:
  3676. return error;
  3677. }
  3678. asmlinkage long 
  3679. sys32_mmap2(struct mmap_arg_struct_emu31 *arg)
  3680. {
  3681. struct mmap_arg_struct_emu31 a;
  3682. int error = -EFAULT;
  3683. if (copy_from_user(&a, arg, sizeof(a)))
  3684. goto out;
  3685. error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
  3686. out:
  3687. return error;
  3688. }
  3689. extern asmlinkage long sys_socket(int family, int type, int protocol);
  3690. extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
  3691. extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
  3692. extern asmlinkage long sys_listen(int fd, int backlog);
  3693. extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen);
  3694. extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len);
  3695. extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len);
  3696. extern asmlinkage long sys_socketpair(int family, int type, int protocol, int usockvec[2]);
  3697. extern asmlinkage long sys_send(int fd, void * buff, size_t len, unsigned flags);
  3698. extern asmlinkage long sys_sendto(int fd, void * buff, size_t len, unsigned flags,
  3699.                            struct sockaddr *addr, int addr_len);
  3700. extern asmlinkage long sys_recv(int fd, void * ubuf, size_t size, unsigned flags);
  3701. extern asmlinkage long sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags,
  3702.                              struct sockaddr *addr, int *addr_len);
  3703. extern asmlinkage long sys_shutdown(int fd, int how);
  3704. extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int * optlen);
  3705. /* Argument list sizes for sys_socketcall */
  3706. #define AL(x) ((x) * sizeof(u32))
  3707. static unsigned char nas[18] = {AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
  3708.                                 AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
  3709.                                 AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
  3710. #undef AL
  3711. asmlinkage long sys32_socketcall(int call, u32 *args)
  3712. {
  3713. int ret;
  3714. u32 a[6];
  3715.  
  3716. if (call < SYS_SOCKET || call > SYS_RECVMSG)
  3717. return -EINVAL;
  3718. if (copy_from_user(a, args, nas[call]))
  3719. return -EFAULT;
  3720. switch(call) {
  3721. case SYS_SOCKET:
  3722. ret = sys_socket(a[0], a[1], a[2]);
  3723. break;
  3724. case SYS_BIND:
  3725. ret = sys_bind(a[0], (struct sockaddr *) A(a[1]), a[2]);
  3726. break;
  3727. case SYS_CONNECT:
  3728. ret = sys_connect(a[0], (struct sockaddr *) A(a[1]), a[2]);
  3729. break;
  3730. case SYS_LISTEN:
  3731. ret = sys_listen(a[0], a[1]);
  3732. break;
  3733. case SYS_ACCEPT:
  3734. ret = sys_accept(a[0], (struct sockaddr *) A(a[1]),
  3735.  (int *) A(a[2]));
  3736. break;
  3737. case SYS_GETSOCKNAME:
  3738. ret = sys_getsockname(a[0], (struct sockaddr *) A(a[1]),
  3739.       (int *) A(a[2]));
  3740. break;
  3741. case SYS_GETPEERNAME:
  3742. ret = sys_getpeername(a[0], (struct sockaddr *) A(a[1]),
  3743.       (int *) A(a[2]));
  3744. break;
  3745. case SYS_SOCKETPAIR:
  3746. ret = sys_socketpair(a[0], a[1], a[2], (int *) A(a[3]));
  3747. break;
  3748. case SYS_SEND:
  3749. ret = sys_send(a[0], (void *) A(a[1]), a[2], a[3]);
  3750. break;
  3751. case SYS_SENDTO:
  3752. ret = sys_sendto(a[0], (void*) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), a[5]);
  3753. break;
  3754. case SYS_RECV:
  3755. ret = sys_recv(a[0], (void *) A(a[1]), a[2], a[3]);
  3756. break;
  3757. case SYS_RECVFROM:
  3758. ret = sys_recvfrom(a[0], (void *) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), (int *) A(a[5]) );
  3759. break;
  3760. case SYS_SHUTDOWN:
  3761. ret = sys_shutdown(a[0], a[1]);
  3762. break;
  3763. case SYS_SETSOCKOPT:
  3764. ret = sys32_setsockopt(a[0], a[1], a[2], (char *) A(a[3]),
  3765.      a[4]);
  3766. break;
  3767. case SYS_GETSOCKOPT:
  3768. ret = sys_getsockopt(a[0], a[1], a[2], (char *) A(a[3]), (int *) A(a[4]) );
  3769. break;
  3770. case SYS_SENDMSG:
  3771. ret = sys32_sendmsg(a[0], (struct msghdr32 *) A(a[1]),
  3772.     a[2]);
  3773. break;
  3774. case SYS_RECVMSG:
  3775. ret = sys32_recvmsg(a[0], (struct msghdr32 *) A(a[1]),
  3776.     a[2]);
  3777. break;
  3778. default:
  3779. ret = EINVAL;
  3780. break;
  3781. }
  3782. return ret;
  3783. }