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