Pull bugzilla-5452 into release branch
[pandora-kernel.git] / arch / mips / kernel / linux32.c
1 /*
2  * Conversion between 32-bit and 64-bit native system calls.
3  *
4  * Copyright (C) 2000 Silicon Graphics, Inc.
5  * Written by Ulf Carlsson (ulfc@engr.sgi.com)
6  * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com)
7  */
8 #include <linux/config.h>
9 #include <linux/compiler.h>
10 #include <linux/mm.h>
11 #include <linux/errno.h>
12 #include <linux/file.h>
13 #include <linux/smp_lock.h>
14 #include <linux/highuid.h>
15 #include <linux/dirent.h>
16 #include <linux/resource.h>
17 #include <linux/highmem.h>
18 #include <linux/time.h>
19 #include <linux/times.h>
20 #include <linux/poll.h>
21 #include <linux/slab.h>
22 #include <linux/skbuff.h>
23 #include <linux/filter.h>
24 #include <linux/shm.h>
25 #include <linux/sem.h>
26 #include <linux/msg.h>
27 #include <linux/icmpv6.h>
28 #include <linux/syscalls.h>
29 #include <linux/sysctl.h>
30 #include <linux/utime.h>
31 #include <linux/utsname.h>
32 #include <linux/personality.h>
33 #include <linux/dnotify.h>
34 #include <linux/module.h>
35 #include <linux/binfmts.h>
36 #include <linux/security.h>
37 #include <linux/compat.h>
38 #include <linux/vfs.h>
39
40 #include <net/sock.h>
41 #include <net/scm.h>
42
43 #include <asm/ipc.h>
44 #include <asm/sim.h>
45 #include <asm/uaccess.h>
46 #include <asm/mmu_context.h>
47 #include <asm/mman.h>
48
49 /* Use this to get at 32-bit user passed pointers. */
50 /* A() macro should be used for places where you e.g.
51    have some internal variable u32 and just want to get
52    rid of a compiler warning. AA() has to be used in
53    places where you want to convert a function argument
54    to 32bit pointer or when you e.g. access pt_regs
55    structure and want to consider 32bit registers only.
56  */
57 #define A(__x) ((unsigned long)(__x))
58 #define AA(__x) ((unsigned long)((int)__x))
59
60 #ifdef __MIPSEB__
61 #define merge_64(r1,r2) ((((r1) & 0xffffffffUL) << 32) + ((r2) & 0xffffffffUL))
62 #endif
63 #ifdef __MIPSEL__
64 #define merge_64(r1,r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL))
65 #endif
66
67 /*
68  * Revalidate the inode. This is required for proper NFS attribute caching.
69  */
70
71 int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
72 {
73         struct compat_stat tmp;
74
75         if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
76                 return -EOVERFLOW;
77
78         memset(&tmp, 0, sizeof(tmp));
79         tmp.st_dev = new_encode_dev(stat->dev);
80         tmp.st_ino = stat->ino;
81         tmp.st_mode = stat->mode;
82         tmp.st_nlink = stat->nlink;
83         SET_UID(tmp.st_uid, stat->uid);
84         SET_GID(tmp.st_gid, stat->gid);
85         tmp.st_rdev = new_encode_dev(stat->rdev);
86         tmp.st_size = stat->size;
87         tmp.st_atime = stat->atime.tv_sec;
88         tmp.st_mtime = stat->mtime.tv_sec;
89         tmp.st_ctime = stat->ctime.tv_sec;
90 #ifdef STAT_HAVE_NSEC
91         tmp.st_atime_nsec = stat->atime.tv_nsec;
92         tmp.st_mtime_nsec = stat->mtime.tv_nsec;
93         tmp.st_ctime_nsec = stat->ctime.tv_nsec;
94 #endif
95         tmp.st_blocks = stat->blocks;
96         tmp.st_blksize = stat->blksize;
97         return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
98 }
99
100 asmlinkage unsigned long
101 sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
102          unsigned long flags, unsigned long fd, unsigned long pgoff)
103 {
104         struct file * file = NULL;
105         unsigned long error;
106
107         error = -EINVAL;
108         if (pgoff & (~PAGE_MASK >> 12))
109                 goto out;
110         pgoff >>= PAGE_SHIFT-12;
111
112         if (!(flags & MAP_ANONYMOUS)) {
113                 error = -EBADF;
114                 file = fget(fd);
115                 if (!file)
116                         goto out;
117         }
118         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
119
120         down_write(&current->mm->mmap_sem);
121         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
122         up_write(&current->mm->mmap_sem);
123         if (file)
124                 fput(file);
125
126 out:
127         return error;
128 }
129
130
131 asmlinkage int sys_truncate64(const char __user *path, unsigned int high,
132                               unsigned int low)
133 {
134         if ((int)high < 0)
135                 return -EINVAL;
136         return sys_truncate(path, ((long) high << 32) | low);
137 }
138
139 asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high,
140                                unsigned int low)
141 {
142         if ((int)high < 0)
143                 return -EINVAL;
144         return sys_ftruncate(fd, ((long) high << 32) | low);
145 }
146
147 /*
148  * sys_execve() executes a new program.
149  */
150 asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)
151 {
152         int error;
153         char * filename;
154
155         filename = getname(compat_ptr(regs.regs[4]));
156         error = PTR_ERR(filename);
157         if (IS_ERR(filename))
158                 goto out;
159         error = compat_do_execve(filename, compat_ptr(regs.regs[5]),
160                                  compat_ptr(regs.regs[6]), &regs);
161         putname(filename);
162
163 out:
164         return error;
165 }
166
167 asmlinkage long
168 sysn32_waitid(int which, compat_pid_t pid,
169               siginfo_t __user *uinfo, int options,
170               struct compat_rusage __user *uru)
171 {
172         struct rusage ru;
173         long ret;
174         mm_segment_t old_fs = get_fs();
175         int si_signo;
176
177         if (!access_ok(VERIFY_WRITE, uinfo, sizeof(*uinfo)))
178                 return -EFAULT;
179
180         set_fs (KERNEL_DS);
181         ret = sys_waitid(which, pid, uinfo, options,
182                          uru ? (struct rusage __user *) &ru : NULL);
183         set_fs (old_fs);
184
185         if (__get_user(si_signo, &uinfo->si_signo))
186                 return -EFAULT;
187         if (ret < 0 || si_signo == 0)
188                 return ret;
189
190         if (uru)
191                 ret = put_compat_rusage(&ru, uru);
192         return ret;
193 }
194
195 struct sysinfo32 {
196         s32 uptime;
197         u32 loads[3];
198         u32 totalram;
199         u32 freeram;
200         u32 sharedram;
201         u32 bufferram;
202         u32 totalswap;
203         u32 freeswap;
204         u16 procs;
205         u32 totalhigh;
206         u32 freehigh;
207         u32 mem_unit;
208         char _f[8];
209 };
210
211 asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info)
212 {
213         struct sysinfo s;
214         int ret, err;
215         mm_segment_t old_fs = get_fs ();
216
217         set_fs (KERNEL_DS);
218         ret = sys_sysinfo((struct sysinfo __user *)&s);
219         set_fs (old_fs);
220         err = put_user (s.uptime, &info->uptime);
221         err |= __put_user (s.loads[0], &info->loads[0]);
222         err |= __put_user (s.loads[1], &info->loads[1]);
223         err |= __put_user (s.loads[2], &info->loads[2]);
224         err |= __put_user (s.totalram, &info->totalram);
225         err |= __put_user (s.freeram, &info->freeram);
226         err |= __put_user (s.sharedram, &info->sharedram);
227         err |= __put_user (s.bufferram, &info->bufferram);
228         err |= __put_user (s.totalswap, &info->totalswap);
229         err |= __put_user (s.freeswap, &info->freeswap);
230         err |= __put_user (s.procs, &info->procs);
231         err |= __put_user (s.totalhigh, &info->totalhigh);
232         err |= __put_user (s.freehigh, &info->freehigh);
233         err |= __put_user (s.mem_unit, &info->mem_unit);
234         if (err)
235                 return -EFAULT;
236         return ret;
237 }
238
239 #define RLIM_INFINITY32 0x7fffffff
240 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
241
242 struct rlimit32 {
243         int     rlim_cur;
244         int     rlim_max;
245 };
246
247 #ifdef __MIPSEB__
248 asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy,
249         int length_hi, int length_lo)
250 #endif
251 #ifdef __MIPSEL__
252 asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy,
253         int length_lo, int length_hi)
254 #endif
255 {
256         loff_t length;
257
258         length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo;
259
260         return sys_truncate(path, length);
261 }
262
263 #ifdef __MIPSEB__
264 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
265         int length_hi, int length_lo)
266 #endif
267 #ifdef __MIPSEL__
268 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
269         int length_lo, int length_hi)
270 #endif
271 {
272         loff_t length;
273
274         length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo;
275
276         return sys_ftruncate(fd, length);
277 }
278
279 static inline long
280 get_tv32(struct timeval *o, struct compat_timeval __user *i)
281 {
282         return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
283                 (__get_user(o->tv_sec, &i->tv_sec) |
284                  __get_user(o->tv_usec, &i->tv_usec)));
285 }
286
287 static inline long
288 put_tv32(struct compat_timeval __user *o, struct timeval *i)
289 {
290         return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
291                 (__put_user(i->tv_sec, &o->tv_sec) |
292                  __put_user(i->tv_usec, &o->tv_usec)));
293 }
294
295 extern struct timezone sys_tz;
296
297 asmlinkage int
298 sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
299 {
300         if (tv) {
301                 struct timeval ktv;
302                 do_gettimeofday(&ktv);
303                 if (put_tv32(tv, &ktv))
304                         return -EFAULT;
305         }
306         if (tz) {
307                 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
308                         return -EFAULT;
309         }
310         return 0;
311 }
312
313 static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
314 {
315         long usec;
316
317         if (!access_ok(VERIFY_READ, i, sizeof(*i)))
318                 return -EFAULT;
319         if (__get_user(o->tv_sec, &i->tv_sec))
320                 return -EFAULT;
321         if (__get_user(usec, &i->tv_usec))
322                 return -EFAULT;
323         o->tv_nsec = usec * 1000;
324                 return 0;
325 }
326
327 asmlinkage int
328 sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
329 {
330         struct timespec kts;
331         struct timezone ktz;
332
333         if (tv) {
334                 if (get_ts32(&kts, tv))
335                         return -EFAULT;
336         }
337         if (tz) {
338                 if (copy_from_user(&ktz, tz, sizeof(ktz)))
339                         return -EFAULT;
340         }
341
342         return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
343 }
344
345 asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
346                             unsigned int offset_low, loff_t __user * result,
347                             unsigned int origin)
348 {
349         return sys_llseek(fd, offset_high, offset_low, result, origin);
350 }
351
352 /* From the Single Unix Spec: pread & pwrite act like lseek to pos + op +
353    lseek back to original location.  They fail just like lseek does on
354    non-seekable files.  */
355
356 asmlinkage ssize_t sys32_pread(unsigned int fd, char __user * buf,
357                                size_t count, u32 unused, u64 a4, u64 a5)
358 {
359         return sys_pread64(fd, buf, count, merge_64(a4, a5));
360 }
361
362 asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char __user * buf,
363                                 size_t count, u32 unused, u64 a4, u64 a5)
364 {
365         return sys_pwrite64(fd, buf, count, merge_64(a4, a5));
366 }
367
368 asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
369         struct compat_timespec __user *interval)
370 {
371         struct timespec t;
372         int ret;
373         mm_segment_t old_fs = get_fs ();
374
375         set_fs (KERNEL_DS);
376         ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
377         set_fs (old_fs);
378         if (put_user (t.tv_sec, &interval->tv_sec) ||
379             __put_user (t.tv_nsec, &interval->tv_nsec))
380                 return -EFAULT;
381         return ret;
382 }
383
384 struct msgbuf32 { s32 mtype; char mtext[1]; };
385
386 struct ipc_perm32
387 {
388         key_t             key;
389         __compat_uid_t  uid;
390         __compat_gid_t  gid;
391         __compat_uid_t  cuid;
392         __compat_gid_t  cgid;
393         compat_mode_t   mode;
394         unsigned short  seq;
395 };
396
397 struct ipc64_perm32 {
398         key_t key;
399         __compat_uid_t uid;
400         __compat_gid_t gid;
401         __compat_uid_t cuid;
402         __compat_gid_t cgid;
403         compat_mode_t   mode;
404         unsigned short  seq;
405         unsigned short __pad1;
406         unsigned int __unused1;
407         unsigned int __unused2;
408 };
409
410 struct semid_ds32 {
411         struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
412         compat_time_t   sem_otime;              /* last semop time */
413         compat_time_t   sem_ctime;              /* last change time */
414         u32 sem_base;              /* ptr to first semaphore in array */
415         u32 sem_pending;          /* pending operations to be processed */
416         u32 sem_pending_last;    /* last pending operation */
417         u32 undo;                  /* undo requests on this array */
418         unsigned short  sem_nsems;              /* no. of semaphores in array */
419 };
420
421 struct semid64_ds32 {
422         struct ipc64_perm32     sem_perm;
423         compat_time_t   sem_otime;
424         compat_time_t   sem_ctime;
425         unsigned int            sem_nsems;
426         unsigned int            __unused1;
427         unsigned int            __unused2;
428 };
429
430 struct msqid_ds32
431 {
432         struct ipc_perm32 msg_perm;
433         u32 msg_first;
434         u32 msg_last;
435         compat_time_t   msg_stime;
436         compat_time_t   msg_rtime;
437         compat_time_t   msg_ctime;
438         u32 wwait;
439         u32 rwait;
440         unsigned short msg_cbytes;
441         unsigned short msg_qnum;
442         unsigned short msg_qbytes;
443         compat_ipc_pid_t msg_lspid;
444         compat_ipc_pid_t msg_lrpid;
445 };
446
447 struct msqid64_ds32 {
448         struct ipc64_perm32 msg_perm;
449         compat_time_t msg_stime;
450         unsigned int __unused1;
451         compat_time_t msg_rtime;
452         unsigned int __unused2;
453         compat_time_t msg_ctime;
454         unsigned int __unused3;
455         unsigned int msg_cbytes;
456         unsigned int msg_qnum;
457         unsigned int msg_qbytes;
458         compat_pid_t msg_lspid;
459         compat_pid_t msg_lrpid;
460         unsigned int __unused4;
461         unsigned int __unused5;
462 };
463
464 struct shmid_ds32 {
465         struct ipc_perm32       shm_perm;
466         int                     shm_segsz;
467         compat_time_t           shm_atime;
468         compat_time_t           shm_dtime;
469         compat_time_t           shm_ctime;
470         compat_ipc_pid_t    shm_cpid;
471         compat_ipc_pid_t    shm_lpid;
472         unsigned short          shm_nattch;
473 };
474
475 struct shmid64_ds32 {
476         struct ipc64_perm32     shm_perm;
477         compat_size_t           shm_segsz;
478         compat_time_t           shm_atime;
479         compat_time_t           shm_dtime;
480         compat_time_t shm_ctime;
481         compat_pid_t shm_cpid;
482         compat_pid_t shm_lpid;
483         unsigned int shm_nattch;
484         unsigned int __unused1;
485         unsigned int __unused2;
486 };
487
488 struct ipc_kludge32 {
489         u32 msgp;
490         s32 msgtyp;
491 };
492
493 static int
494 do_sys32_semctl(int first, int second, int third, void __user *uptr)
495 {
496         union semun fourth;
497         u32 pad;
498         int err, err2;
499         struct semid64_ds s;
500         mm_segment_t old_fs;
501
502         if (!uptr)
503                 return -EINVAL;
504         err = -EFAULT;
505         if (get_user (pad, (u32 __user *)uptr))
506                 return err;
507         if ((third & ~IPC_64) == SETVAL)
508                 fourth.val = (int)pad;
509         else
510                 fourth.__pad = (void __user *)A(pad);
511         switch (third & ~IPC_64) {
512         case IPC_INFO:
513         case IPC_RMID:
514         case IPC_SET:
515         case SEM_INFO:
516         case GETVAL:
517         case GETPID:
518         case GETNCNT:
519         case GETZCNT:
520         case GETALL:
521         case SETVAL:
522         case SETALL:
523                 err = sys_semctl (first, second, third, fourth);
524                 break;
525
526         case IPC_STAT:
527         case SEM_STAT:
528                 fourth.__pad = (struct semid64_ds __user *)&s;
529                 old_fs = get_fs();
530                 set_fs(KERNEL_DS);
531                 err = sys_semctl(first, second, third | IPC_64, fourth);
532                 set_fs(old_fs);
533
534                 if (third & IPC_64) {
535                         struct semid64_ds32 __user *usp64 = (struct semid64_ds32 __user *) A(pad);
536
537                         if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
538                                 err = -EFAULT;
539                                 break;
540                         }
541                         err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key);
542                         err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid);
543                         err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid);
544                         err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid);
545                         err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid);
546                         err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode);
547                         err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq);
548                         err2 |= __put_user(s.sem_otime, &usp64->sem_otime);
549                         err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime);
550                         err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems);
551                 } else {
552                         struct semid_ds32 __user *usp32 = (struct semid_ds32 __user *) A(pad);
553
554                         if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
555                                 err = -EFAULT;
556                                 break;
557                         }
558                         err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key);
559                         err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid);
560                         err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid);
561                         err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid);
562                         err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid);
563                         err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode);
564                         err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq);
565                         err2 |= __put_user(s.sem_otime, &usp32->sem_otime);
566                         err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime);
567                         err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems);
568                 }
569                 if (err2)
570                         err = -EFAULT;
571                 break;
572
573         default:
574                 err = - EINVAL;
575                 break;
576         }
577
578         return err;
579 }
580
581 static int
582 do_sys32_msgsnd (int first, int second, int third, void __user *uptr)
583 {
584         struct msgbuf32 __user *up = (struct msgbuf32 __user *)uptr;
585         struct msgbuf *p;
586         mm_segment_t old_fs;
587         int err;
588
589         if (second < 0)
590                 return -EINVAL;
591         p = kmalloc (second + sizeof (struct msgbuf)
592                                     + 4, GFP_USER);
593         if (!p)
594                 return -ENOMEM;
595         err = get_user (p->mtype, &up->mtype);
596         if (err)
597                 goto out;
598         err |= __copy_from_user (p->mtext, &up->mtext, second);
599         if (err)
600                 goto out;
601         old_fs = get_fs ();
602         set_fs (KERNEL_DS);
603         err = sys_msgsnd (first, (struct msgbuf __user *)p, second, third);
604         set_fs (old_fs);
605 out:
606         kfree (p);
607
608         return err;
609 }
610
611 static int
612 do_sys32_msgrcv (int first, int second, int msgtyp, int third,
613                  int version, void __user *uptr)
614 {
615         struct msgbuf32 __user *up;
616         struct msgbuf *p;
617         mm_segment_t old_fs;
618         int err;
619
620         if (!version) {
621                 struct ipc_kludge32 __user *uipck = (struct ipc_kludge32 __user *)uptr;
622                 struct ipc_kludge32 ipck;
623
624                 err = -EINVAL;
625                 if (!uptr)
626                         goto out;
627                 err = -EFAULT;
628                 if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge32)))
629                         goto out;
630                 uptr = (void __user *)AA(ipck.msgp);
631                 msgtyp = ipck.msgtyp;
632         }
633
634         if (second < 0)
635                 return -EINVAL;
636         err = -ENOMEM;
637         p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
638         if (!p)
639                 goto out;
640         old_fs = get_fs ();
641         set_fs (KERNEL_DS);
642         err = sys_msgrcv (first, (struct msgbuf __user *)p, second + 4, msgtyp, third);
643         set_fs (old_fs);
644         if (err < 0)
645                 goto free_then_out;
646         up = (struct msgbuf32 __user *)uptr;
647         if (put_user (p->mtype, &up->mtype) ||
648             __copy_to_user (&up->mtext, p->mtext, err))
649                 err = -EFAULT;
650 free_then_out:
651         kfree (p);
652 out:
653         return err;
654 }
655
656 static int
657 do_sys32_msgctl (int first, int second, void __user *uptr)
658 {
659         int err = -EINVAL, err2;
660         struct msqid64_ds m;
661         struct msqid_ds32 __user *up32 = (struct msqid_ds32 __user *)uptr;
662         struct msqid64_ds32 __user *up64 = (struct msqid64_ds32 __user *)uptr;
663         mm_segment_t old_fs;
664
665         switch (second & ~IPC_64) {
666         case IPC_INFO:
667         case IPC_RMID:
668         case MSG_INFO:
669                 err = sys_msgctl (first, second, (struct msqid_ds __user *)uptr);
670                 break;
671
672         case IPC_SET:
673                 if (second & IPC_64) {
674                         if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) {
675                                 err = -EFAULT;
676                                 break;
677                         }
678                         err = __get_user(m.msg_perm.uid, &up64->msg_perm.uid);
679                         err |= __get_user(m.msg_perm.gid, &up64->msg_perm.gid);
680                         err |= __get_user(m.msg_perm.mode, &up64->msg_perm.mode);
681                         err |= __get_user(m.msg_qbytes, &up64->msg_qbytes);
682                 } else {
683                         if (!access_ok(VERIFY_READ, up32, sizeof(*up32))) {
684                                 err = -EFAULT;
685                                 break;
686                         }
687                         err = __get_user(m.msg_perm.uid, &up32->msg_perm.uid);
688                         err |= __get_user(m.msg_perm.gid, &up32->msg_perm.gid);
689                         err |= __get_user(m.msg_perm.mode, &up32->msg_perm.mode);
690                         err |= __get_user(m.msg_qbytes, &up32->msg_qbytes);
691                 }
692                 if (err)
693                         break;
694                 old_fs = get_fs();
695                 set_fs(KERNEL_DS);
696                 err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m);
697                 set_fs(old_fs);
698                 break;
699
700         case IPC_STAT:
701         case MSG_STAT:
702                 old_fs = get_fs();
703                 set_fs(KERNEL_DS);
704                 err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m);
705                 set_fs(old_fs);
706                 if (second & IPC_64) {
707                         if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
708                                 err = -EFAULT;
709                                 break;
710                         }
711                         err2 = __put_user(m.msg_perm.key, &up64->msg_perm.key);
712                         err2 |= __put_user(m.msg_perm.uid, &up64->msg_perm.uid);
713                         err2 |= __put_user(m.msg_perm.gid, &up64->msg_perm.gid);
714                         err2 |= __put_user(m.msg_perm.cuid, &up64->msg_perm.cuid);
715                         err2 |= __put_user(m.msg_perm.cgid, &up64->msg_perm.cgid);
716                         err2 |= __put_user(m.msg_perm.mode, &up64->msg_perm.mode);
717                         err2 |= __put_user(m.msg_perm.seq, &up64->msg_perm.seq);
718                         err2 |= __put_user(m.msg_stime, &up64->msg_stime);
719                         err2 |= __put_user(m.msg_rtime, &up64->msg_rtime);
720                         err2 |= __put_user(m.msg_ctime, &up64->msg_ctime);
721                         err2 |= __put_user(m.msg_cbytes, &up64->msg_cbytes);
722                         err2 |= __put_user(m.msg_qnum, &up64->msg_qnum);
723                         err2 |= __put_user(m.msg_qbytes, &up64->msg_qbytes);
724                         err2 |= __put_user(m.msg_lspid, &up64->msg_lspid);
725                         err2 |= __put_user(m.msg_lrpid, &up64->msg_lrpid);
726                         if (err2)
727                                 err = -EFAULT;
728                 } else {
729                         if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
730                                 err = -EFAULT;
731                                 break;
732                         }
733                         err2 = __put_user(m.msg_perm.key, &up32->msg_perm.key);
734                         err2 |= __put_user(m.msg_perm.uid, &up32->msg_perm.uid);
735                         err2 |= __put_user(m.msg_perm.gid, &up32->msg_perm.gid);
736                         err2 |= __put_user(m.msg_perm.cuid, &up32->msg_perm.cuid);
737                         err2 |= __put_user(m.msg_perm.cgid, &up32->msg_perm.cgid);
738                         err2 |= __put_user(m.msg_perm.mode, &up32->msg_perm.mode);
739                         err2 |= __put_user(m.msg_perm.seq, &up32->msg_perm.seq);
740                         err2 |= __put_user(m.msg_stime, &up32->msg_stime);
741                         err2 |= __put_user(m.msg_rtime, &up32->msg_rtime);
742                         err2 |= __put_user(m.msg_ctime, &up32->msg_ctime);
743                         err2 |= __put_user(m.msg_cbytes, &up32->msg_cbytes);
744                         err2 |= __put_user(m.msg_qnum, &up32->msg_qnum);
745                         err2 |= __put_user(m.msg_qbytes, &up32->msg_qbytes);
746                         err2 |= __put_user(m.msg_lspid, &up32->msg_lspid);
747                         err2 |= __put_user(m.msg_lrpid, &up32->msg_lrpid);
748                         if (err2)
749                                 err = -EFAULT;
750                 }
751                 break;
752         }
753
754         return err;
755 }
756
757 static int
758 do_sys32_shmat (int first, int second, int third, int version, void __user *uptr)
759 {
760         unsigned long raddr;
761         u32 __user *uaddr = (u32 __user *)A((u32)third);
762         int err = -EINVAL;
763
764         if (version == 1)
765                 return err;
766         err = do_shmat (first, uptr, second, &raddr);
767         if (err)
768                 return err;
769         err = put_user (raddr, uaddr);
770         return err;
771 }
772
773 struct shm_info32 {
774         int used_ids;
775         u32 shm_tot, shm_rss, shm_swp;
776         u32 swap_attempts, swap_successes;
777 };
778
779 static int
780 do_sys32_shmctl (int first, int second, void __user *uptr)
781 {
782         struct shmid64_ds32 __user *up64 = (struct shmid64_ds32 __user *)uptr;
783         struct shmid_ds32 __user *up32 = (struct shmid_ds32 __user *)uptr;
784         struct shm_info32 __user *uip = (struct shm_info32 __user *)uptr;
785         int err = -EFAULT, err2;
786         struct shmid64_ds s64;
787         mm_segment_t old_fs;
788         struct shm_info si;
789         struct shmid_ds s;
790
791         switch (second & ~IPC_64) {
792         case IPC_INFO:
793                 second = IPC_INFO; /* So that we don't have to translate it */
794         case IPC_RMID:
795         case SHM_LOCK:
796         case SHM_UNLOCK:
797                 err = sys_shmctl(first, second, (struct shmid_ds __user *)uptr);
798                 break;
799         case IPC_SET:
800                 if (second & IPC_64) {
801                         err = get_user(s.shm_perm.uid, &up64->shm_perm.uid);
802                         err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid);
803                         err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode);
804                 } else {
805                         err = get_user(s.shm_perm.uid, &up32->shm_perm.uid);
806                         err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid);
807                         err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode);
808                 }
809                 if (err)
810                         break;
811                 old_fs = get_fs();
812                 set_fs(KERNEL_DS);
813                 err = sys_shmctl(first, second & ~IPC_64, (struct shmid_ds __user *)&s);
814                 set_fs(old_fs);
815                 break;
816
817         case IPC_STAT:
818         case SHM_STAT:
819                 old_fs = get_fs();
820                 set_fs(KERNEL_DS);
821                 err = sys_shmctl(first, second | IPC_64, (void __user *) &s64);
822                 set_fs(old_fs);
823                 if (err < 0)
824                         break;
825                 if (second & IPC_64) {
826                         if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
827                                 err = -EFAULT;
828                                 break;
829                         }
830                         err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
831                         err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
832                         err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
833                         err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
834                         err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
835                         err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
836                         err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
837                         err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
838                         err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
839                         err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
840                         err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
841                         err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
842                         err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
843                         err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
844                 } else {
845                         if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
846                                 err = -EFAULT;
847                                 break;
848                         }
849                         err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
850                         err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
851                         err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
852                         err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
853                         err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
854                         err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
855                         err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
856                         err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
857                         err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
858                         err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
859                         err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
860                         err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
861                         err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
862                         err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
863                 }
864                 if (err2)
865                         err = -EFAULT;
866                 break;
867
868         case SHM_INFO:
869                 old_fs = get_fs();
870                 set_fs(KERNEL_DS);
871                 err = sys_shmctl(first, second, (void __user *)&si);
872                 set_fs(old_fs);
873                 if (err < 0)
874                         break;
875                 err2 = put_user(si.used_ids, &uip->used_ids);
876                 err2 |= __put_user(si.shm_tot, &uip->shm_tot);
877                 err2 |= __put_user(si.shm_rss, &uip->shm_rss);
878                 err2 |= __put_user(si.shm_swp, &uip->shm_swp);
879                 err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
880                 err2 |= __put_user (si.swap_successes, &uip->swap_successes);
881                 if (err2)
882                         err = -EFAULT;
883                 break;
884
885         default:
886                 err = -EINVAL;
887                 break;
888         }
889
890         return err;
891 }
892
893 static int sys32_semtimedop(int semid, struct sembuf __user *tsems, int nsems,
894                             const struct compat_timespec __user *timeout32)
895 {
896         struct compat_timespec t32;
897         struct timespec __user *t64 = compat_alloc_user_space(sizeof(*t64));
898
899         if (copy_from_user(&t32, timeout32, sizeof(t32)))
900                 return -EFAULT;
901
902         if (put_user(t32.tv_sec, &t64->tv_sec) ||
903             put_user(t32.tv_nsec, &t64->tv_nsec))
904                 return -EFAULT;
905
906         return sys_semtimedop(semid, tsems, nsems, t64);
907 }
908
909 asmlinkage long
910 sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
911 {
912         int version, err;
913
914         version = call >> 16; /* hack for backward compatibility */
915         call &= 0xffff;
916
917         switch (call) {
918         case SEMOP:
919                 /* struct sembuf is the same on 32 and 64bit :)) */
920                 err = sys_semtimedop (first, (struct sembuf __user *)AA(ptr), second,
921                                       NULL);
922                 break;
923         case SEMTIMEDOP:
924                 err = sys32_semtimedop (first, (struct sembuf __user *)AA(ptr), second,
925                                       (const struct compat_timespec __user *)AA(fifth));
926                 break;
927         case SEMGET:
928                 err = sys_semget (first, second, third);
929                 break;
930         case SEMCTL:
931                 err = do_sys32_semctl (first, second, third,
932                                        (void __user *)AA(ptr));
933                 break;
934
935         case MSGSND:
936                 err = do_sys32_msgsnd (first, second, third,
937                                        (void __user *)AA(ptr));
938                 break;
939         case MSGRCV:
940                 err = do_sys32_msgrcv (first, second, fifth, third,
941                                        version, (void __user *)AA(ptr));
942                 break;
943         case MSGGET:
944                 err = sys_msgget ((key_t) first, second);
945                 break;
946         case MSGCTL:
947                 err = do_sys32_msgctl (first, second, (void __user *)AA(ptr));
948                 break;
949
950         case SHMAT:
951                 err = do_sys32_shmat (first, second, third,
952                                       version, (void __user *)AA(ptr));
953                 break;
954         case SHMDT:
955                 err = sys_shmdt ((char __user *)A(ptr));
956                 break;
957         case SHMGET:
958                 err = sys_shmget (first, (unsigned)second, third);
959                 break;
960         case SHMCTL:
961                 err = do_sys32_shmctl (first, second, (void __user *)AA(ptr));
962                 break;
963         default:
964                 err = -EINVAL;
965                 break;
966         }
967
968         return err;
969 }
970
971 asmlinkage long sys32_shmat(int shmid, char __user *shmaddr,
972                           int shmflg, int32_t __user *addr)
973 {
974         unsigned long raddr;
975         int err;
976
977         err = do_shmat(shmid, shmaddr, shmflg, &raddr);
978         if (err)
979                 return err;
980
981         return put_user(raddr, addr);
982 }
983
984 struct sysctl_args32
985 {
986         compat_caddr_t name;
987         int nlen;
988         compat_caddr_t oldval;
989         compat_caddr_t oldlenp;
990         compat_caddr_t newval;
991         compat_size_t newlen;
992         unsigned int __unused[4];
993 };
994
995 #ifdef CONFIG_SYSCTL
996
997 asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
998 {
999         struct sysctl_args32 tmp;
1000         int error;
1001         size_t oldlen;
1002         size_t __user *oldlenp = NULL;
1003         unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
1004
1005         if (copy_from_user(&tmp, args, sizeof(tmp)))
1006                 return -EFAULT;
1007
1008         if (tmp.oldval && tmp.oldlenp) {
1009                 /* Duh, this is ugly and might not work if sysctl_args
1010                    is in read-only memory, but do_sysctl does indirectly
1011                    a lot of uaccess in both directions and we'd have to
1012                    basically copy the whole sysctl.c here, and
1013                    glibc's __sysctl uses rw memory for the structure
1014                    anyway.  */
1015                 if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) ||
1016                     put_user(oldlen, (size_t __user *)addr))
1017                         return -EFAULT;
1018                 oldlenp = (size_t __user *)addr;
1019         }
1020
1021         lock_kernel();
1022         error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval),
1023                           oldlenp, (void __user *)A(tmp.newval), tmp.newlen);
1024         unlock_kernel();
1025         if (oldlenp) {
1026                 if (!error) {
1027                         if (get_user(oldlen, (size_t __user *)addr) ||
1028                             put_user(oldlen, (u32 __user *)A(tmp.oldlenp)))
1029                                 error = -EFAULT;
1030                 }
1031                 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
1032         }
1033         return error;
1034 }
1035
1036 #endif /* CONFIG_SYSCTL */
1037
1038 asmlinkage long sys32_newuname(struct new_utsname __user * name)
1039 {
1040         int ret = 0;
1041
1042         down_read(&uts_sem);
1043         if (copy_to_user(name,&system_utsname,sizeof *name))
1044                 ret = -EFAULT;
1045         up_read(&uts_sem);
1046
1047         if (current->personality == PER_LINUX32 && !ret)
1048                 if (copy_to_user(name->machine, "mips\0\0\0", 8))
1049                         ret = -EFAULT;
1050
1051         return ret;
1052 }
1053
1054 asmlinkage int sys32_personality(unsigned long personality)
1055 {
1056         int ret;
1057         if (current->personality == PER_LINUX32 && personality == PER_LINUX)
1058                 personality = PER_LINUX32;
1059         ret = sys_personality(personality);
1060         if (ret == PER_LINUX32)
1061                 ret = PER_LINUX;
1062         return ret;
1063 }
1064
1065 /* ustat compatibility */
1066 struct ustat32 {
1067         compat_daddr_t  f_tfree;
1068         compat_ino_t    f_tinode;
1069         char            f_fname[6];
1070         char            f_fpack[6];
1071 };
1072
1073 extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf);
1074
1075 asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32)
1076 {
1077         int err;
1078         struct ustat tmp;
1079         struct ustat32 tmp32;
1080         mm_segment_t old_fs = get_fs();
1081
1082         set_fs(KERNEL_DS);
1083         err = sys_ustat(dev, (struct ustat __user *)&tmp);
1084         set_fs (old_fs);
1085
1086         if (err)
1087                 goto out;
1088
1089         memset(&tmp32,0,sizeof(struct ustat32));
1090         tmp32.f_tfree = tmp.f_tfree;
1091         tmp32.f_tinode = tmp.f_tinode;
1092
1093         err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0;
1094
1095 out:
1096         return err;
1097 }
1098
1099 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
1100         s32 count)
1101 {
1102         mm_segment_t old_fs = get_fs();
1103         int ret;
1104         off_t of;
1105
1106         if (offset && get_user(of, offset))
1107                 return -EFAULT;
1108
1109         set_fs(KERNEL_DS);
1110         ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count);
1111         set_fs(old_fs);
1112
1113         if (offset && put_user(of, offset))
1114                 return -EFAULT;
1115
1116         return ret;
1117 }
1118
1119 asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
1120                                    size_t count)
1121 {
1122         return sys_readahead(fd, merge_64(a2, a3), count);
1123 }
1124
1125 asmlinkage long sys32_sync_file_range(int fd, int __pad,
1126         unsigned long a2, unsigned long a3,
1127         unsigned long a4, unsigned long a5,
1128         int flags)
1129 {
1130         return sys_sync_file_range(fd,
1131                         merge_64(a2, a3), merge_64(a4, a5),
1132                         flags);
1133 }
1134
1135 /* Argument list sizes for sys_socketcall */
1136 #define AL(x) ((x) * sizeof(unsigned int))
1137 static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
1138                                 AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
1139                                 AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
1140 #undef AL
1141
1142 /*
1143  *      System call vectors.
1144  *
1145  *      Argument checking cleaned up. Saved 20% in size.
1146  *  This function doesn't need to set the kernel lock because
1147  *  it is set by the callees.
1148  */
1149
1150 asmlinkage long sys32_socketcall(int call, unsigned int __user *args32)
1151 {
1152         unsigned int a[6];
1153         unsigned int a0,a1;
1154         int err;
1155
1156         extern asmlinkage long sys_socket(int family, int type, int protocol);
1157         extern asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
1158         extern asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen);
1159         extern asmlinkage long sys_listen(int fd, int backlog);
1160         extern asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen);
1161         extern asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
1162         extern asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
1163         extern asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec);
1164         extern asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags);
1165         extern asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags,
1166                                           struct sockaddr __user *addr, int addr_len);
1167         extern asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags);
1168         extern asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags,
1169                                             struct sockaddr __user *addr, int __user *addr_len);
1170         extern asmlinkage long sys_shutdown(int fd, int how);
1171         extern asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen);
1172         extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen);
1173         extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
1174         extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags);
1175
1176
1177         if(call<1||call>SYS_RECVMSG)
1178                 return -EINVAL;
1179
1180         /* copy_from_user should be SMP safe. */
1181         if (copy_from_user(a, args32, socketcall_nargs[call]))
1182                 return -EFAULT;
1183
1184         a0=a[0];
1185         a1=a[1];
1186
1187         switch(call)
1188         {
1189                 case SYS_SOCKET:
1190                         err = sys_socket(a0,a1,a[2]);
1191                         break;
1192                 case SYS_BIND:
1193                         err = sys_bind(a0,(struct sockaddr __user *)A(a1), a[2]);
1194                         break;
1195                 case SYS_CONNECT:
1196                         err = sys_connect(a0, (struct sockaddr __user *)A(a1), a[2]);
1197                         break;
1198                 case SYS_LISTEN:
1199                         err = sys_listen(a0,a1);
1200                         break;
1201                 case SYS_ACCEPT:
1202                         err = sys_accept(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
1203                         break;
1204                 case SYS_GETSOCKNAME:
1205                         err = sys_getsockname(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
1206                         break;
1207                 case SYS_GETPEERNAME:
1208                         err = sys_getpeername(a0, (struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
1209                         break;
1210                 case SYS_SOCKETPAIR:
1211                         err = sys_socketpair(a0,a1, a[2], (int __user *)A(a[3]));
1212                         break;
1213                 case SYS_SEND:
1214                         err = sys_send(a0, (void __user *)A(a1), a[2], a[3]);
1215                         break;
1216                 case SYS_SENDTO:
1217                         err = sys_sendto(a0,(void __user *)A(a1), a[2], a[3],
1218                                          (struct sockaddr __user *)A(a[4]), a[5]);
1219                         break;
1220                 case SYS_RECV:
1221                         err = sys_recv(a0, (void __user *)A(a1), a[2], a[3]);
1222                         break;
1223                 case SYS_RECVFROM:
1224                         err = sys_recvfrom(a0, (void __user *)A(a1), a[2], a[3],
1225                                            (struct sockaddr __user *)A(a[4]), (int __user *)A(a[5]));
1226                         break;
1227                 case SYS_SHUTDOWN:
1228                         err = sys_shutdown(a0,a1);
1229                         break;
1230                 case SYS_SETSOCKOPT:
1231                         err = sys_setsockopt(a0, a1, a[2], (char __user *)A(a[3]), a[4]);
1232                         break;
1233                 case SYS_GETSOCKOPT:
1234                         err = sys_getsockopt(a0, a1, a[2], (char __user *)A(a[3]), (int __user *)A(a[4]));
1235                         break;
1236                 case SYS_SENDMSG:
1237                         err = sys_sendmsg(a0, (struct msghdr __user *) A(a1), a[2]);
1238                         break;
1239                 case SYS_RECVMSG:
1240                         err = sys_recvmsg(a0, (struct msghdr __user *) A(a1), a[2]);
1241                         break;
1242                 default:
1243                         err = -EINVAL;
1244                         break;
1245         }
1246         return err;
1247 }
1248
1249 struct sigevent32 {
1250         u32 sigev_value;
1251         u32 sigev_signo;
1252         u32 sigev_notify;
1253         u32 payload[(64 / 4) - 3];
1254 };
1255
1256 extern asmlinkage long
1257 sys_timer_create(clockid_t which_clock,
1258                  struct sigevent __user *timer_event_spec,
1259                  timer_t __user * created_timer_id);
1260
1261 long
1262 sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id)
1263 {
1264         struct sigevent __user *p = NULL;
1265         if (se32) {
1266                 struct sigevent se;
1267                 p = compat_alloc_user_space(sizeof(struct sigevent));
1268                 memset(&se, 0, sizeof(struct sigevent));
1269                 if (get_user(se.sigev_value.sival_int,  &se32->sigev_value) ||
1270                     __get_user(se.sigev_signo, &se32->sigev_signo) ||
1271                     __get_user(se.sigev_notify, &se32->sigev_notify) ||
1272                     __copy_from_user(&se._sigev_un._pad, &se32->payload,
1273                                      sizeof(se32->payload)) ||
1274                     copy_to_user(p, &se, sizeof(se)))
1275                         return -EFAULT;
1276         }
1277         return sys_timer_create(clock, p, timer_id);
1278 }
1279
1280 save_static_function(sys32_clone);
1281 __attribute_used__ noinline static int
1282 _sys32_clone(nabi_no_regargs struct pt_regs regs)
1283 {
1284         unsigned long clone_flags;
1285         unsigned long newsp;
1286         int __user *parent_tidptr, *child_tidptr;
1287
1288         clone_flags = regs.regs[4];
1289         newsp = regs.regs[5];
1290         if (!newsp)
1291                 newsp = regs.regs[29];
1292         parent_tidptr = (int __user *) regs.regs[6];
1293
1294         /* Use __dummy4 instead of getting it off the stack, so that
1295            syscall() works.  */
1296         child_tidptr = (int __user *) __dummy4;
1297         return do_fork(clone_flags, newsp, &regs, 0,
1298                        parent_tidptr, child_tidptr);
1299 }
1300
1301 extern asmlinkage void sys_set_thread_area(u32 addr);
1302 asmlinkage void sys32_set_thread_area(u32 addr)
1303 {
1304         sys_set_thread_area(AA(addr));
1305 }