patch-2_6_7-vs1_9_1_12
[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 asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group)
66 {
67         return sys_chown(filename, low2highuid(user), low2highgid(group));
68 }
69
70 asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group)
71 {
72         return sys_lchown(filename, low2highuid(user), low2highgid(group));
73 }
74
75 asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
76 {
77         return sys_fchown(fd, low2highuid(user), low2highgid(group));
78 }
79
80 asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
81 {
82         return sys_setregid(low2highgid(rgid), low2highgid(egid));
83 }
84
85 asmlinkage long sys32_setgid16(u16 gid)
86 {
87         return sys_setgid((gid_t)gid);
88 }
89
90 asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
91 {
92         return sys_setreuid(low2highuid(ruid), low2highuid(euid));
93 }
94
95 asmlinkage long sys32_setuid16(u16 uid)
96 {
97         return sys_setuid((uid_t)uid);
98 }
99
100 asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
101 {
102         return sys_setresuid(low2highuid(ruid), low2highuid(euid),
103                 low2highuid(suid));
104 }
105
106 asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid)
107 {
108         int retval;
109
110         if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
111             !(retval = put_user(high2lowuid(current->euid), euid)))
112                 retval = put_user(high2lowuid(current->suid), suid);
113
114         return retval;
115 }
116
117 asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
118 {
119         return sys_setresgid(low2highgid(rgid), low2highgid(egid),
120                 low2highgid(sgid));
121 }
122
123 asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid)
124 {
125         int retval;
126
127         if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
128             !(retval = put_user(high2lowgid(current->egid), egid)))
129                 retval = put_user(high2lowgid(current->sgid), sgid);
130
131         return retval;
132 }
133
134 asmlinkage long sys32_setfsuid16(u16 uid)
135 {
136         return sys_setfsuid((uid_t)uid);
137 }
138
139 asmlinkage long sys32_setfsgid16(u16 gid)
140 {
141         return sys_setfsgid((gid_t)gid);
142 }
143
144 static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info)
145 {
146         int i;
147         u16 group;
148
149         for (i = 0; i < group_info->ngroups; i++) {
150                 group = (u16)GROUP_AT(group_info, i);
151                 if (put_user(group, grouplist+i))
152                         return -EFAULT;
153         }
154
155         return 0;
156 }
157
158 static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist)
159 {
160         int i;
161         u16 group;
162
163         for (i = 0; i < group_info->ngroups; i++) {
164                 if (get_user(group, grouplist+i))
165                         return  -EFAULT;
166                 GROUP_AT(group_info, i) = (gid_t)group;
167         }
168
169         return 0;
170 }
171
172 asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
173 {
174         int i;
175
176         if (gidsetsize < 0)
177                 return -EINVAL;
178
179         get_group_info(current->group_info);
180         i = current->group_info->ngroups;
181         if (gidsetsize) {
182                 if (i > gidsetsize) {
183                         i = -EINVAL;
184                         goto out;
185                 }
186                 if (groups16_to_user(grouplist, current->group_info)) {
187                         i = -EFAULT;
188                         goto out;
189                 }
190         }
191 out:
192         put_group_info(current->group_info);
193         return i;
194 }
195
196 asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
197 {
198         struct group_info *group_info;
199         int retval;
200
201         if (!capable(CAP_SETGID))
202                 return -EPERM;
203         if ((unsigned)gidsetsize > NGROUPS_MAX)
204                 return -EINVAL;
205
206         group_info = groups_alloc(gidsetsize);
207         if (!group_info)
208                 return -ENOMEM;
209         retval = groups16_from_user(group_info, grouplist);
210         if (retval) {
211                 put_group_info(group_info);
212                 return retval;
213         }
214
215         retval = set_current_groups(group_info);
216         put_group_info(group_info);
217
218         return retval;
219 }
220
221 asmlinkage long sys32_getuid16(void)
222 {
223         return high2lowuid(current->uid);
224 }
225
226 asmlinkage long sys32_geteuid16(void)
227 {
228         return high2lowuid(current->euid);
229 }
230
231 asmlinkage long sys32_getgid16(void)
232 {
233         return high2lowgid(current->gid);
234 }
235
236 asmlinkage long sys32_getegid16(void)
237 {
238         return high2lowgid(current->egid);
239 }
240
241 /* 32-bit timeval and related flotsam.  */
242
243 static long get_tv32(struct timeval *o, struct compat_timeval __user *i)
244 {
245         return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||
246                 (__get_user(o->tv_sec, &i->tv_sec) |
247                  __get_user(o->tv_usec, &i->tv_usec)));
248 }
249
250 static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
251 {
252         return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
253                 (__put_user(i->tv_sec, &o->tv_sec) |
254                  __put_user(i->tv_usec, &o->tv_usec)));
255 }
256
257 struct msgbuf32 { s32 mtype; char mtext[1]; };
258
259 struct ipc_perm32 {
260         key_t             key;
261         compat_uid_t  uid;
262         compat_gid_t  gid;
263         compat_uid_t  cuid;
264         compat_gid_t  cgid;
265         compat_mode_t mode;
266         unsigned short  seq;
267 };
268
269 struct semid_ds32 {
270         struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
271         compat_time_t   sem_otime;              /* last semop time */
272         compat_time_t   sem_ctime;              /* last change time */
273         u32 sem_base;              /* ptr to first semaphore in array */
274         u32 sem_pending;          /* pending operations to be processed */
275         u32 sem_pending_last;    /* last pending operation */
276         u32 undo;                  /* undo requests on this array */
277         unsigned short  sem_nsems;              /* no. of semaphores in array */
278 };
279
280 struct semid64_ds32 {
281         struct ipc64_perm sem_perm;               /* this structure is the same on sparc32 and sparc64 */
282         unsigned int      __pad1;
283         compat_time_t   sem_otime;
284         unsigned int      __pad2;
285         compat_time_t   sem_ctime;
286         u32 sem_nsems;
287         u32 __unused1;
288         u32 __unused2;
289 };
290
291 struct msqid_ds32
292 {
293         struct ipc_perm32 msg_perm;
294         u32 msg_first;
295         u32 msg_last;
296         compat_time_t   msg_stime;
297         compat_time_t   msg_rtime;
298         compat_time_t   msg_ctime;
299         u32 wwait;
300         u32 rwait;
301         unsigned short msg_cbytes;
302         unsigned short msg_qnum;  
303         unsigned short msg_qbytes;
304         compat_ipc_pid_t msg_lspid;
305         compat_ipc_pid_t msg_lrpid;
306 };
307
308 struct msqid64_ds32 {
309         struct ipc64_perm msg_perm;
310         unsigned int   __pad1;
311         compat_time_t   msg_stime;
312         unsigned int   __pad2;
313         compat_time_t   msg_rtime;
314         unsigned int   __pad3;
315         compat_time_t   msg_ctime;
316         unsigned int  msg_cbytes;
317         unsigned int  msg_qnum;
318         unsigned int  msg_qbytes;
319         compat_pid_t msg_lspid;
320         compat_pid_t msg_lrpid;
321         unsigned int  __unused1;
322         unsigned int  __unused2;
323 };
324
325
326 struct shmid_ds32 {
327         struct ipc_perm32       shm_perm;
328         int                     shm_segsz;
329         compat_time_t         shm_atime;
330         compat_time_t         shm_dtime;
331         compat_time_t         shm_ctime;
332         compat_ipc_pid_t    shm_cpid; 
333         compat_ipc_pid_t    shm_lpid; 
334         unsigned short          shm_nattch;
335 };
336
337 struct shmid64_ds32 {
338         struct ipc64_perm       shm_perm;
339         unsigned int            __pad1;
340         compat_time_t   shm_atime;
341         unsigned int            __pad2;
342         compat_time_t   shm_dtime;
343         unsigned int            __pad3;
344         compat_time_t   shm_ctime;
345         compat_size_t   shm_segsz;
346         compat_pid_t    shm_cpid;
347         compat_pid_t    shm_lpid;
348         unsigned int            shm_nattch;
349         unsigned int            __unused1;
350         unsigned int            __unused2;
351 };
352
353                                                         
354 /*
355  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
356  *
357  * This is really horribly ugly.
358  */
359 #define IPCOP_MASK(__x) (1UL << ((__x)&~IPC_64))
360 static int do_sys32_semctl(int first, int second, int third,
361                            compat_uptr_t __user *uptr)
362 {
363         union semun fourth;
364         compat_uptr_t pad;
365         int err = -EINVAL;
366
367         if (!uptr)
368                 goto out;
369         err = -EFAULT;
370         if (get_user(pad, uptr))
371                 goto out;
372         if ((third & ~IPC_64) == SETVAL)
373                 fourth.val = (int)pad;
374         else
375                 fourth.__pad = compat_ptr(pad);
376         if (IPCOP_MASK (third) &
377             (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
378              IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
379              IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {
380                 err = sys_semctl (first, second, third, fourth);
381         } else if (third & IPC_64) {
382                 struct semid64_ds s;
383                 struct semid64_ds32 __user *usp = compat_ptr(pad);
384                 mm_segment_t old_fs;
385                 int need_back_translation;
386
387                 if (third == (IPC_SET|IPC_64)) {
388                         err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
389                         err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
390                         err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
391                         if (err)
392                                 goto out;
393                         fourth.__pad = (void __user *) &s;
394                 }
395                 need_back_translation =
396                         (IPCOP_MASK (third) &
397                          (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
398                 if (need_back_translation)
399                         fourth.__pad = (void __user *) &s;
400                 old_fs = get_fs ();
401                 set_fs (KERNEL_DS);
402                 err = sys_semctl (first, second, third, fourth);
403                 set_fs (old_fs);
404                 if (need_back_translation) {
405                         int err2 = copy_to_user (&usp->sem_perm, &s.sem_perm, sizeof(struct ipc64_perm) + 2*sizeof(time_t));
406                         err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
407                         if (err2) err = -EFAULT;
408                 }
409         } else {
410                 struct semid_ds s;
411                 struct semid_ds32 __user *usp = compat_ptr(pad);
412                 mm_segment_t old_fs;
413                 int need_back_translation;
414
415                 if (third == IPC_SET) {
416                         err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
417                         err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
418                         err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
419                         if (err)
420                                 goto out;
421                         fourth.__pad = (void __user *) &s;
422                 }
423                 need_back_translation =
424                         (IPCOP_MASK (third) &
425                          (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
426                 if (need_back_translation)
427                         fourth.__pad = (void __user *) &s;
428                 old_fs = get_fs ();
429                 set_fs (KERNEL_DS);
430                 err = sys_semctl (first, second, third, fourth);
431                 set_fs (old_fs);
432                 if (need_back_translation) {
433                         int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
434                         err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
435                         err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
436                         err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
437                         err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
438                         err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
439                         err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
440                         err2 |= __put_user (s.sem_otime, &usp->sem_otime);
441                         err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
442                         err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
443                         if (err2) err = -EFAULT;
444                 }
445         }
446 out:
447         return err;
448 }
449
450 static int do_sys32_msgsnd(int first, int second, int third,
451                            void __user *uptr)
452 {
453         struct msgbuf32 __user *up = uptr;
454         struct msgbuf *p;
455         mm_segment_t old_fs;
456         int err;
457
458         p = kmalloc(second + sizeof (struct msgbuf), GFP_USER);
459         if (!p)
460                 return -ENOMEM;
461         err = -EFAULT;
462         if (get_user (p->mtype, &up->mtype) ||
463             __copy_from_user (p->mtext, &up->mtext, second))
464                 goto out;
465         old_fs = get_fs ();
466         set_fs (KERNEL_DS);
467         err = sys_msgsnd (first, (struct msgbuf __user *) p,
468                           second, third);
469         set_fs (old_fs);
470 out:
471         kfree (p);
472         return err;
473 }
474
475 static int do_sys32_msgrcv(int first, int second, int msgtyp, int third,
476                            int version, void __user *uptr)
477 {
478         struct msgbuf32 __user *up;
479         struct msgbuf *p;
480         mm_segment_t old_fs;
481         int err;
482
483         if (!version) {
484                 struct ipc_kludge __user *uipck = uptr;
485                 struct ipc_kludge ipck;
486
487                 err = -EINVAL;
488                 if (!uptr)
489                         goto out;
490                 err = -EFAULT;
491                 if (copy_from_user (&ipck, uipck,
492                                     sizeof (struct ipc_kludge)))
493                         goto out;
494                 uptr = compat_ptr(ipck.msgp);
495                 msgtyp = ipck.msgtyp;
496         }
497         err = -ENOMEM;
498         p = kmalloc(second + sizeof (struct msgbuf), GFP_USER);
499         if (!p)
500                 goto out;
501         old_fs = get_fs ();
502         set_fs (KERNEL_DS);
503         err = sys_msgrcv (first, (struct msgbuf __user *) p, second,
504                           msgtyp, third);
505         set_fs (old_fs);
506         if (err < 0)
507                 goto free_then_out;
508         up = uptr;
509         if (put_user (p->mtype, &up->mtype) ||
510             __copy_to_user (&up->mtext, p->mtext, err))
511                 err = -EFAULT;
512 free_then_out:
513         kfree (p);
514 out:
515         return err;
516 }
517
518 static int do_sys32_msgctl(int first, int second, void __user *uptr)
519 {
520         int err;
521
522         if (IPCOP_MASK (second) &
523             (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
524              IPCOP_MASK (IPC_RMID))) {
525                 err = sys_msgctl (first, second, uptr);
526         } else if (second & IPC_64) {
527                 struct msqid64_ds m;
528                 struct msqid64_ds32 __user *up = uptr;
529                 mm_segment_t old_fs;
530
531                 if (second == (IPC_SET|IPC_64)) {
532                         err = get_user (m.msg_perm.uid,
533                                         &up->msg_perm.uid);
534                         err |= __get_user (m.msg_perm.gid,
535                                            &up->msg_perm.gid);
536                         err |= __get_user (m.msg_perm.mode,
537                                            &up->msg_perm.mode);
538                         err |= __get_user (m.msg_qbytes,
539                                            &up->msg_qbytes);
540                         if (err)
541                                 goto out;
542                 }
543                 old_fs = get_fs ();
544                 set_fs (KERNEL_DS);
545                 err = sys_msgctl(first, second,
546                                  (struct msqid_ds __user *)&m);
547                 set_fs (old_fs);
548                 if (IPCOP_MASK (second) &
549                     (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
550                         int err2 = copy_to_user(&up->msg_perm,
551                                                 &m.msg_perm,
552                                                 (sizeof(struct ipc64_perm) + 3*sizeof(time_t)));
553                         err2 |= __put_user (m.msg_cbytes,
554                                             &up->msg_cbytes);
555                         err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
556                         err2 |= __put_user (m.msg_qbytes,
557                                             &up->msg_qbytes);
558                         err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
559                         err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
560                         if (err2)
561                                 err = -EFAULT;
562                 }
563         } else {
564                 struct msqid_ds m;
565                 struct msqid_ds32 __user *up = uptr;
566                 mm_segment_t old_fs;
567
568                 if (second == IPC_SET) {
569                         err = get_user(m.msg_perm.uid,
570                                        &up->msg_perm.uid);
571                         err |= __get_user(m.msg_perm.gid,
572                                           &up->msg_perm.gid);
573                         err |= __get_user(m.msg_perm.mode,
574                                           &up->msg_perm.mode);
575                         err |= __get_user(m.msg_qbytes,
576                                           &up->msg_qbytes);
577                         if (err)
578                                 goto out;
579                 }
580                 old_fs = get_fs ();
581                 set_fs (KERNEL_DS);
582                 err = sys_msgctl(first, second,
583                                  (struct msqid_ds __user *) &m);
584                 set_fs (old_fs);
585                 if (IPCOP_MASK (second) &
586                     (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
587                         int err2 = put_user(m.msg_perm.key,
588                                             &up->msg_perm.key);
589                         err2 |= __put_user(high2lowuid(m.msg_perm.uid),
590                                            &up->msg_perm.uid);
591                         err2 |= __put_user(high2lowgid(m.msg_perm.gid),
592                                            &up->msg_perm.gid);
593                         err2 |= __put_user(high2lowuid(m.msg_perm.cuid),
594                                            &up->msg_perm.cuid);
595                         err2 |= __put_user(high2lowgid(m.msg_perm.cgid),
596                                            &up->msg_perm.cgid);
597                         err2 |= __put_user(m.msg_perm.mode,
598                                            &up->msg_perm.mode);
599                         err2 |= __put_user(m.msg_perm.seq,
600                                            &up->msg_perm.seq);
601                         err2 |= __put_user(m.msg_stime, &up->msg_stime);
602                         err2 |= __put_user(m.msg_rtime, &up->msg_rtime);
603                         err2 |= __put_user(m.msg_ctime, &up->msg_ctime);
604                         err2 |= __put_user(m.msg_cbytes,
605                                            &up->msg_cbytes);
606                         err2 |= __put_user(m.msg_qnum, &up->msg_qnum);
607                         err2 |= __put_user(m.msg_qbytes,
608                                            &up->msg_qbytes);
609                         err2 |= __put_user(m.msg_lspid, &up->msg_lspid);
610                         err2 |= __put_user(m.msg_lrpid, &up->msg_lrpid);
611                         if (err2)
612                                 err = -EFAULT;
613                 }
614         }
615
616 out:
617         return err;
618 }
619
620 static int do_sys32_shmat (int first, int second, int third, int version, void __user *uptr)
621 {
622         unsigned long raddr;
623         u32 __user *uaddr = compat_ptr((compat_uptr_t)third);
624         int err = -EINVAL;
625
626         if (version == 1)
627                 goto out;
628         err = do_shmat (first, uptr, second, &raddr);
629         if (err)
630                 goto out;
631         err = put_user (raddr, uaddr);
632 out:
633         return err;
634 }
635
636 static int do_sys32_shmctl(int first, int second, void __user *uptr)
637 {
638         int err;
639
640         if (IPCOP_MASK (second) &
641             (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) |
642              IPCOP_MASK (SHM_UNLOCK) | IPCOP_MASK (IPC_RMID))) {
643                 if (second == (IPC_INFO|IPC_64)) {
644                         /* So that we don't have to translate it */
645                         second = IPC_INFO;
646                 }
647                 err = sys_shmctl(first, second, uptr);
648         } else if ((second & IPC_64) && second != (SHM_INFO|IPC_64)) {
649                 struct shmid64_ds s;
650                 struct shmid64_ds32 __user *up = uptr;
651                 mm_segment_t old_fs;
652
653                 if (second == (IPC_SET|IPC_64)) {
654                         err = get_user(s.shm_perm.uid,
655                                        &up->shm_perm.uid);
656                         err |= __get_user(s.shm_perm.gid,
657                                           &up->shm_perm.gid);
658                         err |= __get_user(s.shm_perm.mode,
659                                           &up->shm_perm.mode);
660                         if (err)
661                                 goto out;
662                 }
663                 old_fs = get_fs();
664                 set_fs(KERNEL_DS);
665                 err = sys_shmctl(first, second,
666                                  (struct shmid_ds __user *)&s);
667                 set_fs(old_fs);
668                 if (err < 0)
669                         goto out;
670
671                 /* Mask it even in this case so it becomes a CSE. */
672                 if (IPCOP_MASK (second) &
673                     (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
674                         int err2 = copy_to_user(&up->shm_perm,
675                                                 &s.shm_perm,
676                                                 sizeof(struct ipc64_perm) + 3*sizeof(time_t));
677                         err2 |= __put_user(s.shm_segsz, &up->shm_segsz);
678                         err2 |= __put_user(s.shm_nattch,&up->shm_nattch);
679                         err2 |= __put_user(s.shm_cpid, &up->shm_cpid);
680                         err2 |= __put_user(s.shm_lpid, &up->shm_lpid);
681                         if (err2)
682                                 err = -EFAULT;
683                 }
684         } else {
685                 struct shmid_ds s;
686                 struct shmid_ds32 __user *up = uptr;
687                 mm_segment_t old_fs;
688
689                 second &= ~IPC_64;
690                 if (second == IPC_SET) {
691                         err = get_user(s.shm_perm.uid,
692                                        &up->shm_perm.uid);
693                         err |= __get_user(s.shm_perm.gid,
694                                           &up->shm_perm.gid);
695                         err |= __get_user(s.shm_perm.mode,
696                                           &up->shm_perm.mode);
697                         if (err)
698                                 goto out;
699                 }
700                 old_fs = get_fs();
701                 set_fs(KERNEL_DS);
702                 err = sys_shmctl(first, second,
703                                  (struct shmid_ds __user *) &s);
704                 set_fs(old_fs);
705                 if (err < 0)
706                         goto out;
707
708                 /* Mask it even in this case so it becomes a CSE. */
709                 if (second == SHM_INFO) {
710                         struct shm_info32 {
711                                 int used_ids;
712                                 u32 shm_tot, shm_rss, shm_swp;
713                                 u32 swap_attempts, swap_successes;
714                         };
715                         struct shm_info32 __user *uip = uptr;
716                         struct shm_info *kp = (struct shm_info *) &s;
717                         int err2 = put_user(kp->used_ids,
718                                             &uip->used_ids);
719                         err2 |= __put_user(kp->shm_tot, &uip->shm_tot);
720                         err2 |= __put_user(kp->shm_rss, &uip->shm_rss);
721                         err2 |= __put_user(kp->shm_swp, &uip->shm_swp);
722                         err2 |= __put_user(kp->swap_attempts,
723                                            &uip->swap_attempts);
724                         err2 |= __put_user(kp->swap_successes,
725                                            &uip->swap_successes);
726                         if (err2)
727                                 err = -EFAULT;
728                 } else if (IPCOP_MASK (second) &
729                            (IPCOP_MASK (SHM_STAT) |
730                             IPCOP_MASK (IPC_STAT))) {
731                         int err2;
732
733                         err2  = put_user(s.shm_perm.key,
734                                          &up->shm_perm.key);
735                         err2 |= __put_user(high2lowuid(s.shm_perm.uid),
736                                            &up->shm_perm.uid);
737                         err2 |= __put_user(high2lowuid(s.shm_perm.gid),
738                                            &up->shm_perm.gid);
739                         err2 |= __put_user(high2lowuid(s.shm_perm.cuid),
740                                            &up->shm_perm.cuid);
741                         err2 |= __put_user(high2lowuid(s.shm_perm.cgid),
742                                            &up->shm_perm.cgid);
743                         err2 |= __put_user(s.shm_perm.mode,
744                                            &up->shm_perm.mode);
745                         err2 |= __put_user(s.shm_perm.seq,
746                                            &up->shm_perm.seq);
747                         err2 |= __put_user(s.shm_atime, &up->shm_atime);
748                         err2 |= __put_user(s.shm_dtime, &up->shm_dtime);
749                         err2 |= __put_user(s.shm_ctime, &up->shm_ctime);
750                         err2 |= __put_user(s.shm_segsz, &up->shm_segsz);
751                         err2 |= __put_user(s.shm_nattch,&up->shm_nattch);
752                         err2 |= __put_user(s.shm_cpid, &up->shm_cpid);
753                         err2 |= __put_user(s.shm_lpid, &up->shm_lpid);
754                         if (err2)
755                                 err = -EFAULT;
756                 }
757         }
758 out:
759         return err;
760 }
761
762 static int sys32_semtimedop(int semid, struct sembuf __user *tsems,
763                 int nsems,
764                 const struct compat_timespec __user *timeout32)
765 {
766         struct compat_timespec t32;
767         struct timespec __user *t64;
768
769         t64 = compat_alloc_user_space(sizeof(*t64));
770         if (copy_from_user(&t32, timeout32, sizeof(t32)))
771                 return -EFAULT;
772
773         if (put_user(t32.tv_sec, &t64->tv_sec) ||
774             put_user(t32.tv_nsec, &t64->tv_nsec))
775                 return -EFAULT;
776
777         return sys_semtimedop(semid, tsems, nsems, t64);
778 }
779
780 asmlinkage long compat_sys_ipc(u32 call, int first, int second, int third, compat_uptr_t __ptr, u32 fifth)
781 {
782         int version, err;
783         void __user *ptr = compat_ptr(__ptr);
784
785         version = call >> 16; /* hack for backward compatibility */
786         call &= 0xffff;
787
788         if (call <= SEMCTL) {
789                 switch (call) {
790                 case SEMOP:
791                         /* struct sembuf is the same on 32 and 64 :)) */
792                         err = sys_semtimedop (first, ptr, second, NULL);
793                         goto out;
794                 case SEMTIMEDOP:
795                         err = sys32_semtimedop(first, ptr, second,
796                                                compat_ptr(fifth));
797                 case SEMGET:
798                         err = sys_semget(first, second, third);
799                         goto out;
800                 case SEMCTL:
801                         err = do_sys32_semctl(first, second, third, ptr);
802                         goto out;
803                 default:
804                         err = -ENOSYS;
805                         goto out;
806                 };
807         }
808         if (call <= MSGCTL) {
809                 switch (call) {
810                 case MSGSND:
811                         err = do_sys32_msgsnd(first, second, third, ptr);
812                         goto out;
813                 case MSGRCV:
814                         err = do_sys32_msgrcv(first, second, fifth,
815                                               third, version, ptr);
816                         goto out;
817                 case MSGGET:
818                         err = sys_msgget((key_t) first, second);
819                         goto out;
820                 case MSGCTL:
821                         err = do_sys32_msgctl(first, second, ptr);
822                         goto out;
823                 default:
824                         err = -ENOSYS;
825                         goto out;
826                 };
827         }
828         if (call <= SHMCTL) {
829                 switch (call) {
830                 case SHMAT:
831                         err = do_sys32_shmat(first, second, third,
832                                              version, ptr);
833                         goto out;
834                 case SHMDT: 
835                         err = sys_shmdt(ptr);
836                         goto out;
837                 case SHMGET:
838                         err = sys_shmget(first, second, third);
839                         goto out;
840                 case SHMCTL:
841                         err = do_sys32_shmctl(first, second, ptr);
842                         goto out;
843                 default:
844                         err = -ENOSYS;
845                         goto out;
846                 };
847         }
848         err = -ENOSYS;
849
850 out:
851         return err;
852 }
853
854 asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
855 {
856         if ((int)high < 0)
857                 return -EINVAL;
858         else
859                 return sys_truncate(path, (high << 32) | low);
860 }
861
862 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
863 {
864         if ((int)high < 0)
865                 return -EINVAL;
866         else
867                 return sys_ftruncate(fd, (high << 32) | low);
868 }
869
870 /* readdir & getdents */
871
872 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
873 #define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
874
875 struct old_linux_dirent32 {
876         u32             d_ino;
877         u32             d_offset;
878         unsigned short  d_namlen;
879         char            d_name[1];
880 };
881
882 struct readdir_callback32 {
883         struct old_linux_dirent32 __user * dirent;
884         int count;
885 };
886
887 static int fillonedir(void * __buf, const char * name, int namlen,
888                       loff_t offset, ino_t ino, unsigned int d_type)
889 {
890         struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
891         struct old_linux_dirent32 __user * dirent;
892
893         if (buf->count)
894                 return -EINVAL;
895         buf->count++;
896         dirent = buf->dirent;
897         put_user(ino, &dirent->d_ino);
898         put_user(offset, &dirent->d_offset);
899         put_user(namlen, &dirent->d_namlen);
900         copy_to_user(dirent->d_name, name, namlen);
901         put_user(0, dirent->d_name + namlen);
902         return 0;
903 }
904
905 asmlinkage long old32_readdir(unsigned int fd, struct old_linux_dirent32 __user *dirent, unsigned int count)
906 {
907         int error = -EBADF;
908         struct file * file;
909         struct readdir_callback32 buf;
910
911         file = fget(fd);
912         if (!file)
913                 goto out;
914
915         buf.count = 0;
916         buf.dirent = dirent;
917
918         error = vfs_readdir(file, fillonedir, &buf);
919         if (error < 0)
920                 goto out_putf;
921         error = buf.count;
922
923 out_putf:
924         fput(file);
925 out:
926         return error;
927 }
928
929 struct linux_dirent32 {
930         u32             d_ino;
931         u32             d_off;
932         unsigned short  d_reclen;
933         char            d_name[1];
934 };
935
936 struct getdents_callback32 {
937         struct linux_dirent32 __user *current_dir;
938         struct linux_dirent32 __user *previous;
939         int count;
940         int error;
941 };
942
943 static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
944                    unsigned int d_type)
945 {
946         struct linux_dirent32 __user * dirent;
947         struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
948         int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
949
950         buf->error = -EINVAL;   /* only used if we fail.. */
951         if (reclen > buf->count)
952                 return -EINVAL;
953         dirent = buf->previous;
954         if (dirent)
955                 put_user(offset, &dirent->d_off);
956         dirent = buf->current_dir;
957         buf->previous = dirent;
958         put_user(ino, &dirent->d_ino);
959         put_user(reclen, &dirent->d_reclen);
960         copy_to_user(dirent->d_name, name, namlen);
961         put_user(0, dirent->d_name + namlen);
962         put_user(d_type, (char __user *) dirent + reclen - 1);
963         dirent = (void __user *) dirent + reclen;
964         buf->current_dir = dirent;
965         buf->count -= reclen;
966         return 0;
967 }
968
969 asmlinkage long sys32_getdents(unsigned int fd, struct linux_dirent32 __user *dirent, unsigned int count)
970 {
971         struct file * file;
972         struct linux_dirent32 __user *lastdirent;
973         struct getdents_callback32 buf;
974         int error = -EBADF;
975
976         file = fget(fd);
977         if (!file)
978                 goto out;
979
980         buf.current_dir = dirent;
981         buf.previous = NULL;
982         buf.count = count;
983         buf.error = 0;
984
985         error = vfs_readdir(file, filldir, &buf);
986         if (error < 0)
987                 goto out_putf;
988         lastdirent = buf.previous;
989         error = buf.error;
990         if (lastdirent) {
991                 put_user(file->f_pos, &lastdirent->d_off);
992                 error = count - buf.count;
993         }
994 out_putf:
995         fput(file);
996 out:
997         return error;
998 }
999
1000 /* end of readdir & getdents */
1001
1002 int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
1003 {
1004         int err;
1005
1006         if (stat->size > MAX_NON_LFS || !old_valid_dev(stat->dev) ||
1007             !old_valid_dev(stat->rdev))
1008                 return -EOVERFLOW;
1009
1010         err  = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
1011         err |= put_user(stat->ino, &statbuf->st_ino);
1012         err |= put_user(stat->mode, &statbuf->st_mode);
1013         err |= put_user(stat->nlink, &statbuf->st_nlink);
1014         err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
1015         err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
1016         err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
1017         err |= put_user(stat->size, &statbuf->st_size);
1018         err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
1019         err |= put_user(0, &statbuf->__unused1);
1020         err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
1021         err |= put_user(0, &statbuf->__unused2);
1022         err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
1023         err |= put_user(0, &statbuf->__unused3);
1024         err |= put_user(stat->blksize, &statbuf->st_blksize);
1025         err |= put_user(stat->blocks, &statbuf->st_blocks);
1026         err |= put_user(0, &statbuf->__unused4[0]);
1027         err |= put_user(0, &statbuf->__unused4[1]);
1028
1029         return err;
1030 }
1031
1032 asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
1033 {
1034         return sys_sysfs(option, arg1, arg2);
1035 }
1036
1037 struct sysinfo32 {
1038         s32 uptime;
1039         u32 loads[3];
1040         u32 totalram;
1041         u32 freeram;
1042         u32 sharedram;
1043         u32 bufferram;
1044         u32 totalswap;
1045         u32 freeswap;
1046         unsigned short procs;
1047         unsigned short pad;
1048         u32 totalhigh;
1049         u32 freehigh;
1050         u32 mem_unit;
1051         char _f[20-2*sizeof(int)-sizeof(int)];
1052 };
1053
1054 asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info)
1055 {
1056         struct sysinfo s;
1057         int ret, err;
1058         int bitcount = 0;
1059         mm_segment_t old_fs = get_fs ();
1060         
1061         set_fs(KERNEL_DS);
1062         ret = sys_sysinfo((struct sysinfo __user *) &s);
1063         set_fs(old_fs);
1064         /* Check to see if any memory value is too large for 32-bit and
1065          * scale down if needed.
1066          */
1067         if ((s.totalram >> 32) || (s.totalswap >> 32)) {
1068                 while (s.mem_unit < PAGE_SIZE) {
1069                         s.mem_unit <<= 1;
1070                         bitcount++;
1071                 }
1072                 s.totalram >>= bitcount;
1073                 s.freeram >>= bitcount;
1074                 s.sharedram >>= bitcount;
1075                 s.bufferram >>= bitcount;
1076                 s.totalswap >>= bitcount;
1077                 s.freeswap >>= bitcount;
1078                 s.totalhigh >>= bitcount;
1079                 s.freehigh >>= bitcount;
1080         }
1081
1082         err = put_user (s.uptime, &info->uptime);
1083         err |= __put_user (s.loads[0], &info->loads[0]);
1084         err |= __put_user (s.loads[1], &info->loads[1]);
1085         err |= __put_user (s.loads[2], &info->loads[2]);
1086         err |= __put_user (s.totalram, &info->totalram);
1087         err |= __put_user (s.freeram, &info->freeram);
1088         err |= __put_user (s.sharedram, &info->sharedram);
1089         err |= __put_user (s.bufferram, &info->bufferram);
1090         err |= __put_user (s.totalswap, &info->totalswap);
1091         err |= __put_user (s.freeswap, &info->freeswap);
1092         err |= __put_user (s.procs, &info->procs);
1093         err |= __put_user (s.totalhigh, &info->totalhigh);
1094         err |= __put_user (s.freehigh, &info->freehigh);
1095         err |= __put_user (s.mem_unit, &info->mem_unit);
1096         if (err)
1097                 return -EFAULT;
1098         return ret;
1099 }
1100
1101 asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval)
1102 {
1103         struct timespec t;
1104         int ret;
1105         mm_segment_t old_fs = get_fs ();
1106         
1107         set_fs (KERNEL_DS);
1108         ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
1109         set_fs (old_fs);
1110         if (put_compat_timespec(&t, interval))
1111                 return -EFAULT;
1112         return ret;
1113 }
1114
1115 asmlinkage long compat_sys_rt_sigprocmask(int how,
1116                                           compat_sigset_t __user *set,
1117                                           compat_sigset_t __user *oset,
1118                                           compat_size_t sigsetsize)
1119 {
1120         sigset_t s;
1121         compat_sigset_t s32;
1122         int ret;
1123         mm_segment_t old_fs = get_fs();
1124         
1125         if (set) {
1126                 if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))
1127                         return -EFAULT;
1128                 switch (_NSIG_WORDS) {
1129                 case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
1130                 case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
1131                 case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
1132                 case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
1133                 }
1134         }
1135         set_fs (KERNEL_DS);
1136         ret = sys_rt_sigprocmask(how,
1137                                  set ? (sigset_t __user *) &s : NULL,
1138                                  oset ? (sigset_t __user *) &s : NULL,
1139                                  sigsetsize);
1140         set_fs (old_fs);
1141         if (ret) return ret;
1142         if (oset) {
1143                 switch (_NSIG_WORDS) {
1144                 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
1145                 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
1146                 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
1147                 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
1148                 }
1149                 if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))
1150                         return -EFAULT;
1151         }
1152         return 0;
1153 }
1154
1155 asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
1156                                     compat_size_t sigsetsize)
1157 {
1158         sigset_t s;
1159         compat_sigset_t s32;
1160         int ret;
1161         mm_segment_t old_fs = get_fs();
1162                 
1163         set_fs (KERNEL_DS);
1164         ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
1165         set_fs (old_fs);
1166         if (!ret) {
1167                 switch (_NSIG_WORDS) {
1168                 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
1169                 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
1170                 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
1171                 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
1172                 }
1173                 if (copy_to_user (set, &s32, sizeof(compat_sigset_t)))
1174                         return -EFAULT;
1175         }
1176         return ret;
1177 }
1178
1179 asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,
1180                                       siginfo_t32 __user *uinfo,
1181                                       struct compat_timespec __user *uts,
1182                                       compat_size_t sigsetsize)
1183 {
1184         int ret, sig;
1185         sigset_t these;
1186         compat_sigset_t these32;
1187         struct timespec ts;
1188         siginfo_t info;
1189         long timeout = 0;
1190
1191         /* XXX: Don't preclude handling different sized sigset_t's.  */
1192         if (sigsetsize != sizeof(sigset_t))
1193                 return -EINVAL;
1194
1195         if (copy_from_user (&these32, uthese, sizeof(compat_sigset_t)))
1196                 return -EFAULT;
1197
1198         switch (_NSIG_WORDS) {
1199         case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
1200         case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
1201         case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
1202         case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
1203         }
1204                 
1205         /*
1206          * Invert the set of allowed signals to get those we
1207          * want to block.
1208          */
1209         sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
1210         signotset(&these);
1211
1212         if (uts) {
1213                 if (get_compat_timespec(&ts, uts))
1214                         return -EINVAL;
1215                 if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
1216                     || ts.tv_sec < 0)
1217                         return -EINVAL;
1218         }
1219
1220         spin_lock_irq(&current->sighand->siglock);
1221         sig = dequeue_signal(current, &these, &info);
1222         if (!sig) {
1223                 timeout = MAX_SCHEDULE_TIMEOUT;
1224                 if (uts)
1225                         timeout = (timespec_to_jiffies(&ts)
1226                                    + (ts.tv_sec || ts.tv_nsec));
1227
1228                 if (timeout) {
1229                         /* None ready -- temporarily unblock those we're
1230                          * interested while we are sleeping in so that we'll
1231                          * be awakened when they arrive.  */
1232                         current->real_blocked = current->blocked;
1233                         sigandsets(&current->blocked, &current->blocked, &these);
1234                         recalc_sigpending();
1235                         spin_unlock_irq(&current->sighand->siglock);
1236
1237                         current->state = TASK_INTERRUPTIBLE;
1238                         timeout = schedule_timeout(timeout);
1239
1240                         spin_lock_irq(&current->sighand->siglock);
1241                         sig = dequeue_signal(current, &these, &info);
1242                         current->blocked = current->real_blocked;
1243                         siginitset(&current->real_blocked, 0);
1244                         recalc_sigpending();
1245                 }
1246         }
1247         spin_unlock_irq(&current->sighand->siglock);
1248
1249         if (sig) {
1250                 ret = sig;
1251                 if (uinfo) {
1252                         if (copy_siginfo_to_user32(uinfo, &info))
1253                                 ret = -EFAULT;
1254                 }
1255         } else {
1256                 ret = -EAGAIN;
1257                 if (timeout)
1258                         ret = -EINTR;
1259         }
1260
1261         return ret;
1262 }
1263
1264 asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
1265                                            siginfo_t32 __user *uinfo)
1266 {
1267         siginfo_t info;
1268         int ret;
1269         mm_segment_t old_fs = get_fs();
1270         
1271         if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
1272             copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
1273                 return -EFAULT;
1274         set_fs (KERNEL_DS);
1275         ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
1276         set_fs (old_fs);
1277         return ret;
1278 }
1279
1280 asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act,
1281                                      struct old_sigaction32 __user *oact)
1282 {
1283         struct k_sigaction new_ka, old_ka;
1284         int ret;
1285
1286         if (sig < 0) {
1287                 set_thread_flag(TIF_NEWSIGNALS);
1288                 sig = -sig;
1289         }
1290
1291         if (act) {
1292                 compat_old_sigset_t mask;
1293                 u32 u_handler, u_restorer;
1294                 
1295                 ret = get_user(u_handler, &act->sa_handler);
1296                 new_ka.sa.sa_handler = (void *) (long) u_handler;
1297                 ret |= __get_user(u_restorer, &act->sa_restorer);
1298                 new_ka.sa.sa_restorer = (void *) (long) u_restorer;
1299                 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
1300                 ret |= __get_user(mask, &act->sa_mask);
1301                 if (ret)
1302                         return ret;
1303                 new_ka.ka_restorer = NULL;
1304                 siginitset(&new_ka.sa.sa_mask, mask);
1305         }
1306
1307         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
1308
1309         if (!ret && oact) {
1310                 ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
1311                 ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
1312                 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
1313                 ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
1314         }
1315
1316         return ret;
1317 }
1318
1319 asmlinkage long compat_sys_rt_sigaction(int sig,
1320                                         struct sigaction32 __user *act,
1321                                         struct sigaction32 __user *oact,
1322                                         void __user *restorer,
1323                                         compat_size_t sigsetsize)
1324 {
1325         struct k_sigaction new_ka, old_ka;
1326         int ret;
1327         compat_sigset_t set32;
1328
1329         /* XXX: Don't preclude handling different sized sigset_t's.  */
1330         if (sigsetsize != sizeof(compat_sigset_t))
1331                 return -EINVAL;
1332
1333         /* All tasks which use RT signals (effectively) use
1334          * new style signals.
1335          */
1336         set_thread_flag(TIF_NEWSIGNALS);
1337
1338         if (act) {
1339                 u32 u_handler, u_restorer;
1340
1341                 new_ka.ka_restorer = restorer;
1342                 ret = get_user(u_handler, &act->sa_handler);
1343                 new_ka.sa.sa_handler = (void *) (long) u_handler;
1344                 ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));
1345                 switch (_NSIG_WORDS) {
1346                 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
1347                 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
1348                 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
1349                 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
1350                 }
1351                 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
1352                 ret |= __get_user(u_restorer, &act->sa_restorer);
1353                 new_ka.sa.sa_restorer = (void *) (long) u_restorer;
1354                 if (ret)
1355                         return -EFAULT;
1356         }
1357
1358         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
1359
1360         if (!ret && oact) {
1361                 switch (_NSIG_WORDS) {
1362                 case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
1363                 case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
1364                 case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
1365                 case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
1366                 }
1367                 ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
1368                 ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));
1369                 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
1370                 ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
1371                 if (ret)
1372                         ret = -EFAULT;
1373         }
1374
1375         return ret;
1376 }
1377
1378 /*
1379  * sparc32_execve() executes a new program after the asm stub has set
1380  * things up for us.  This should basically do what I want it to.
1381  */
1382 asmlinkage long sparc32_execve(struct pt_regs *regs)
1383 {
1384         int error, base = 0;
1385         char *filename;
1386
1387         /* User register window flush is done by entry.S */
1388
1389         /* Check for indirect call. */
1390         if ((u32)regs->u_regs[UREG_G1] == 0)
1391                 base = 1;
1392
1393         filename = getname(compat_ptr(regs->u_regs[base + UREG_I0]));
1394         error = PTR_ERR(filename);
1395         if (IS_ERR(filename))
1396                 goto out;
1397
1398         error = compat_do_execve(filename,
1399                                  compat_ptr(regs->u_regs[base + UREG_I1]),
1400                                  compat_ptr(regs->u_regs[base + UREG_I2]), regs);
1401
1402         putname(filename);
1403
1404         if (!error) {
1405                 fprs_write(0);
1406                 current_thread_info()->xfsr[0] = 0;
1407                 current_thread_info()->fpsaved[0] = 0;
1408                 regs->tstate &= ~TSTATE_PEF;
1409                 current->ptrace &= ~PT_DTRACE;
1410         }
1411 out:
1412         return error;
1413 }
1414
1415 #ifdef CONFIG_MODULES
1416
1417 asmlinkage long sys32_init_module(void __user *umod, u32 len,
1418                                   const char __user *uargs)
1419 {
1420         return sys_init_module(umod, len, uargs);
1421 }
1422
1423 asmlinkage long sys32_delete_module(const char __user *name_user,
1424                                     unsigned int flags)
1425 {
1426         return sys_delete_module(name_user, flags);
1427 }
1428
1429 #else /* CONFIG_MODULES */
1430
1431 asmlinkage long sys32_init_module(const char __user *name_user,
1432                                   struct module __user *mod_user)
1433 {
1434         return -ENOSYS;
1435 }
1436
1437 asmlinkage long sys32_delete_module(const char __user *name_user)
1438 {
1439         return -ENOSYS;
1440 }
1441
1442 #endif  /* CONFIG_MODULES */
1443
1444 /* Translations due to time_t size differences.  Which affects all
1445    sorts of things, like timeval and itimerval.  */
1446
1447 extern struct timezone sys_tz;
1448
1449 asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv,
1450                                    struct timezone __user *tz)
1451 {
1452         if (tv) {
1453                 struct timeval ktv;
1454                 do_gettimeofday(&ktv);
1455                 if (put_tv32(tv, &ktv))
1456                         return -EFAULT;
1457         }
1458         if (tz) {
1459                 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
1460                         return -EFAULT;
1461         }
1462         return 0;
1463 }
1464
1465 static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
1466 {
1467         long usec;
1468
1469         if (!access_ok(VERIFY_READ, i, sizeof(*i)))
1470                 return -EFAULT;
1471         if (__get_user(o->tv_sec, &i->tv_sec))
1472                 return -EFAULT;
1473         if (__get_user(usec, &i->tv_usec))
1474                 return -EFAULT;
1475         o->tv_nsec = usec * 1000;
1476         return 0;
1477 }
1478
1479 asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
1480                                    struct timezone __user *tz)
1481 {
1482         struct timespec kts;
1483         struct timezone ktz;
1484
1485         if (tv) {
1486                 if (get_ts32(&kts, tv))
1487                         return -EFAULT;
1488         }
1489         if (tz) {
1490                 if (copy_from_user(&ktz, tz, sizeof(ktz)))
1491                         return -EFAULT;
1492         }
1493
1494         return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
1495 }
1496
1497 asmlinkage long sys32_utimes(char __user *filename,
1498                              struct compat_timeval __user *tvs)
1499 {
1500         struct timeval ktvs[2];
1501
1502         if (tvs) {
1503                 if (get_tv32(&ktvs[0], tvs) ||
1504                     get_tv32(&ktvs[1], 1+tvs))
1505                         return -EFAULT;
1506         }
1507
1508         return do_utimes(filename, (tvs ? &ktvs[0] : NULL));
1509 }
1510
1511 /* These are here just in case some old sparc32 binary calls it. */
1512 asmlinkage long sys32_pause(void)
1513 {
1514         current->state = TASK_INTERRUPTIBLE;
1515         schedule();
1516         return -ERESTARTNOHAND;
1517 }
1518
1519 asmlinkage compat_ssize_t sys32_pread64(unsigned int fd,
1520                                         char __user *ubuf,
1521                                         compat_size_t count,
1522                                         unsigned long poshi,
1523                                         unsigned long poslo)
1524 {
1525         return sys_pread64(fd, ubuf, count, (poshi << 32) | poslo);
1526 }
1527
1528 asmlinkage compat_ssize_t sys32_pwrite64(unsigned int fd,
1529                                          char __user *ubuf,
1530                                          compat_size_t count,
1531                                          unsigned long poshi,
1532                                          unsigned long poslo)
1533 {
1534         return sys_pwrite64(fd, ubuf, count, (poshi << 32) | poslo);
1535 }
1536
1537 asmlinkage long compat_sys_readahead(int fd,
1538                                      unsigned long offhi,
1539                                      unsigned long offlo,
1540                                      compat_size_t count)
1541 {
1542         return sys_readahead(fd, (offhi << 32) | offlo, count);
1543 }
1544
1545 long compat_sys_fadvise64(int fd,
1546                           unsigned long offhi,
1547                           unsigned long offlo,
1548                           compat_size_t len, int advice)
1549 {
1550         return sys_fadvise64_64(fd, (offhi << 32) | offlo, len, advice);
1551 }
1552
1553 long compat_sys_fadvise64_64(int fd,
1554                              unsigned long offhi, unsigned long offlo,
1555                              unsigned long lenhi, unsigned long lenlo,
1556                              int advice)
1557 {
1558         return sys_fadvise64_64(fd,
1559                                 (offhi << 32) | offlo,
1560                                 (lenhi << 32) | lenlo,
1561                                 advice);
1562 }
1563
1564 asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
1565                                     compat_off_t __user *offset,
1566                                     compat_size_t count)
1567 {
1568         mm_segment_t old_fs = get_fs();
1569         int ret;
1570         off_t of;
1571         
1572         if (offset && get_user(of, offset))
1573                 return -EFAULT;
1574                 
1575         set_fs(KERNEL_DS);
1576         ret = sys_sendfile(out_fd, in_fd,
1577                            offset ? (off_t __user *) &of : NULL,
1578                            count);
1579         set_fs(old_fs);
1580         
1581         if (offset && put_user(of, offset))
1582                 return -EFAULT;
1583                 
1584         return ret;
1585 }
1586
1587 asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd,
1588                                       compat_loff_t __user *offset,
1589                                       compat_size_t count)
1590 {
1591         mm_segment_t old_fs = get_fs();
1592         int ret;
1593         loff_t lof;
1594         
1595         if (offset && get_user(lof, offset))
1596                 return -EFAULT;
1597                 
1598         set_fs(KERNEL_DS);
1599         ret = sys_sendfile64(out_fd, in_fd,
1600                              offset ? (loff_t __user *) &lof : NULL,
1601                              count);
1602         set_fs(old_fs);
1603         
1604         if (offset && put_user(lof, offset))
1605                 return -EFAULT;
1606                 
1607         return ret;
1608 }
1609
1610 /* Handle adjtimex compatibility. */
1611
1612 struct timex32 {
1613         u32 modes;
1614         s32 offset, freq, maxerror, esterror;
1615         s32 status, constant, precision, tolerance;
1616         struct compat_timeval time;
1617         s32 tick;
1618         s32 ppsfreq, jitter, shift, stabil;
1619         s32 jitcnt, calcnt, errcnt, stbcnt;
1620         s32  :32; s32  :32; s32  :32; s32  :32;
1621         s32  :32; s32  :32; s32  :32; s32  :32;
1622         s32  :32; s32  :32; s32  :32; s32  :32;
1623 };
1624
1625 extern int do_adjtimex(struct timex *);
1626
1627 asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
1628 {
1629         struct timex txc;
1630         int ret;
1631
1632         memset(&txc, 0, sizeof(struct timex));
1633
1634         if (get_user(txc.modes, &utp->modes) ||
1635             __get_user(txc.offset, &utp->offset) ||
1636             __get_user(txc.freq, &utp->freq) ||
1637             __get_user(txc.maxerror, &utp->maxerror) ||
1638             __get_user(txc.esterror, &utp->esterror) ||
1639             __get_user(txc.status, &utp->status) ||
1640             __get_user(txc.constant, &utp->constant) ||
1641             __get_user(txc.precision, &utp->precision) ||
1642             __get_user(txc.tolerance, &utp->tolerance) ||
1643             __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
1644             __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
1645             __get_user(txc.tick, &utp->tick) ||
1646             __get_user(txc.ppsfreq, &utp->ppsfreq) ||
1647             __get_user(txc.jitter, &utp->jitter) ||
1648             __get_user(txc.shift, &utp->shift) ||
1649             __get_user(txc.stabil, &utp->stabil) ||
1650             __get_user(txc.jitcnt, &utp->jitcnt) ||
1651             __get_user(txc.calcnt, &utp->calcnt) ||
1652             __get_user(txc.errcnt, &utp->errcnt) ||
1653             __get_user(txc.stbcnt, &utp->stbcnt))
1654                 return -EFAULT;
1655
1656         ret = do_adjtimex(&txc);
1657
1658         if (put_user(txc.modes, &utp->modes) ||
1659             __put_user(txc.offset, &utp->offset) ||
1660             __put_user(txc.freq, &utp->freq) ||
1661             __put_user(txc.maxerror, &utp->maxerror) ||
1662             __put_user(txc.esterror, &utp->esterror) ||
1663             __put_user(txc.status, &utp->status) ||
1664             __put_user(txc.constant, &utp->constant) ||
1665             __put_user(txc.precision, &utp->precision) ||
1666             __put_user(txc.tolerance, &utp->tolerance) ||
1667             __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
1668             __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
1669             __put_user(txc.tick, &utp->tick) ||
1670             __put_user(txc.ppsfreq, &utp->ppsfreq) ||
1671             __put_user(txc.jitter, &utp->jitter) ||
1672             __put_user(txc.shift, &utp->shift) ||
1673             __put_user(txc.stabil, &utp->stabil) ||
1674             __put_user(txc.jitcnt, &utp->jitcnt) ||
1675             __put_user(txc.calcnt, &utp->calcnt) ||
1676             __put_user(txc.errcnt, &utp->errcnt) ||
1677             __put_user(txc.stbcnt, &utp->stbcnt))
1678                 ret = -EFAULT;
1679
1680         return ret;
1681 }
1682
1683 /* This is just a version for 32-bit applications which does
1684  * not force O_LARGEFILE on.
1685  */
1686
1687 asmlinkage long sparc32_open(const char __user *filename,
1688                              int flags, int mode)
1689 {
1690         char * tmp;
1691         int fd, error;
1692
1693         tmp = getname(filename);
1694         fd = PTR_ERR(tmp);
1695         if (!IS_ERR(tmp)) {
1696                 fd = get_unused_fd();
1697                 if (fd >= 0) {
1698                         struct file * f = filp_open(tmp, flags, mode);
1699                         error = PTR_ERR(f);
1700                         if (IS_ERR(f))
1701                                 goto out_error;
1702                         fd_install(fd, f);
1703                 }
1704 out:
1705                 putname(tmp);
1706         }
1707         return fd;
1708
1709 out_error:
1710         put_unused_fd(fd);
1711         fd = error;
1712         goto out;
1713 }
1714
1715 extern unsigned long do_mremap(unsigned long addr,
1716         unsigned long old_len, unsigned long new_len,
1717         unsigned long flags, unsigned long new_addr);
1718                 
1719 asmlinkage unsigned long sys32_mremap(unsigned long addr,
1720         unsigned long old_len, unsigned long new_len,
1721         unsigned long flags, u32 __new_addr)
1722 {
1723         struct vm_area_struct *vma;
1724         unsigned long ret = -EINVAL;
1725         unsigned long new_addr = __new_addr;
1726
1727         if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
1728                 goto out;
1729         if (addr > 0xf0000000UL - old_len)
1730                 goto out;
1731         down_write(&current->mm->mmap_sem);
1732         if (flags & MREMAP_FIXED) {
1733                 if (new_addr > 0xf0000000UL - new_len)
1734                         goto out_sem;
1735         } else if (addr > 0xf0000000UL - new_len) {
1736                 unsigned long map_flags = 0;
1737                 struct file *file = NULL;
1738
1739                 ret = -ENOMEM;
1740                 if (!(flags & MREMAP_MAYMOVE))
1741                         goto out_sem;
1742
1743                 vma = find_vma(current->mm, addr);
1744                 if (vma) {
1745                         if (vma->vm_flags & VM_SHARED)
1746                                 map_flags |= MAP_SHARED;
1747                         file = vma->vm_file;
1748                 }
1749
1750                 /* MREMAP_FIXED checked above. */
1751                 new_addr = get_unmapped_area(file, addr, new_len,
1752                                     vma ? vma->vm_pgoff : 0,
1753                                     map_flags);
1754                 ret = new_addr;
1755                 if (new_addr & ~PAGE_MASK)
1756                         goto out_sem;
1757                 flags |= MREMAP_FIXED;
1758         }
1759         ret = do_mremap(addr, old_len, new_len, flags, new_addr);
1760 out_sem:
1761         up_write(&current->mm->mmap_sem);
1762 out:
1763         return ret;       
1764 }
1765
1766 struct __sysctl_args32 {
1767         u32 name;
1768         int nlen;
1769         u32 oldval;
1770         u32 oldlenp;
1771         u32 newval;
1772         u32 newlen;
1773         u32 __unused[4];
1774 };
1775
1776 asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
1777 {
1778 #ifndef CONFIG_SYSCTL
1779         return -ENOSYS;
1780 #else
1781         struct __sysctl_args32 tmp;
1782         int error;
1783         size_t oldlen, __user *oldlenp = NULL;
1784         unsigned long addr = (((unsigned long)&args->__unused[0]) + 7UL) & ~7UL;
1785
1786         if (copy_from_user(&tmp, args, sizeof(tmp)))
1787                 return -EFAULT;
1788
1789         if (tmp.oldval && tmp.oldlenp) {
1790                 /* Duh, this is ugly and might not work if sysctl_args
1791                    is in read-only memory, but do_sysctl does indirectly
1792                    a lot of uaccess in both directions and we'd have to
1793                    basically copy the whole sysctl.c here, and
1794                    glibc's __sysctl uses rw memory for the structure
1795                    anyway.  */
1796                 if (get_user(oldlen, (u32 __user *)(unsigned long)tmp.oldlenp) ||
1797                     put_user(oldlen, (size_t __user *)addr))
1798                         return -EFAULT;
1799                 oldlenp = (size_t __user *)addr;
1800         }
1801
1802         lock_kernel();
1803         error = do_sysctl((int __user *)(unsigned long) tmp.name,
1804                           tmp.nlen,
1805                           (void __user *)(unsigned long) tmp.oldval,
1806                           oldlenp,
1807                           (void __user *)(unsigned long) tmp.newval,
1808                           tmp.newlen);
1809         unlock_kernel();
1810         if (oldlenp) {
1811                 if (!error) {
1812                         if (get_user(oldlen, (size_t __user *)addr) ||
1813                             put_user(oldlen, (u32 __user *)(unsigned long) tmp.oldlenp))
1814                                 error = -EFAULT;
1815                 }
1816                 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
1817         }
1818         return error;
1819 #endif
1820 }
1821
1822 long sys32_lookup_dcookie(unsigned long cookie_high,
1823                           unsigned long cookie_low,
1824                           char __user *buf, size_t len)
1825 {
1826         return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
1827                                   buf, len);
1828 }
1829
1830 extern asmlinkage long
1831 sys_timer_create(clockid_t which_clock,
1832                  struct sigevent __user *timer_event_spec,
1833                  timer_t __user *created_timer_id);
1834
1835 long
1836 sys32_timer_create(u32 clock, struct sigevent32 __user *se32,
1837                    timer_t __user *timer_id)
1838 {
1839         struct sigevent se;
1840         mm_segment_t oldfs;
1841         timer_t t;
1842         long err;
1843
1844         if (se32 == NULL)
1845                 return sys_timer_create(clock, NULL, timer_id);
1846
1847         memset(&se, 0, sizeof(struct sigevent));
1848         if (get_user(se.sigev_value.sival_int,  &se32->sigev_value.sival_int) ||
1849             __get_user(se.sigev_signo, &se32->sigev_signo) ||
1850             __get_user(se.sigev_notify, &se32->sigev_notify) ||
1851             __copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad,
1852             sizeof(se._sigev_un._pad)))
1853                 return -EFAULT;
1854
1855         if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
1856                 return -EFAULT;
1857
1858         oldfs = get_fs();
1859         set_fs(KERNEL_DS);
1860         err = sys_timer_create(clock,
1861                                (struct sigevent __user *) &se,
1862                                (timer_t __user *) &t);
1863         set_fs(oldfs);
1864
1865         if (!err)
1866                 err = __put_user (t, timer_id);
1867
1868         return err;
1869 }
1870