ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / sparc64 / kernel / sys_sparc32.c
1 /* $Id: sys_sparc32.c,v 1.184 2002/02/09 19:49:31 davem Exp $
2  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
3  *
4  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
6  *
7  * These routines maintain argument size conversion between 32bit and 64bit
8  * environment.
9  */
10
11 #include <linux/config.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/fs.h> 
15 #include <linux/mm.h> 
16 #include <linux/file.h> 
17 #include <linux/signal.h>
18 #include <linux/resource.h>
19 #include <linux/times.h>
20 #include <linux/utsname.h>
21 #include <linux/timex.h>
22 #include <linux/smp.h>
23 #include <linux/smp_lock.h>
24 #include <linux/sem.h>
25 #include <linux/msg.h>
26 #include <linux/shm.h>
27 #include <linux/slab.h>
28 #include <linux/uio.h>
29 #include <linux/nfs_fs.h>
30 #include <linux/quota.h>
31 #include <linux/module.h>
32 #include <linux/sunrpc/svc.h>
33 #include <linux/nfsd/nfsd.h>
34 #include <linux/nfsd/cache.h>
35 #include <linux/nfsd/xdr.h>
36 #include <linux/nfsd/syscall.h>
37 #include <linux/poll.h>
38 #include <linux/personality.h>
39 #include <linux/stat.h>
40 #include <linux/filter.h>
41 #include <linux/highmem.h>
42 #include <linux/highuid.h>
43 #include <linux/mman.h>
44 #include <linux/ipv6.h>
45 #include <linux/in.h>
46 #include <linux/icmpv6.h>
47 #include <linux/syscalls.h>
48 #include <linux/sysctl.h>
49 #include <linux/binfmts.h>
50 #include <linux/dnotify.h>
51 #include <linux/security.h>
52 #include <linux/compat.h>
53 #include <linux/vfs.h>
54 #include <linux/netfilter_ipv4/ip_tables.h>
55 #include <linux/ptrace.h>
56 #include <linux/highuid.h>
57
58 #include <asm/types.h>
59 #include <asm/ipc.h>
60 #include <asm/uaccess.h>
61 #include <asm/fpumacro.h>
62 #include <asm/semaphore.h>
63 #include <asm/mmu_context.h>
64
65 /* Use this to get at 32-bit user passed pointers. */
66 /* Things to consider: the low-level assembly stub does
67    srl x, 0, x for first four arguments, so if you have
68    pointer to something in the first four arguments, just
69    declare it as a pointer, not u32. On the other side, 
70    arguments from 5th onwards should be declared as u32
71    for pointers, and need AA() around each usage.
72    A() macro should be used for places where you e.g.
73    have some internal variable u32 and just want to get
74    rid of a compiler warning. AA() has to be used in
75    places where you want to convert a function argument
76    to 32bit pointer or when you e.g. access pt_regs
77    structure and want to consider 32bit registers only.
78    -jj
79  */
80 #define A(__x) ((unsigned long)(__x))
81 #define AA(__x)                         \
82 ({      unsigned long __ret;            \
83         __asm__ ("srl   %0, 0, %0"      \
84                  : "=r" (__ret)         \
85                  : "0" (__x));          \
86         __ret;                          \
87 })
88
89  
90 asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
91 {
92         return sys_chown(filename, low2highuid(user), low2highgid(group));
93 }
94
95 asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
96 {
97         return sys_lchown(filename, low2highuid(user), low2highgid(group));
98 }
99
100 asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
101 {
102         return sys_fchown(fd, low2highuid(user), low2highgid(group));
103 }
104
105 asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
106 {
107         return sys_setregid(low2highgid(rgid), low2highgid(egid));
108 }
109
110 asmlinkage long sys32_setgid16(u16 gid)
111 {
112         return sys_setgid((gid_t)gid);
113 }
114
115 asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
116 {
117         return sys_setreuid(low2highuid(ruid), low2highuid(euid));
118 }
119
120 asmlinkage long sys32_setuid16(u16 uid)
121 {
122         return sys_setuid((uid_t)uid);
123 }
124
125 asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
126 {
127         return sys_setresuid(low2highuid(ruid), low2highuid(euid),
128                 low2highuid(suid));
129 }
130
131 asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid)
132 {
133         int retval;
134
135         if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
136             !(retval = put_user(high2lowuid(current->euid), euid)))
137                 retval = put_user(high2lowuid(current->suid), suid);
138
139         return retval;
140 }
141
142 asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
143 {
144         return sys_setresgid(low2highgid(rgid), low2highgid(egid),
145                 low2highgid(sgid));
146 }
147
148 asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid)
149 {
150         int retval;
151
152         if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
153             !(retval = put_user(high2lowgid(current->egid), egid)))
154                 retval = put_user(high2lowgid(current->sgid), sgid);
155
156         return retval;
157 }
158
159 asmlinkage long sys32_setfsuid16(u16 uid)
160 {
161         return sys_setfsuid((uid_t)uid);
162 }
163
164 asmlinkage long sys32_setfsgid16(u16 gid)
165 {
166         return sys_setfsgid((gid_t)gid);
167 }
168
169 static int groups16_to_user(u16 *grouplist, struct group_info *group_info)
170 {
171         int i;
172         u16 group;
173
174         for (i = 0; i < group_info->ngroups; i++) {
175                 group = (u16)GROUP_AT(group_info, i);
176                 if (put_user(group, grouplist+i))
177                         return -EFAULT;
178         }
179
180         return 0;
181 }
182
183 static int groups16_from_user(struct group_info *group_info, u16 *grouplist)
184 {
185         int i;
186         u16 group;
187
188         for (i = 0; i < group_info->ngroups; i++) {
189                 if (get_user(group, grouplist+i))
190                         return  -EFAULT;
191                 GROUP_AT(group_info, i) = (gid_t)group;
192         }
193
194         return 0;
195 }
196
197 asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
198 {
199         int i;
200
201         if (gidsetsize < 0)
202                 return -EINVAL;
203
204         get_group_info(current->group_info);
205         i = current->group_info->ngroups;
206         if (gidsetsize) {
207                 if (i > gidsetsize) {
208                         i = -EINVAL;
209                         goto out;
210                 }
211                 if (groups16_to_user(grouplist, current->group_info)) {
212                         i = -EFAULT;
213                         goto out;
214                 }
215         }
216 out:
217         put_group_info(current->group_info);
218         return i;
219 }
220
221 asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
222 {
223         struct group_info *group_info;
224         int retval;
225
226         if (!capable(CAP_SETGID))
227                 return -EPERM;
228         if ((unsigned)gidsetsize > NGROUPS_MAX)
229                 return -EINVAL;
230
231         group_info = groups_alloc(gidsetsize);
232         if (!group_info)
233                 return -ENOMEM;
234         retval = groups16_from_user(group_info, grouplist);
235         if (retval) {
236                 put_group_info(group_info);
237                 return retval;
238         }
239
240         retval = set_current_groups(group_info);
241         put_group_info(group_info);
242
243         return retval;
244 }
245
246 asmlinkage long sys32_getuid16(void)
247 {
248         return high2lowuid(current->uid);
249 }
250
251 asmlinkage long sys32_geteuid16(void)
252 {
253         return high2lowuid(current->euid);
254 }
255
256 asmlinkage long sys32_getgid16(void)
257 {
258         return high2lowgid(current->gid);
259 }
260
261 asmlinkage long sys32_getegid16(void)
262 {
263         return high2lowgid(current->egid);
264 }
265
266 /* 32-bit timeval and related flotsam.  */
267
268 static long get_tv32(struct timeval *o, struct compat_timeval *i)
269 {
270         return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||
271                 (__get_user(o->tv_sec, &i->tv_sec) |
272                  __get_user(o->tv_usec, &i->tv_usec)));
273 }
274
275 static inline long put_tv32(struct compat_timeval *o, struct timeval *i)
276 {
277         return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
278                 (__put_user(i->tv_sec, &o->tv_sec) |
279                  __put_user(i->tv_usec, &o->tv_usec)));
280 }
281
282 struct msgbuf32 { s32 mtype; char mtext[1]; };
283
284 struct ipc_perm32
285 {
286         key_t             key;
287         compat_uid_t  uid;
288         compat_gid_t  gid;
289         compat_uid_t  cuid;
290         compat_gid_t  cgid;
291         compat_mode_t mode;
292         unsigned short  seq;
293 };
294
295 struct semid_ds32 {
296         struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
297         compat_time_t   sem_otime;              /* last semop time */
298         compat_time_t   sem_ctime;              /* last change time */
299         u32 sem_base;              /* ptr to first semaphore in array */
300         u32 sem_pending;          /* pending operations to be processed */
301         u32 sem_pending_last;    /* last pending operation */
302         u32 undo;                  /* undo requests on this array */
303         unsigned short  sem_nsems;              /* no. of semaphores in array */
304 };
305
306 struct semid64_ds32 {
307         struct ipc64_perm sem_perm;               /* this structure is the same on sparc32 and sparc64 */
308         unsigned int      __pad1;
309         compat_time_t   sem_otime;
310         unsigned int      __pad2;
311         compat_time_t   sem_ctime;
312         u32 sem_nsems;
313         u32 __unused1;
314         u32 __unused2;
315 };
316
317 struct msqid_ds32
318 {
319         struct ipc_perm32 msg_perm;
320         u32 msg_first;
321         u32 msg_last;
322         compat_time_t   msg_stime;
323         compat_time_t   msg_rtime;
324         compat_time_t   msg_ctime;
325         u32 wwait;
326         u32 rwait;
327         unsigned short msg_cbytes;
328         unsigned short msg_qnum;  
329         unsigned short msg_qbytes;
330         compat_ipc_pid_t msg_lspid;
331         compat_ipc_pid_t msg_lrpid;
332 };
333
334 struct msqid64_ds32 {
335         struct ipc64_perm msg_perm;
336         unsigned int   __pad1;
337         compat_time_t   msg_stime;
338         unsigned int   __pad2;
339         compat_time_t   msg_rtime;
340         unsigned int   __pad3;
341         compat_time_t   msg_ctime;
342         unsigned int  msg_cbytes;
343         unsigned int  msg_qnum;
344         unsigned int  msg_qbytes;
345         compat_pid_t msg_lspid;
346         compat_pid_t msg_lrpid;
347         unsigned int  __unused1;
348         unsigned int  __unused2;
349 };
350
351
352 struct shmid_ds32 {
353         struct ipc_perm32       shm_perm;
354         int                     shm_segsz;
355         compat_time_t         shm_atime;
356         compat_time_t         shm_dtime;
357         compat_time_t         shm_ctime;
358         compat_ipc_pid_t    shm_cpid; 
359         compat_ipc_pid_t    shm_lpid; 
360         unsigned short          shm_nattch;
361 };
362
363 struct shmid64_ds32 {
364         struct ipc64_perm       shm_perm;
365         unsigned int            __pad1;
366         compat_time_t   shm_atime;
367         unsigned int            __pad2;
368         compat_time_t   shm_dtime;
369         unsigned int            __pad3;
370         compat_time_t   shm_ctime;
371         compat_size_t   shm_segsz;
372         compat_pid_t    shm_cpid;
373         compat_pid_t    shm_lpid;
374         unsigned int            shm_nattch;
375         unsigned int            __unused1;
376         unsigned int            __unused2;
377 };
378
379                                                         
380 /*
381  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
382  *
383  * This is really horribly ugly.
384  */
385 #define IPCOP_MASK(__x) (1UL << ((__x)&~IPC_64))
386 static int do_sys32_semctl(int first, int second, int third, void *uptr)
387 {
388         union semun fourth;
389         u32 pad;
390         int err = -EINVAL;
391
392         if (!uptr)
393                 goto out;
394         err = -EFAULT;
395         if (get_user (pad, (u32 *)uptr))
396                 goto out;
397         if ((third & ~IPC_64) == SETVAL)
398                 fourth.val = (int)pad;
399         else
400                 fourth.__pad = (void *)A(pad);
401         if (IPCOP_MASK (third) &
402             (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
403              IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
404              IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {
405                 err = sys_semctl (first, second, third, fourth);
406         } else if (third & IPC_64) {
407                 struct semid64_ds s;
408                 struct semid64_ds32 *usp = (struct semid64_ds32 *)A(pad);
409                 mm_segment_t old_fs;
410                 int need_back_translation;
411
412                 if (third == (IPC_SET|IPC_64)) {
413                         err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
414                         err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
415                         err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
416                         if (err)
417                                 goto out;
418                         fourth.__pad = &s;
419                 }
420                 need_back_translation =
421                         (IPCOP_MASK (third) &
422                          (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
423                 if (need_back_translation)
424                         fourth.__pad = &s;
425                 old_fs = get_fs ();
426                 set_fs (KERNEL_DS);
427                 err = sys_semctl (first, second, third, fourth);
428                 set_fs (old_fs);
429                 if (need_back_translation) {
430                         int err2 = copy_to_user (&usp->sem_perm, &s.sem_perm, sizeof(struct ipc64_perm) + 2*sizeof(time_t));
431                         err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
432                         if (err2) err = -EFAULT;
433                 }
434         } else {
435                 struct semid_ds s;
436                 struct semid_ds32 *usp = (struct semid_ds32 *)A(pad);
437                 mm_segment_t old_fs;
438                 int need_back_translation;
439
440                 if (third == IPC_SET) {
441                         err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
442                         err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
443                         err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
444                         if (err)
445                                 goto out;
446                         fourth.__pad = &s;
447                 }
448                 need_back_translation =
449                         (IPCOP_MASK (third) &
450                          (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
451                 if (need_back_translation)
452                         fourth.__pad = &s;
453                 old_fs = get_fs ();
454                 set_fs (KERNEL_DS);
455                 err = sys_semctl (first, second, third, fourth);
456                 set_fs (old_fs);
457                 if (need_back_translation) {
458                         int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
459                         err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
460                         err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
461                         err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
462                         err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
463                         err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
464                         err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
465                         err2 |= __put_user (s.sem_otime, &usp->sem_otime);
466                         err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
467                         err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
468                         if (err2) err = -EFAULT;
469                 }
470         }
471 out:
472         return err;
473 }
474
475 static int do_sys32_msgsnd (int first, int second, int third, void *uptr)
476 {
477         struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
478         struct msgbuf32 *up = (struct msgbuf32 *)uptr;
479         mm_segment_t old_fs;
480         int err;
481
482         if (!p)
483                 return -ENOMEM;
484         err = -EFAULT;
485         if (get_user (p->mtype, &up->mtype) ||
486             __copy_from_user (p->mtext, &up->mtext, second))
487                 goto out;
488         old_fs = get_fs ();
489         set_fs (KERNEL_DS);
490         err = sys_msgsnd (first, p, second, third);
491         set_fs (old_fs);
492 out:
493         kfree (p);
494         return err;
495 }
496
497 static int do_sys32_msgrcv (int first, int second, int msgtyp, int third,
498                             int version, void *uptr)
499 {
500         struct msgbuf32 *up;
501         struct msgbuf *p;
502         mm_segment_t old_fs;
503         int err;
504
505         if (!version) {
506                 struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
507                 struct ipc_kludge ipck;
508
509                 err = -EINVAL;
510                 if (!uptr)
511                         goto out;
512                 err = -EFAULT;
513                 if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge)))
514                         goto out;
515                 uptr = (void *)A(ipck.msgp);
516                 msgtyp = ipck.msgtyp;
517         }
518         err = -ENOMEM;
519         p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
520         if (!p)
521                 goto out;
522         old_fs = get_fs ();
523         set_fs (KERNEL_DS);
524         err = sys_msgrcv (first, p, second, msgtyp, third);
525         set_fs (old_fs);
526         if (err < 0)
527                 goto free_then_out;
528         up = (struct msgbuf32 *)uptr;
529         if (put_user (p->mtype, &up->mtype) ||
530             __copy_to_user (&up->mtext, p->mtext, err))
531                 err = -EFAULT;
532 free_then_out:
533         kfree (p);
534 out:
535         return err;
536 }
537
538 static int do_sys32_msgctl (int first, int second, void *uptr)
539 {
540         int err;
541
542         if (IPCOP_MASK (second) &
543             (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
544              IPCOP_MASK (IPC_RMID))) {
545                 err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
546         } else if (second & IPC_64) {
547                 struct msqid64_ds m;
548                 struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr;
549                 mm_segment_t old_fs;
550
551                 if (second == (IPC_SET|IPC_64)) {
552                         err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
553                         err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
554                         err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
555                         err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
556                         if (err)
557                                 goto out;
558                 }
559                 old_fs = get_fs ();
560                 set_fs (KERNEL_DS);
561                 err = sys_msgctl (first, second, (struct msqid_ds *)&m);
562                 set_fs (old_fs);
563                 if (IPCOP_MASK (second) &
564                     (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
565                         int err2 = copy_to_user(&up->msg_perm, &m.msg_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
566                         err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
567                         err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
568                         err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
569                         err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
570                         err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
571                         if (err2)
572                                 err = -EFAULT;
573                 }
574         } else {
575                 struct msqid_ds m;
576                 struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
577                 mm_segment_t old_fs;
578
579                 if (second == IPC_SET) {
580                         err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
581                         err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
582                         err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
583                         err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
584                         if (err)
585                                 goto out;
586                 }
587                 old_fs = get_fs ();
588                 set_fs (KERNEL_DS);
589                 err = sys_msgctl (first, second, &m);
590                 set_fs (old_fs);
591                 if (IPCOP_MASK (second) &
592                     (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
593                         int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
594                         err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
595                         err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
596                         err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
597                         err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
598                         err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
599                         err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
600                         err2 |= __put_user (m.msg_stime, &up->msg_stime);
601                         err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
602                         err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
603                         err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
604                         err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
605                         err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
606                         err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
607                         err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
608                         if (err2)
609                                 err = -EFAULT;
610                 }
611         }
612
613 out:
614         return err;
615 }
616
617 static int do_sys32_shmat (int first, int second, int third, int version, void *uptr)
618 {
619         unsigned long raddr;
620         u32 *uaddr = (u32 *)A((u32)third);
621         int err = -EINVAL;
622
623         if (version == 1)
624                 goto out;
625         err = do_shmat (first, uptr, second, &raddr);
626         if (err)
627                 goto out;
628         err = put_user (raddr, uaddr);
629 out:
630         return err;
631 }
632
633 static int do_sys32_shmctl (int first, int second, void *uptr)
634 {
635         int err;
636
637         if (IPCOP_MASK (second) &
638             (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) |
639              IPCOP_MASK (IPC_RMID))) {
640                 if (second == (IPC_INFO|IPC_64))
641                         second = IPC_INFO; /* So that we don't have to translate it */
642                 err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
643         } else if ((second & IPC_64) && second != (SHM_INFO|IPC_64)) {
644                 struct shmid64_ds s;
645                 struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr;
646                 mm_segment_t old_fs;
647
648                 if (second == (IPC_SET|IPC_64)) {
649                         err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
650                         err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
651                         err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
652                         if (err)
653                                 goto out;
654                 }
655                 old_fs = get_fs ();
656                 set_fs (KERNEL_DS);
657                 err = sys_shmctl (first, second, (struct shmid_ds *)&s);
658                 set_fs (old_fs);
659                 if (err < 0)
660                         goto out;
661
662                 /* Mask it even in this case so it becomes a CSE. */
663                 if (IPCOP_MASK (second) &
664                     (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
665                         int err2 = copy_to_user (&up->shm_perm, &s.shm_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
666                         err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
667                         err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
668                         err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
669                         err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
670                         if (err2)
671                                 err = -EFAULT;
672                 }
673         } else {
674                 struct shmid_ds s;
675                 struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
676                 mm_segment_t old_fs;
677
678                 second &= ~IPC_64;
679                 if (second == IPC_SET) {
680                         err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
681                         err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
682                         err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
683                         if (err)
684                                 goto out;
685                 }
686                 old_fs = get_fs ();
687                 set_fs (KERNEL_DS);
688                 err = sys_shmctl (first, second, &s);
689                 set_fs (old_fs);
690                 if (err < 0)
691                         goto out;
692
693                 /* Mask it even in this case so it becomes a CSE. */
694                 if (second == SHM_INFO) {
695                         struct shm_info32 {
696                                 int used_ids;
697                                 u32 shm_tot, shm_rss, shm_swp;
698                                 u32 swap_attempts, swap_successes;
699                         } *uip = (struct shm_info32 *)uptr;
700                         struct shm_info *kp = (struct shm_info *)&s;
701                         int err2 = put_user (kp->used_ids, &uip->used_ids);
702                         err2 |= __put_user (kp->shm_tot, &uip->shm_tot);
703                         err2 |= __put_user (kp->shm_rss, &uip->shm_rss);
704                         err2 |= __put_user (kp->shm_swp, &uip->shm_swp);
705                         err2 |= __put_user (kp->swap_attempts, &uip->swap_attempts);
706                         err2 |= __put_user (kp->swap_successes, &uip->swap_successes);
707                         if (err2)
708                                 err = -EFAULT;
709                 } else if (IPCOP_MASK (second) &
710                            (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
711                         int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
712                         err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
713                         err2 |= __put_user (high2lowuid(s.shm_perm.gid), &up->shm_perm.gid);
714                         err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
715                         err2 |= __put_user (high2lowuid(s.shm_perm.cgid), &up->shm_perm.cgid);
716                         err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
717                         err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
718                         err2 |= __put_user (s.shm_atime, &up->shm_atime);
719                         err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
720                         err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
721                         err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
722                         err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
723                         err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
724                         err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
725                         if (err2)
726                                 err = -EFAULT;
727                 }
728         }
729 out:
730         return err;
731 }
732
733 static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems,
734                             const struct compat_timespec *timeout32)
735 {
736         struct compat_timespec t32;
737         struct timespec *t64 = compat_alloc_user_space(sizeof(*t64));
738
739         if (copy_from_user(&t32, timeout32, sizeof(t32)))
740                 return -EFAULT;
741
742         if (put_user(t32.tv_sec, &t64->tv_sec) ||
743             put_user(t32.tv_nsec, &t64->tv_nsec))
744                 return -EFAULT;
745
746         return sys_semtimedop(semid, tsems, nsems, t64);
747 }
748
749 asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
750 {
751         int version, err;
752
753         version = call >> 16; /* hack for backward compatibility */
754         call &= 0xffff;
755
756         if (call <= SEMCTL)
757                 switch (call) {
758                 case SEMOP:
759                         /* struct sembuf is the same on 32 and 64bit :)) */
760                         err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second, NULL);
761                         goto out;
762                 case SEMTIMEDOP:
763                         err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second, (const struct compat_timespec *) AA(fifth));
764                 case SEMGET:
765                         err = sys_semget (first, second, third);
766                         goto out;
767                 case SEMCTL:
768                         err = do_sys32_semctl (first, second, third, (void *)AA(ptr));
769                         goto out;
770                 default:
771                         err = -ENOSYS;
772                         goto out;
773                 };
774         if (call <= MSGCTL) 
775                 switch (call) {
776                 case MSGSND:
777                         err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr));
778                         goto out;
779                 case MSGRCV:
780                         err = do_sys32_msgrcv (first, second, fifth, third,
781                                                version, (void *)AA(ptr));
782                         goto out;
783                 case MSGGET:
784                         err = sys_msgget ((key_t) first, second);
785                         goto out;
786                 case MSGCTL:
787                         err = do_sys32_msgctl (first, second, (void *)AA(ptr));
788                         goto out;
789                 default:
790                         err = -ENOSYS;
791                         goto out;
792                 }
793         if (call <= SHMCTL) 
794                 switch (call) {
795                 case SHMAT:
796                         err = do_sys32_shmat (first, second, third,
797                                               version, (void *)AA(ptr));
798                         goto out;
799                 case SHMDT: 
800                         err = sys_shmdt ((char *)AA(ptr));
801                         goto out;
802                 case SHMGET:
803                         err = sys_shmget (first, second, third);
804                         goto out;
805                 case SHMCTL:
806                         err = do_sys32_shmctl (first, second, (void *)AA(ptr));
807                         goto out;
808                 default:
809                         err = -ENOSYS;
810                         goto out;
811                 }
812
813         err = -ENOSYS;
814
815 out:
816         return err;
817 }
818
819 asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low)
820 {
821         if ((int)high < 0)
822                 return -EINVAL;
823         else
824                 return sys_truncate(path, (high << 32) | low);
825 }
826
827 asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
828 {
829         if ((int)high < 0)
830                 return -EINVAL;
831         else
832                 return sys_ftruncate(fd, (high << 32) | low);
833 }
834
835 typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
836 typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
837
838 static long do_readv_writev32(int type, struct file *file,
839                               const struct compat_iovec *vector, u32 count)
840 {
841         compat_ssize_t tot_len;
842         struct iovec iovstack[UIO_FASTIOV];
843         struct iovec *iov=iovstack, *ivp;
844         struct inode *inode;
845         long retval, i;
846         io_fn_t fn;
847         iov_fn_t fnv;
848
849         /*
850          * SuS says "The readv() function *may* fail if the iovcnt argument
851          * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
852          * traditionally returned zero for zero segments, so...
853          */
854         retval = 0;
855         if (count == 0)
856                 goto out;
857
858         /* First get the "struct iovec" from user memory and
859          * verify all the pointers
860          */
861         retval = -EINVAL;
862         if (count > UIO_MAXIOV)
863                 goto out;
864         if (!file->f_op)
865                 goto out;
866         if (count > UIO_FASTIOV) {
867                 retval = -ENOMEM;
868                 iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
869                 if (!iov)
870                         goto out;
871         }
872         retval = -EFAULT;
873         if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
874                 goto out;
875
876         /*
877          * Single unix specification:
878          * We should -EINVAL if an element length is not >= 0 and fitting an
879          * ssize_t.  The total length is fitting an ssize_t
880          *
881          * Be careful here because iov_len is a size_t not an ssize_t
882          */
883         tot_len = 0;
884         i = count;
885         ivp = iov;
886         retval = -EINVAL;
887         while(i > 0) {
888                 compat_ssize_t tmp = tot_len;
889                 compat_ssize_t len;
890                 u32 buf;
891
892                 if (__get_user(len, &vector->iov_len) ||
893                     __get_user(buf, &vector->iov_base)) {
894                         retval = -EFAULT;
895                         goto out;
896                 }
897                 if (len < 0)    /* size_t not fitting an ssize_t32 .. */
898                         goto out;
899                 tot_len += len;
900                 if (tot_len < tmp) /* maths overflow on the compat_ssize_t */
901                         goto out;
902                 ivp->iov_base = (void *)A(buf);
903                 ivp->iov_len = (__kernel_size_t) len;
904                 vector++;
905                 ivp++;
906                 i--;
907         }
908         if (tot_len == 0) {
909                 retval = 0;
910                 goto out;
911         }
912
913         inode = file->f_dentry->d_inode;
914         /* VERIFY_WRITE actually means a read, as we write to user space */
915         retval = locks_verify_area((type == READ
916                                     ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
917                                    inode, file, file->f_pos, tot_len);
918         if (retval)
919                 goto out;
920
921         if (type == READ) {
922                 fn = file->f_op->read;
923                 fnv = file->f_op->readv;
924         } else {
925                 fn = (io_fn_t)file->f_op->write;
926                 fnv = file->f_op->writev;
927         }
928         if (fnv) {
929                 retval = fnv(file, iov, count, &file->f_pos);
930                 goto out;
931         }
932
933         /* Do it by hand, with file-ops */
934         ivp = iov;
935         while (count > 0) {
936                 void * base;
937                 int len, nr;
938
939                 base = ivp->iov_base;
940                 len = ivp->iov_len;
941                 ivp++;
942                 count--;
943
944                 nr = fn(file, base, len, &file->f_pos);
945
946                 if (nr < 0) {
947                         if (!retval)
948                                 retval = nr;
949                         break;
950                 }
951                 retval += nr;
952                 if (nr != len)
953                         break;
954         }
955 out:
956         if (iov != iovstack)
957                 kfree(iov);
958         if ((retval + (type == READ)) > 0)
959                 dnotify_parent(file->f_dentry,
960                         (type == READ) ? DN_ACCESS : DN_MODIFY);
961
962         return retval;
963 }
964
965 asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count)
966 {
967         struct file *file;
968         int ret;
969
970         file = fget(fd);
971         if(!file)
972                 return -EBADF;
973
974         ret = -EBADF;
975         if (!(file->f_mode & FMODE_READ))
976                 goto out;
977         ret = -EINVAL;
978         if (!file->f_op || (!file->f_op->readv && !file->f_op->read))
979                 goto out;
980
981         ret = do_readv_writev32(READ, file, vector, count);
982
983 out:
984         fput(file);
985         return ret;
986 }
987
988 asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count)
989 {
990         struct file *file;
991         int ret;
992
993         file = fget(fd);
994         if(!file)
995                 return -EBADF;
996
997         ret = -EBADF;
998         if (!(file->f_mode & FMODE_WRITE))
999                 goto out;
1000         ret = -EINVAL;
1001         if (!file->f_op || (!file->f_op->writev && !file->f_op->write))
1002                 goto out;
1003
1004         ret = do_readv_writev32(WRITE, file, vector, count);
1005
1006 out:
1007         fput(file);
1008         return ret;
1009 }
1010
1011 /* readdir & getdents */
1012
1013 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
1014 #define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
1015
1016 struct old_linux_dirent32 {
1017         u32             d_ino;
1018         u32             d_offset;
1019         unsigned short  d_namlen;
1020         char            d_name[1];
1021 };
1022
1023 struct readdir_callback32 {
1024         struct old_linux_dirent32 * dirent;
1025         int count;
1026 };
1027
1028 static int fillonedir(void * __buf, const char * name, int namlen,
1029                       loff_t offset, ino_t ino, unsigned int d_type)
1030 {
1031         struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
1032         struct old_linux_dirent32 * dirent;
1033
1034         if (buf->count)
1035                 return -EINVAL;
1036         buf->count++;
1037         dirent = buf->dirent;
1038         put_user(ino, &dirent->d_ino);
1039         put_user(offset, &dirent->d_offset);
1040         put_user(namlen, &dirent->d_namlen);
1041         copy_to_user(dirent->d_name, name, namlen);
1042         put_user(0, dirent->d_name + namlen);
1043         return 0;
1044 }
1045
1046 asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count)
1047 {
1048         int error = -EBADF;
1049         struct file * file;
1050         struct readdir_callback32 buf;
1051
1052         file = fget(fd);
1053         if (!file)
1054                 goto out;
1055
1056         buf.count = 0;
1057         buf.dirent = dirent;
1058
1059         error = vfs_readdir(file, fillonedir, &buf);
1060         if (error < 0)
1061                 goto out_putf;
1062         error = buf.count;
1063
1064 out_putf:
1065         fput(file);
1066 out:
1067         return error;
1068 }
1069
1070 struct linux_dirent32 {
1071         u32             d_ino;
1072         u32             d_off;
1073         unsigned short  d_reclen;
1074         char            d_name[1];
1075 };
1076
1077 struct getdents_callback32 {
1078         struct linux_dirent32 * current_dir;
1079         struct linux_dirent32 * previous;
1080         int count;
1081         int error;
1082 };
1083
1084 static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
1085                    unsigned int d_type)
1086 {
1087         struct linux_dirent32 * dirent;
1088         struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
1089         int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
1090
1091         buf->error = -EINVAL;   /* only used if we fail.. */
1092         if (reclen > buf->count)
1093                 return -EINVAL;
1094         dirent = buf->previous;
1095         if (dirent)
1096                 put_user(offset, &dirent->d_off);
1097         dirent = buf->current_dir;
1098         buf->previous = dirent;
1099         put_user(ino, &dirent->d_ino);
1100         put_user(reclen, &dirent->d_reclen);
1101         copy_to_user(dirent->d_name, name, namlen);
1102         put_user(0, dirent->d_name + namlen);
1103         put_user(d_type, (char *) dirent + reclen - 1);
1104         dirent = (void *) dirent + reclen;
1105         buf->current_dir = dirent;
1106         buf->count -= reclen;
1107         return 0;
1108 }
1109
1110 asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count)
1111 {
1112         struct file * file;
1113         struct linux_dirent32 * lastdirent;
1114         struct getdents_callback32 buf;
1115         int error = -EBADF;
1116
1117         file = fget(fd);
1118         if (!file)
1119                 goto out;
1120
1121         buf.current_dir = dirent;
1122         buf.previous = NULL;
1123         buf.count = count;
1124         buf.error = 0;
1125
1126         error = vfs_readdir(file, filldir, &buf);
1127         if (error < 0)
1128                 goto out_putf;
1129         lastdirent = buf.previous;
1130         error = buf.error;
1131         if(lastdirent) {
1132                 put_user(file->f_pos, &lastdirent->d_off);
1133                 error = count - buf.count;
1134         }
1135 out_putf:
1136         fput(file);
1137 out:
1138         return error;
1139 }
1140
1141 /* end of readdir & getdents */
1142
1143 /*
1144  * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
1145  * 64-bit unsigned longs.
1146  */
1147
1148 static int get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
1149 {
1150         if (ufdset) {
1151                 unsigned long odd;
1152
1153                 if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
1154                         return -EFAULT;
1155
1156                 odd = n & 1UL;
1157                 n &= ~1UL;
1158                 while (n) {
1159                         unsigned long h, l;
1160                         __get_user(l, ufdset);
1161                         __get_user(h, ufdset+1);
1162                         ufdset += 2;
1163                         *fdset++ = h << 32 | l;
1164                         n -= 2;
1165                 }
1166                 if (odd)
1167                         __get_user(*fdset, ufdset);
1168         } else {
1169                 /* Tricky, must clear full unsigned long in the
1170                  * kernel fdset at the end, this makes sure that
1171                  * actually happens.
1172                  */
1173                 memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
1174         }
1175         return 0;
1176 }
1177
1178 static void set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
1179 {
1180         unsigned long odd;
1181
1182         if (!ufdset)
1183                 return;
1184
1185         odd = n & 1UL;
1186         n &= ~1UL;
1187         while (n) {
1188                 unsigned long h, l;
1189                 l = *fdset++;
1190                 h = l >> 32;
1191                 __put_user(l, ufdset);
1192                 __put_user(h, ufdset+1);
1193                 ufdset += 2;
1194                 n -= 2;
1195         }
1196         if (odd)
1197                 __put_user(*fdset, ufdset);
1198 }
1199
1200 #define MAX_SELECT_SECONDS \
1201         ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1202
1203 asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x)
1204 {
1205         fd_set_bits fds;
1206         struct compat_timeval *tvp = (struct compat_timeval *)AA(tvp_x);
1207         char *bits;
1208         unsigned long nn;
1209         long timeout;
1210         int ret, size;
1211
1212         timeout = MAX_SCHEDULE_TIMEOUT;
1213         if (tvp) {
1214                 time_t sec, usec;
1215
1216                 if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
1217                     || (ret = __get_user(sec, &tvp->tv_sec))
1218                     || (ret = __get_user(usec, &tvp->tv_usec)))
1219                         goto out_nofds;
1220
1221                 ret = -EINVAL;
1222                 if(sec < 0 || usec < 0)
1223                         goto out_nofds;
1224
1225                 if ((unsigned long) sec < MAX_SELECT_SECONDS) {
1226                         timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
1227                         timeout += sec * (unsigned long) HZ;
1228                 }
1229         }
1230
1231         ret = -EINVAL;
1232         if (n < 0)
1233                 goto out_nofds;
1234         if (n > current->files->max_fdset)
1235                 n = current->files->max_fdset;
1236
1237         /*
1238          * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1239          * since we used fdset we need to allocate memory in units of
1240          * long-words. 
1241          */
1242         ret = -ENOMEM;
1243         size = FDS_BYTES(n);
1244         bits = kmalloc(6 * size, GFP_KERNEL);
1245         if (!bits)
1246                 goto out_nofds;
1247         fds.in      = (unsigned long *)  bits;
1248         fds.out     = (unsigned long *) (bits +   size);
1249         fds.ex      = (unsigned long *) (bits + 2*size);
1250         fds.res_in  = (unsigned long *) (bits + 3*size);
1251         fds.res_out = (unsigned long *) (bits + 4*size);
1252         fds.res_ex  = (unsigned long *) (bits + 5*size);
1253
1254         nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
1255         if ((ret = get_fd_set32(nn, fds.in, inp)) ||
1256             (ret = get_fd_set32(nn, fds.out, outp)) ||
1257             (ret = get_fd_set32(nn, fds.ex, exp)))
1258                 goto out;
1259         zero_fd_set(n, fds.res_in);
1260         zero_fd_set(n, fds.res_out);
1261         zero_fd_set(n, fds.res_ex);
1262
1263         ret = do_select(n, &fds, &timeout);
1264
1265         if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
1266                 time_t sec = 0, usec = 0;
1267                 if (timeout) {
1268                         sec = timeout / HZ;
1269                         usec = timeout % HZ;
1270                         usec *= (1000000/HZ);
1271                 }
1272                 put_user(sec, &tvp->tv_sec);
1273                 put_user(usec, &tvp->tv_usec);
1274         }
1275
1276         if (ret < 0)
1277                 goto out;
1278         if (!ret) {
1279                 ret = -ERESTARTNOHAND;
1280                 if (signal_pending(current))
1281                         goto out;
1282                 ret = 0;
1283         }
1284
1285         set_fd_set32(nn, inp, fds.res_in);
1286         set_fd_set32(nn, outp, fds.res_out);
1287         set_fd_set32(nn, exp, fds.res_ex);
1288
1289 out:
1290         kfree(bits);
1291 out_nofds:
1292         return ret;
1293 }
1294
1295 int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf)
1296 {
1297         int err;
1298
1299         if (stat->size > MAX_NON_LFS || !old_valid_dev(stat->dev) ||
1300             !old_valid_dev(stat->rdev))
1301                 return -EOVERFLOW;
1302
1303         err  = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
1304         err |= put_user(stat->ino, &statbuf->st_ino);
1305         err |= put_user(stat->mode, &statbuf->st_mode);
1306         err |= put_user(stat->nlink, &statbuf->st_nlink);
1307         err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
1308         err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
1309         err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
1310         err |= put_user(stat->size, &statbuf->st_size);
1311         err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
1312         err |= put_user(0, &statbuf->__unused1);
1313         err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
1314         err |= put_user(0, &statbuf->__unused2);
1315         err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
1316         err |= put_user(0, &statbuf->__unused3);
1317         err |= put_user(stat->blksize, &statbuf->st_blksize);
1318         err |= put_user(stat->blocks, &statbuf->st_blocks);
1319         err |= put_user(0, &statbuf->__unused4[0]);
1320         err |= put_user(0, &statbuf->__unused4[1]);
1321
1322         return err;
1323 }
1324
1325 asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
1326 {
1327         return sys_sysfs(option, arg1, arg2);
1328 }
1329
1330 struct sysinfo32 {
1331         s32 uptime;
1332         u32 loads[3];
1333         u32 totalram;
1334         u32 freeram;
1335         u32 sharedram;
1336         u32 bufferram;
1337         u32 totalswap;
1338         u32 freeswap;
1339         unsigned short procs;
1340         unsigned short pad;
1341         u32 totalhigh;
1342         u32 freehigh;
1343         u32 mem_unit;
1344         char _f[20-2*sizeof(int)-sizeof(int)];
1345 };
1346
1347 asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
1348 {
1349         struct sysinfo s;
1350         int ret, err;
1351         int bitcount = 0;
1352         mm_segment_t old_fs = get_fs ();
1353         
1354         set_fs(KERNEL_DS);
1355         ret = sys_sysinfo(&s);
1356         set_fs(old_fs);
1357         /* Check to see if any memory value is too large for 32-bit and
1358          * scale down if needed.
1359          */
1360         if ((s.totalram >> 32) || (s.totalswap >> 32)) {
1361                 while (s.mem_unit < PAGE_SIZE) {
1362                         s.mem_unit <<= 1;
1363                         bitcount++;
1364                 }
1365                 s.totalram >>= bitcount;
1366                 s.freeram >>= bitcount;
1367                 s.sharedram >>= bitcount;
1368                 s.bufferram >>= bitcount;
1369                 s.totalswap >>= bitcount;
1370                 s.freeswap >>= bitcount;
1371                 s.totalhigh >>= bitcount;
1372                 s.freehigh >>= bitcount;
1373         }
1374
1375         err = put_user (s.uptime, &info->uptime);
1376         err |= __put_user (s.loads[0], &info->loads[0]);
1377         err |= __put_user (s.loads[1], &info->loads[1]);
1378         err |= __put_user (s.loads[2], &info->loads[2]);
1379         err |= __put_user (s.totalram, &info->totalram);
1380         err |= __put_user (s.freeram, &info->freeram);
1381         err |= __put_user (s.sharedram, &info->sharedram);
1382         err |= __put_user (s.bufferram, &info->bufferram);
1383         err |= __put_user (s.totalswap, &info->totalswap);
1384         err |= __put_user (s.freeswap, &info->freeswap);
1385         err |= __put_user (s.procs, &info->procs);
1386         err |= __put_user (s.totalhigh, &info->totalhigh);
1387         err |= __put_user (s.freehigh, &info->freehigh);
1388         err |= __put_user (s.mem_unit, &info->mem_unit);
1389         if (err)
1390                 return -EFAULT;
1391         return ret;
1392 }
1393
1394 asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec *interval)
1395 {
1396         struct timespec t;
1397         int ret;
1398         mm_segment_t old_fs = get_fs ();
1399         
1400         set_fs (KERNEL_DS);
1401         ret = sys_sched_rr_get_interval(pid, &t);
1402         set_fs (old_fs);
1403         if (put_compat_timespec(&t, interval))
1404                 return -EFAULT;
1405         return ret;
1406 }
1407
1408 asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset, compat_size_t sigsetsize)
1409 {
1410         sigset_t s;
1411         compat_sigset_t s32;
1412         int ret;
1413         mm_segment_t old_fs = get_fs();
1414         
1415         if (set) {
1416                 if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))
1417                         return -EFAULT;
1418                 switch (_NSIG_WORDS) {
1419                 case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
1420                 case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
1421                 case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
1422                 case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
1423                 }
1424         }
1425         set_fs (KERNEL_DS);
1426         ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sigsetsize);
1427         set_fs (old_fs);
1428         if (ret) return ret;
1429         if (oset) {
1430                 switch (_NSIG_WORDS) {
1431                 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
1432                 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
1433                 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
1434                 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
1435                 }
1436                 if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))
1437                         return -EFAULT;
1438         }
1439         return 0;
1440 }
1441
1442 asmlinkage int sys32_rt_sigpending(compat_sigset_t *set, compat_size_t sigsetsize)
1443 {
1444         sigset_t s;
1445         compat_sigset_t s32;
1446         int ret;
1447         mm_segment_t old_fs = get_fs();
1448                 
1449         set_fs (KERNEL_DS);
1450         ret = sys_rt_sigpending(&s, sigsetsize);
1451         set_fs (old_fs);
1452         if (!ret) {
1453                 switch (_NSIG_WORDS) {
1454                 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
1455                 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
1456                 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
1457                 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
1458                 }
1459                 if (copy_to_user (set, &s32, sizeof(compat_sigset_t)))
1460                         return -EFAULT;
1461         }
1462         return ret;
1463 }
1464
1465 asmlinkage int
1466 sys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo,
1467                       struct compat_timespec *uts, compat_size_t sigsetsize)
1468 {
1469         int ret, sig;
1470         sigset_t these;
1471         compat_sigset_t these32;
1472         struct timespec ts;
1473         siginfo_t info;
1474         long timeout = 0;
1475
1476         /* XXX: Don't preclude handling different sized sigset_t's.  */
1477         if (sigsetsize != sizeof(sigset_t))
1478                 return -EINVAL;
1479
1480         if (copy_from_user (&these32, uthese, sizeof(compat_sigset_t)))
1481                 return -EFAULT;
1482
1483         switch (_NSIG_WORDS) {
1484         case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
1485         case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
1486         case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
1487         case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
1488         }
1489                 
1490         /*
1491          * Invert the set of allowed signals to get those we
1492          * want to block.
1493          */
1494         sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
1495         signotset(&these);
1496
1497         if (uts) {
1498                 if (get_compat_timespec(&ts, uts))
1499                         return -EINVAL;
1500                 if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
1501                     || ts.tv_sec < 0)
1502                         return -EINVAL;
1503         }
1504
1505         spin_lock_irq(&current->sighand->siglock);
1506         sig = dequeue_signal(current, &these, &info);
1507         if (!sig) {
1508                 timeout = MAX_SCHEDULE_TIMEOUT;
1509                 if (uts)
1510                         timeout = (timespec_to_jiffies(&ts)
1511                                    + (ts.tv_sec || ts.tv_nsec));
1512
1513                 if (timeout) {
1514                         /* None ready -- temporarily unblock those we're
1515                          * interested while we are sleeping in so that we'll
1516                          * be awakened when they arrive.  */
1517                         current->real_blocked = current->blocked;
1518                         sigandsets(&current->blocked, &current->blocked, &these);
1519                         recalc_sigpending();
1520                         spin_unlock_irq(&current->sighand->siglock);
1521
1522                         current->state = TASK_INTERRUPTIBLE;
1523                         timeout = schedule_timeout(timeout);
1524
1525                         spin_lock_irq(&current->sighand->siglock);
1526                         sig = dequeue_signal(current, &these, &info);
1527                         current->blocked = current->real_blocked;
1528                         siginitset(&current->real_blocked, 0);
1529                         recalc_sigpending();
1530                 }
1531         }
1532         spin_unlock_irq(&current->sighand->siglock);
1533
1534         if (sig) {
1535                 ret = sig;
1536                 if (uinfo) {
1537                         if (copy_siginfo_to_user32(uinfo, &info))
1538                                 ret = -EFAULT;
1539                 }
1540         } else {
1541                 ret = -EAGAIN;
1542                 if (timeout)
1543                         ret = -EINTR;
1544         }
1545
1546         return ret;
1547 }
1548
1549 asmlinkage int
1550 sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
1551 {
1552         siginfo_t info;
1553         int ret;
1554         mm_segment_t old_fs = get_fs();
1555         
1556         if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
1557             copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
1558                 return -EFAULT;
1559         set_fs (KERNEL_DS);
1560         ret = sys_rt_sigqueueinfo(pid, sig, &info);
1561         set_fs (old_fs);
1562         return ret;
1563 }
1564
1565 extern void check_pending(int signum);
1566
1567 asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
1568 {
1569         struct k_sigaction new_ka, old_ka;
1570         int ret;
1571
1572         if (sig < 0) {
1573                 set_thread_flag(TIF_NEWSIGNALS);
1574                 sig = -sig;
1575         }
1576
1577         if (act) {
1578                 compat_old_sigset_t mask;
1579                 u32 u_handler, u_restorer;
1580                 
1581                 ret = get_user(u_handler, &act->sa_handler);
1582                 new_ka.sa.sa_handler = (void *) (long) u_handler;
1583                 ret |= __get_user(u_restorer, &act->sa_restorer);
1584                 new_ka.sa.sa_restorer = (void *) (long) u_restorer;
1585                 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
1586                 ret |= __get_user(mask, &act->sa_mask);
1587                 if (ret)
1588                         return ret;
1589                 new_ka.ka_restorer = NULL;
1590                 siginitset(&new_ka.sa.sa_mask, mask);
1591         }
1592
1593         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
1594
1595         if (!ret && oact) {
1596                 ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
1597                 ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
1598                 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
1599                 ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
1600         }
1601
1602         return ret;
1603 }
1604
1605 asmlinkage int
1606 sys32_rt_sigaction(int sig, struct sigaction32 *act, struct sigaction32 *oact,
1607                    void *restorer, compat_size_t sigsetsize)
1608 {
1609         struct k_sigaction new_ka, old_ka;
1610         int ret;
1611         compat_sigset_t set32;
1612
1613         /* XXX: Don't preclude handling different sized sigset_t's.  */
1614         if (sigsetsize != sizeof(compat_sigset_t))
1615                 return -EINVAL;
1616
1617         /* All tasks which use RT signals (effectively) use
1618          * new style signals.
1619          */
1620         set_thread_flag(TIF_NEWSIGNALS);
1621
1622         if (act) {
1623                 u32 u_handler, u_restorer;
1624
1625                 new_ka.ka_restorer = restorer;
1626                 ret = get_user(u_handler, &act->sa_handler);
1627                 new_ka.sa.sa_handler = (void *) (long) u_handler;
1628                 ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));
1629                 switch (_NSIG_WORDS) {
1630                 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
1631                 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
1632                 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
1633                 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
1634                 }
1635                 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
1636                 ret |= __get_user(u_restorer, &act->sa_restorer);
1637                 new_ka.sa.sa_restorer = (void *) (long) u_restorer;
1638                 if (ret)
1639                         return -EFAULT;
1640         }
1641
1642         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
1643
1644         if (!ret && oact) {
1645                 switch (_NSIG_WORDS) {
1646                 case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
1647                 case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
1648                 case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
1649                 case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
1650                 }
1651                 ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
1652                 ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));
1653                 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
1654                 ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
1655                 if (ret)
1656                         ret = -EFAULT;
1657         }
1658
1659         return ret;
1660 }
1661
1662
1663 /*
1664  * count32() counts the number of arguments/envelopes
1665  */
1666 static int count32(u32 * argv, int max)
1667 {
1668         int i = 0;
1669
1670         if (argv != NULL) {
1671                 for (;;) {
1672                         u32 p; int error;
1673
1674                         error = get_user(p,argv);
1675                         if (error)
1676                                 return error;
1677                         if (!p)
1678                                 break;
1679                         argv++;
1680                         if (++i > max)
1681                                 return -E2BIG;
1682                 }
1683         }
1684         return i;
1685 }
1686
1687 /*
1688  * 'copy_string32()' copies argument/envelope strings from user
1689  * memory to free pages in kernel mem. These are in a format ready
1690  * to be put directly into the top of new user memory.
1691  */
1692 static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
1693 {
1694         while (argc-- > 0) {
1695                 u32 str;
1696                 int len;
1697                 unsigned long pos;
1698
1699                 if (get_user(str, argv + argc) ||
1700                     !str ||
1701                     !(len = strnlen_user((char *)A(str), bprm->p)))
1702                         return -EFAULT;
1703
1704                 if (bprm->p < len)
1705                         return -E2BIG;
1706
1707                 bprm->p -= len;
1708
1709                 pos = bprm->p;
1710                 while (len) {
1711                         char *kaddr;
1712                         struct page *page;
1713                         int offset, bytes_to_copy, new, err;
1714
1715                         offset = pos % PAGE_SIZE;
1716                         page = bprm->page[pos / PAGE_SIZE];
1717                         new = 0;
1718                         if (!page) {
1719                                 page = alloc_page(GFP_USER);
1720                                 bprm->page[pos / PAGE_SIZE] = page;
1721                                 if (!page)
1722                                         return -ENOMEM;
1723                                 new = 1;
1724                         }
1725                         kaddr = kmap(page);
1726
1727                         if (new && offset)
1728                                 memset(kaddr, 0, offset);
1729                         bytes_to_copy = PAGE_SIZE - offset;
1730                         if (bytes_to_copy > len) {
1731                                 bytes_to_copy = len;
1732                                 if (new)
1733                                         memset(kaddr+offset+len, 0,
1734                                                PAGE_SIZE-offset-len);
1735                         }
1736
1737                         err = copy_from_user(kaddr + offset, (char *)A(str),
1738                                              bytes_to_copy);
1739                         kunmap(page);
1740
1741                         if (err)
1742                                 return -EFAULT;
1743
1744                         pos += bytes_to_copy;
1745                         str += bytes_to_copy;
1746                         len -= bytes_to_copy;
1747                 }
1748         }
1749         return 0;
1750 }
1751
1752 /*
1753  * sys32_execve() executes a new program.
1754  */
1755 static inline int 
1756 do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
1757 {
1758         struct linux_binprm bprm;
1759         struct file * file;
1760         int retval;
1761         int i;
1762
1763         sched_balance_exec();
1764
1765         file = open_exec(filename);
1766
1767         retval = PTR_ERR(file);
1768         if (IS_ERR(file))
1769                 return retval;
1770
1771         bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
1772         memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
1773
1774         bprm.file = file;
1775         bprm.filename = filename;
1776         bprm.interp = filename;
1777         bprm.sh_bang = 0;
1778         bprm.loader = 0;
1779         bprm.exec = 0;
1780         bprm.security = NULL;
1781         bprm.mm = mm_alloc();
1782         retval = -ENOMEM;
1783         if (!bprm.mm) 
1784                 goto out_file;
1785
1786         retval = init_new_context(current, bprm.mm);
1787         if (retval < 0)
1788                 goto out_mm;
1789
1790         bprm.argc = count32(argv, bprm.p / sizeof(u32));
1791         if ((retval = bprm.argc) < 0)
1792                 goto out_mm;
1793
1794         bprm.envc = count32(envp, bprm.p / sizeof(u32));
1795         if ((retval = bprm.envc) < 0)
1796                 goto out_mm;
1797
1798         retval = security_bprm_alloc(&bprm);
1799         if (retval)
1800                 goto out;
1801
1802         retval = prepare_binprm(&bprm);
1803         if (retval < 0)
1804                 goto out;
1805         
1806         retval = copy_strings_kernel(1, &bprm.filename, &bprm);
1807         if (retval < 0)
1808                 goto out;
1809
1810         bprm.exec = bprm.p;
1811         retval = copy_strings32(bprm.envc, envp, &bprm);
1812         if (retval < 0)
1813                 goto out;
1814
1815         retval = copy_strings32(bprm.argc, argv, &bprm);
1816         if (retval < 0)
1817                 goto out;
1818
1819         retval = search_binary_handler(&bprm, regs);
1820         if (retval >= 0) {
1821                 /* execve success */
1822                 security_bprm_free(&bprm);
1823                 return retval;
1824         }
1825
1826 out:
1827         /* Something went wrong, return the inode and free the argument pages*/
1828         for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
1829                 struct page * page = bprm.page[i];
1830                 if (page)
1831                         __free_page(page);
1832         }
1833
1834         if (bprm.security)
1835                 security_bprm_free(&bprm);
1836
1837 out_mm:
1838         if (bprm.mm)
1839                 mmdrop(bprm.mm);
1840
1841 out_file:
1842         if (bprm.file) {
1843                 allow_write_access(bprm.file);
1844                 fput(bprm.file);
1845         }
1846         return retval;
1847 }
1848
1849 /*
1850  * sparc32_execve() executes a new program after the asm stub has set
1851  * things up for us.  This should basically do what I want it to.
1852  */
1853 asmlinkage int sparc32_execve(struct pt_regs *regs)
1854 {
1855         int error, base = 0;
1856         char *filename;
1857
1858         /* User register window flush is done by entry.S */
1859
1860         /* Check for indirect call. */
1861         if((u32)regs->u_regs[UREG_G1] == 0)
1862                 base = 1;
1863
1864         filename = getname((char *)AA(regs->u_regs[base + UREG_I0]));
1865         error = PTR_ERR(filename);
1866         if(IS_ERR(filename))
1867                 goto out;
1868         error = do_execve32(filename,
1869                 (u32 *)AA((u32)regs->u_regs[base + UREG_I1]),
1870                 (u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs);
1871         putname(filename);
1872
1873         if(!error) {
1874                 fprs_write(0);
1875                 current_thread_info()->xfsr[0] = 0;
1876                 current_thread_info()->fpsaved[0] = 0;
1877                 regs->tstate &= ~TSTATE_PEF;
1878                 current->ptrace &= ~PT_DTRACE;
1879         }
1880 out:
1881         return error;
1882 }
1883
1884 #ifdef CONFIG_MODULES
1885
1886 asmlinkage int sys32_init_module(void *umod, u32 len, const char *uargs)
1887 {
1888         return sys_init_module(umod, len, uargs);
1889 }
1890
1891 asmlinkage int sys32_delete_module(const char *name_user, unsigned int flags)
1892 {
1893         return sys_delete_module(name_user, flags);
1894 }
1895
1896 #else /* CONFIG_MODULES */
1897
1898 asmlinkage int
1899 sys32_init_module(const char *name_user, struct module *mod_user)
1900 {
1901         return -ENOSYS;
1902 }
1903
1904 asmlinkage int
1905 sys32_delete_module(const char *name_user)
1906 {
1907         return -ENOSYS;
1908 }
1909
1910 #endif  /* CONFIG_MODULES */
1911
1912 #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
1913 /* Stuff for NFS server syscalls... */
1914 struct nfsctl_svc32 {
1915         u16                     svc32_port;
1916         s32                     svc32_nthreads;
1917 };
1918
1919 struct nfsctl_client32 {
1920         s8                      cl32_ident[NFSCLNT_IDMAX+1];
1921         s32                     cl32_naddr;
1922         struct in_addr          cl32_addrlist[NFSCLNT_ADDRMAX];
1923         s32                     cl32_fhkeytype;
1924         s32                     cl32_fhkeylen;
1925         u8                      cl32_fhkey[NFSCLNT_KEYMAX];
1926 };
1927
1928 struct nfsctl_export32 {
1929         s8                      ex32_client[NFSCLNT_IDMAX+1];
1930         s8                      ex32_path[NFS_MAXPATHLEN+1];
1931         compat_dev_t    ex32_dev;
1932         compat_ino_t    ex32_ino;
1933         s32                     ex32_flags;
1934         compat_uid_t    ex32_anon_uid;
1935         compat_gid_t    ex32_anon_gid;
1936 };
1937
1938 struct nfsctl_fdparm32 {
1939         struct sockaddr         gd32_addr;
1940         s8                      gd32_path[NFS_MAXPATHLEN+1];
1941         s32                     gd32_version;
1942 };
1943
1944 struct nfsctl_fsparm32 {
1945         struct sockaddr         gd32_addr;
1946         s8                      gd32_path[NFS_MAXPATHLEN+1];
1947         s32                     gd32_maxlen;
1948 };
1949
1950 struct nfsctl_arg32 {
1951         s32                     ca32_version;   /* safeguard */
1952         union {
1953                 struct nfsctl_svc32     u32_svc;
1954                 struct nfsctl_client32  u32_client;
1955                 struct nfsctl_export32  u32_export;
1956                 struct nfsctl_fdparm32  u32_getfd;
1957                 struct nfsctl_fsparm32  u32_getfs;
1958         } u;
1959 #define ca32_svc        u.u32_svc
1960 #define ca32_client     u.u32_client
1961 #define ca32_export     u.u32_export
1962 #define ca32_getfd      u.u32_getfd
1963 #define ca32_getfs      u.u32_getfs
1964 };
1965
1966 union nfsctl_res32 {
1967         __u8                    cr32_getfh[NFS_FHSIZE];
1968         struct knfsd_fh         cr32_getfs;
1969 };
1970
1971 static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
1972 {
1973         int err;
1974         
1975         err = __get_user(karg->ca_version, &arg32->ca32_version);
1976         err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
1977         err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
1978         return err;
1979 }
1980
1981 static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
1982 {
1983         int err;
1984         
1985         err = __get_user(karg->ca_version, &arg32->ca32_version);
1986         err |= copy_from_user(&karg->ca_client.cl_ident[0],
1987                           &arg32->ca32_client.cl32_ident[0],
1988                           NFSCLNT_IDMAX);
1989         err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
1990         err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
1991                           &arg32->ca32_client.cl32_addrlist[0],
1992                           (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
1993         err |= __get_user(karg->ca_client.cl_fhkeytype,
1994                       &arg32->ca32_client.cl32_fhkeytype);
1995         err |= __get_user(karg->ca_client.cl_fhkeylen,
1996                       &arg32->ca32_client.cl32_fhkeylen);
1997         err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
1998                           &arg32->ca32_client.cl32_fhkey[0],
1999                           NFSCLNT_KEYMAX);
2000         return (err ? -EFAULT : 0);
2001 }
2002
2003 static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
2004 {
2005         int err;
2006         
2007         err = __get_user(karg->ca_version, &arg32->ca32_version);
2008         err |= copy_from_user(&karg->ca_export.ex_client[0],
2009                           &arg32->ca32_export.ex32_client[0],
2010                           NFSCLNT_IDMAX);
2011         err |= copy_from_user(&karg->ca_export.ex_path[0],
2012                           &arg32->ca32_export.ex32_path[0],
2013                           NFS_MAXPATHLEN);
2014         err |= __get_user(karg->ca_export.ex_dev,
2015                       &arg32->ca32_export.ex32_dev);
2016         err |= __get_user(karg->ca_export.ex_ino,
2017                       &arg32->ca32_export.ex32_ino);
2018         err |= __get_user(karg->ca_export.ex_flags,
2019                       &arg32->ca32_export.ex32_flags);
2020         err |= __get_user(karg->ca_export.ex_anon_uid,
2021                       &arg32->ca32_export.ex32_anon_uid);
2022         err |= __get_user(karg->ca_export.ex_anon_gid,
2023                       &arg32->ca32_export.ex32_anon_gid);
2024         karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
2025         karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
2026         return (err ? -EFAULT : 0);
2027 }
2028
2029 static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
2030 {
2031         int err;
2032         
2033         err = __get_user(karg->ca_version, &arg32->ca32_version);
2034         err |= copy_from_user(&karg->ca_getfd.gd_addr,
2035                           &arg32->ca32_getfd.gd32_addr,
2036                           (sizeof(struct sockaddr)));
2037         err |= copy_from_user(&karg->ca_getfd.gd_path,
2038                           &arg32->ca32_getfd.gd32_path,
2039                           (NFS_MAXPATHLEN+1));
2040         err |= __get_user(karg->ca_getfd.gd_version,
2041                       &arg32->ca32_getfd.gd32_version);
2042         return (err ? -EFAULT : 0);
2043 }
2044
2045 static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
2046 {
2047         int err;
2048         
2049         err = __get_user(karg->ca_version, &arg32->ca32_version);
2050         err |= copy_from_user(&karg->ca_getfs.gd_addr,
2051                           &arg32->ca32_getfs.gd32_addr,
2052                           (sizeof(struct sockaddr)));
2053         err |= copy_from_user(&karg->ca_getfs.gd_path,
2054                           &arg32->ca32_getfs.gd32_path,
2055                           (NFS_MAXPATHLEN+1));
2056         err |= __get_user(karg->ca_getfs.gd_maxlen,
2057                       &arg32->ca32_getfs.gd32_maxlen);
2058         return (err ? -EFAULT : 0);
2059 }
2060
2061 /* This really doesn't need translations, we are only passing
2062  * back a union which contains opaque nfs file handle data.
2063  */
2064 static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
2065 {
2066         return (copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0);
2067 }
2068
2069 int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
2070 {
2071         struct nfsctl_arg *karg = NULL;
2072         union nfsctl_res *kres = NULL;
2073         mm_segment_t oldfs;
2074         int err;
2075
2076         karg = kmalloc(sizeof(*karg), GFP_USER);
2077         if(!karg)
2078                 return -ENOMEM;
2079         if(res32) {
2080                 kres = kmalloc(sizeof(*kres), GFP_USER);
2081                 if(!kres) {
2082                         kfree(karg);
2083                         return -ENOMEM;
2084                 }
2085         }
2086         switch(cmd) {
2087         case NFSCTL_SVC:
2088                 err = nfs_svc32_trans(karg, arg32);
2089                 break;
2090         case NFSCTL_ADDCLIENT:
2091                 err = nfs_clnt32_trans(karg, arg32);
2092                 break;
2093         case NFSCTL_DELCLIENT:
2094                 err = nfs_clnt32_trans(karg, arg32);
2095                 break;
2096         case NFSCTL_EXPORT:
2097         case NFSCTL_UNEXPORT:
2098                 err = nfs_exp32_trans(karg, arg32);
2099                 break;
2100         case NFSCTL_GETFD:
2101                 err = nfs_getfd32_trans(karg, arg32);
2102                 break;
2103         case NFSCTL_GETFS:
2104                 err = nfs_getfs32_trans(karg, arg32);
2105                 break;
2106         default:
2107                 err = -EINVAL;
2108                 break;
2109         }
2110         if(err)
2111                 goto done;
2112         oldfs = get_fs();
2113         set_fs(KERNEL_DS);
2114         err = sys_nfsservctl(cmd, karg, kres);
2115         set_fs(oldfs);
2116
2117         if (err)
2118                 goto done;
2119
2120         if((cmd == NFSCTL_GETFD) ||
2121            (cmd == NFSCTL_GETFS))
2122                 err = nfs_getfh32_res_trans(kres, res32);
2123
2124 done:
2125         if(karg)
2126                 kfree(karg);
2127         if(kres)
2128                 kfree(kres);
2129         return err;
2130 }
2131 #else /* !NFSD */
2132 int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
2133 {
2134         return sys_ni_syscall();
2135 }
2136 #endif
2137
2138 /* Translations due to time_t size differences.  Which affects all
2139    sorts of things, like timeval and itimerval.  */
2140
2141 extern struct timezone sys_tz;
2142
2143 asmlinkage int sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
2144 {
2145         if (tv) {
2146                 struct timeval ktv;
2147                 do_gettimeofday(&ktv);
2148                 if (put_tv32(tv, &ktv))
2149                         return -EFAULT;
2150         }
2151         if (tz) {
2152                 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
2153                         return -EFAULT;
2154         }
2155         return 0;
2156 }
2157
2158 static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
2159 {
2160         long usec;
2161
2162         if (!access_ok(VERIFY_READ, i, sizeof(*i)))
2163                 return -EFAULT;
2164         if (__get_user(o->tv_sec, &i->tv_sec))
2165                 return -EFAULT;
2166         if (__get_user(usec, &i->tv_usec))
2167                 return -EFAULT;
2168         o->tv_nsec = usec * 1000;
2169         return 0;
2170 }
2171
2172 asmlinkage int sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
2173 {
2174         struct timespec kts;
2175         struct timezone ktz;
2176
2177         if (tv) {
2178                 if (get_ts32(&kts, tv))
2179                         return -EFAULT;
2180         }
2181         if (tz) {
2182                 if (copy_from_user(&ktz, tz, sizeof(ktz)))
2183                         return -EFAULT;
2184         }
2185
2186         return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
2187 }
2188
2189 asmlinkage int sys32_utimes(char *filename, struct compat_timeval *tvs)
2190 {
2191         char *kfilename;
2192         struct timeval ktvs[2];
2193         mm_segment_t old_fs;
2194         int ret;
2195
2196         kfilename = getname(filename);
2197         ret = PTR_ERR(kfilename);
2198         if (!IS_ERR(kfilename)) {
2199                 if (tvs) {
2200                         if (get_tv32(&ktvs[0], tvs) ||
2201                             get_tv32(&ktvs[1], 1+tvs))
2202                                 return -EFAULT;
2203                 }
2204
2205                 old_fs = get_fs();
2206                 set_fs(KERNEL_DS);
2207                 ret = do_utimes(kfilename, (tvs ? &ktvs[0] : NULL));
2208                 set_fs(old_fs);
2209
2210                 putname(kfilename);
2211         }
2212         return ret;
2213 }
2214
2215 /* These are here just in case some old sparc32 binary calls it. */
2216 asmlinkage int sys32_pause(void)
2217 {
2218         current->state = TASK_INTERRUPTIBLE;
2219         schedule();
2220         return -ERESTARTNOHAND;
2221 }
2222
2223 /* PCI config space poking. */
2224
2225 asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
2226 {
2227         return sys_pciconfig_read((unsigned long) bus,
2228                                   (unsigned long) dfn,
2229                                   (unsigned long) off,
2230                                   (unsigned long) len,
2231                                   (unsigned char *)AA(ubuf));
2232 }
2233
2234 asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
2235 {
2236         return sys_pciconfig_write((unsigned long) bus,
2237                                    (unsigned long) dfn,
2238                                    (unsigned long) off,
2239                                    (unsigned long) len,
2240                                    (unsigned char *)AA(ubuf));
2241 }
2242
2243 asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
2244 {
2245         return sys_prctl(option,
2246                          (unsigned long) arg2,
2247                          (unsigned long) arg3,
2248                          (unsigned long) arg4,
2249                          (unsigned long) arg5);
2250 }
2251
2252
2253 asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf,
2254                                    compat_size_t count, u32 poshi, u32 poslo)
2255 {
2256         return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
2257 }
2258
2259 asmlinkage compat_ssize_t sys32_pwrite64(unsigned int fd, char *ubuf,
2260                                     compat_size_t count, u32 poshi, u32 poslo)
2261 {
2262         return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
2263 }
2264
2265 asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
2266 {
2267         return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
2268 }
2269
2270 long sys32_fadvise64(int fd, u32 offhi, u32 offlo, s32 len, int advice)
2271 {
2272         return sys_fadvise64_64(fd, ((loff_t)AA(offhi)<<32)|AA(offlo), len, advice);
2273 }
2274
2275 long sys32_fadvise64_64(int fd, u32 offhi, u32 offlo, u32 lenhi, u32 lenlo, int advice)
2276 {
2277         return sys_fadvise64_64(fd, ((loff_t)AA(offhi)<<32)|AA(offlo),
2278                                 ((loff_t)AA(lenhi)<<32)|AA(lenlo), advice);
2279 }
2280
2281 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count)
2282 {
2283         mm_segment_t old_fs = get_fs();
2284         int ret;
2285         off_t of;
2286         
2287         if (offset && get_user(of, offset))
2288                 return -EFAULT;
2289                 
2290         set_fs(KERNEL_DS);
2291         ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
2292         set_fs(old_fs);
2293         
2294         if (offset && put_user(of, offset))
2295                 return -EFAULT;
2296                 
2297         return ret;
2298 }
2299
2300 asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t *offset, s32 count)
2301 {
2302         mm_segment_t old_fs = get_fs();
2303         int ret;
2304         loff_t lof;
2305         
2306         if (offset && get_user(lof, offset))
2307                 return -EFAULT;
2308                 
2309         set_fs(KERNEL_DS);
2310         ret = sys_sendfile64(out_fd, in_fd, offset ? &lof : NULL, count);
2311         set_fs(old_fs);
2312         
2313         if (offset && put_user(lof, offset))
2314                 return -EFAULT;
2315                 
2316         return ret;
2317 }
2318
2319 /* Handle adjtimex compatibility. */
2320
2321 struct timex32 {
2322         u32 modes;
2323         s32 offset, freq, maxerror, esterror;
2324         s32 status, constant, precision, tolerance;
2325         struct compat_timeval time;
2326         s32 tick;
2327         s32 ppsfreq, jitter, shift, stabil;
2328         s32 jitcnt, calcnt, errcnt, stbcnt;
2329         s32  :32; s32  :32; s32  :32; s32  :32;
2330         s32  :32; s32  :32; s32  :32; s32  :32;
2331         s32  :32; s32  :32; s32  :32; s32  :32;
2332 };
2333
2334 extern int do_adjtimex(struct timex *);
2335
2336 asmlinkage int sys32_adjtimex(struct timex32 *utp)
2337 {
2338         struct timex txc;
2339         int ret;
2340
2341         memset(&txc, 0, sizeof(struct timex));
2342
2343         if(get_user(txc.modes, &utp->modes) ||
2344            __get_user(txc.offset, &utp->offset) ||
2345            __get_user(txc.freq, &utp->freq) ||
2346            __get_user(txc.maxerror, &utp->maxerror) ||
2347            __get_user(txc.esterror, &utp->esterror) ||
2348            __get_user(txc.status, &utp->status) ||
2349            __get_user(txc.constant, &utp->constant) ||
2350            __get_user(txc.precision, &utp->precision) ||
2351            __get_user(txc.tolerance, &utp->tolerance) ||
2352            __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
2353            __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
2354            __get_user(txc.tick, &utp->tick) ||
2355            __get_user(txc.ppsfreq, &utp->ppsfreq) ||
2356            __get_user(txc.jitter, &utp->jitter) ||
2357            __get_user(txc.shift, &utp->shift) ||
2358            __get_user(txc.stabil, &utp->stabil) ||
2359            __get_user(txc.jitcnt, &utp->jitcnt) ||
2360            __get_user(txc.calcnt, &utp->calcnt) ||
2361            __get_user(txc.errcnt, &utp->errcnt) ||
2362            __get_user(txc.stbcnt, &utp->stbcnt))
2363                 return -EFAULT;
2364
2365         ret = do_adjtimex(&txc);
2366
2367         if(put_user(txc.modes, &utp->modes) ||
2368            __put_user(txc.offset, &utp->offset) ||
2369            __put_user(txc.freq, &utp->freq) ||
2370            __put_user(txc.maxerror, &utp->maxerror) ||
2371            __put_user(txc.esterror, &utp->esterror) ||
2372            __put_user(txc.status, &utp->status) ||
2373            __put_user(txc.constant, &utp->constant) ||
2374            __put_user(txc.precision, &utp->precision) ||
2375            __put_user(txc.tolerance, &utp->tolerance) ||
2376            __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
2377            __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
2378            __put_user(txc.tick, &utp->tick) ||
2379            __put_user(txc.ppsfreq, &utp->ppsfreq) ||
2380            __put_user(txc.jitter, &utp->jitter) ||
2381            __put_user(txc.shift, &utp->shift) ||
2382            __put_user(txc.stabil, &utp->stabil) ||
2383            __put_user(txc.jitcnt, &utp->jitcnt) ||
2384            __put_user(txc.calcnt, &utp->calcnt) ||
2385            __put_user(txc.errcnt, &utp->errcnt) ||
2386            __put_user(txc.stbcnt, &utp->stbcnt))
2387                 ret = -EFAULT;
2388
2389         return ret;
2390 }
2391
2392 /* This is just a version for 32-bit applications which does
2393  * not force O_LARGEFILE on.
2394  */
2395
2396 asmlinkage long sparc32_open(const char * filename, int flags, int mode)
2397 {
2398         char * tmp;
2399         int fd, error;
2400
2401         tmp = getname(filename);
2402         fd = PTR_ERR(tmp);
2403         if (!IS_ERR(tmp)) {
2404                 fd = get_unused_fd();
2405                 if (fd >= 0) {
2406                         struct file * f = filp_open(tmp, flags, mode);
2407                         error = PTR_ERR(f);
2408                         if (IS_ERR(f))
2409                                 goto out_error;
2410                         fd_install(fd, f);
2411                 }
2412 out:
2413                 putname(tmp);
2414         }
2415         return fd;
2416
2417 out_error:
2418         put_unused_fd(fd);
2419         fd = error;
2420         goto out;
2421 }
2422
2423 extern unsigned long do_mremap(unsigned long addr,
2424         unsigned long old_len, unsigned long new_len,
2425         unsigned long flags, unsigned long new_addr);
2426                 
2427 asmlinkage unsigned long sys32_mremap(unsigned long addr,
2428         unsigned long old_len, unsigned long new_len,
2429         unsigned long flags, u32 __new_addr)
2430 {
2431         struct vm_area_struct *vma;
2432         unsigned long ret = -EINVAL;
2433         unsigned long new_addr = AA(__new_addr);
2434
2435         if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
2436                 goto out;
2437         if (addr > 0xf0000000UL - old_len)
2438                 goto out;
2439         down_write(&current->mm->mmap_sem);
2440         if (flags & MREMAP_FIXED) {
2441                 if (new_addr > 0xf0000000UL - new_len)
2442                         goto out_sem;
2443         } else if (addr > 0xf0000000UL - new_len) {
2444                 unsigned long map_flags = 0;
2445                 struct file *file = NULL;
2446
2447                 ret = -ENOMEM;
2448                 if (!(flags & MREMAP_MAYMOVE))
2449                         goto out_sem;
2450
2451                 vma = find_vma(current->mm, addr);
2452                 if (vma) {
2453                         if (vma->vm_flags & VM_SHARED)
2454                                 map_flags |= MAP_SHARED;
2455                         file = vma->vm_file;
2456                 }
2457
2458                 /* MREMAP_FIXED checked above. */
2459                 new_addr = get_unmapped_area(file, addr, new_len,
2460                                     vma ? vma->vm_pgoff : 0,
2461                                     map_flags);
2462                 ret = new_addr;
2463                 if (new_addr & ~PAGE_MASK)
2464                         goto out_sem;
2465                 flags |= MREMAP_FIXED;
2466         }
2467         ret = do_mremap(addr, old_len, new_len, flags, new_addr);
2468 out_sem:
2469         up_write(&current->mm->mmap_sem);
2470 out:
2471         return ret;       
2472 }
2473
2474 asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
2475 {
2476         return sys_setpriority((int) which,
2477                                (int) who,
2478                                (int) niceval);
2479 }
2480
2481 struct __sysctl_args32 {
2482         u32 name;
2483         int nlen;
2484         u32 oldval;
2485         u32 oldlenp;
2486         u32 newval;
2487         u32 newlen;
2488         u32 __unused[4];
2489 };
2490
2491 asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
2492 {
2493 #ifndef CONFIG_SYSCTL
2494         return -ENOSYS;
2495 #else
2496         struct __sysctl_args32 tmp;
2497         int error;
2498         size_t oldlen, *oldlenp = NULL;
2499         unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
2500
2501         if (copy_from_user(&tmp, args, sizeof(tmp)))
2502                 return -EFAULT;
2503
2504         if (tmp.oldval && tmp.oldlenp) {
2505                 /* Duh, this is ugly and might not work if sysctl_args
2506                    is in read-only memory, but do_sysctl does indirectly
2507                    a lot of uaccess in both directions and we'd have to
2508                    basically copy the whole sysctl.c here, and
2509                    glibc's __sysctl uses rw memory for the structure
2510                    anyway.  */
2511                 if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
2512                     put_user(oldlen, (size_t *)addr))
2513                         return -EFAULT;
2514                 oldlenp = (size_t *)addr;
2515         }
2516
2517         lock_kernel();
2518         error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
2519                           oldlenp, (void *)A(tmp.newval), tmp.newlen);
2520         unlock_kernel();
2521         if (oldlenp) {
2522                 if (!error) {
2523                         if (get_user(oldlen, (size_t *)addr) ||
2524                             put_user(oldlen, (u32 *)A(tmp.oldlenp)))
2525                                 error = -EFAULT;
2526                 }
2527                 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
2528         }
2529         return error;
2530 #endif
2531 }
2532
2533 long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf, size_t len)
2534 {
2535         return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
2536                                   buf, len);
2537 }
2538
2539 extern asmlinkage long
2540 sys_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec,
2541                  timer_t * created_timer_id);
2542
2543 long
2544 sys32_timer_create(u32 clock, struct sigevent32 *se32, timer_t *timer_id)
2545 {
2546         struct sigevent se;
2547         mm_segment_t oldfs;
2548         timer_t t;
2549         long err;
2550
2551         if (se32 == NULL)
2552                 return sys_timer_create(clock, NULL, timer_id);
2553
2554         memset(&se, 0, sizeof(struct sigevent));
2555         if (get_user(se.sigev_value.sival_int,  &se32->sigev_value.sival_int) ||
2556             __get_user(se.sigev_signo, &se32->sigev_signo) ||
2557             __get_user(se.sigev_notify, &se32->sigev_notify) ||
2558             __copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad,
2559             sizeof(se._sigev_un._pad)))
2560                 return -EFAULT;
2561
2562         if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
2563                 return -EFAULT;
2564
2565         oldfs = get_fs();
2566         set_fs(KERNEL_DS);
2567         err = sys_timer_create(clock, &se, &t);
2568         set_fs(oldfs);
2569
2570         if (!err)
2571                 err = __put_user (t, timer_id);
2572
2573         return err;
2574 }
2575