Merge with rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[sfrench/cifs-2.6.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/timex.h>
34 #include <linux/dnotify.h>
35 #include <linux/module.h>
36 #include <linux/binfmts.h>
37 #include <linux/security.h>
38 #include <linux/compat.h>
39 #include <linux/vfs.h>
40
41 #include <net/sock.h>
42 #include <net/scm.h>
43
44 #include <asm/ipc.h>
45 #include <asm/sim.h>
46 #include <asm/uaccess.h>
47 #include <asm/mmu_context.h>
48 #include <asm/mman.h>
49
50 /* Use this to get at 32-bit user passed pointers. */
51 /* A() macro should be used for places where you e.g.
52    have some internal variable u32 and just want to get
53    rid of a compiler warning. AA() has to be used in
54    places where you want to convert a function argument
55    to 32bit pointer or when you e.g. access pt_regs
56    structure and want to consider 32bit registers only.
57  */
58 #define A(__x) ((unsigned long)(__x))
59 #define AA(__x) ((unsigned long)((int)__x))
60
61 #ifdef __MIPSEB__
62 #define merge_64(r1,r2) ((((r1) & 0xffffffffUL) << 32) + ((r2) & 0xffffffffUL))
63 #endif
64 #ifdef __MIPSEL__
65 #define merge_64(r1,r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL))
66 #endif
67
68 /*
69  * Revalidate the inode. This is required for proper NFS attribute caching.
70  */
71
72 int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
73 {
74         struct compat_stat tmp;
75
76         if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
77                 return -EOVERFLOW;
78
79         memset(&tmp, 0, sizeof(tmp));
80         tmp.st_dev = new_encode_dev(stat->dev);
81         tmp.st_ino = stat->ino;
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         ssize_t ret;
361         struct file * file;
362         ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
363         loff_t pos;
364
365         ret = -EBADF;
366         file = fget(fd);
367         if (!file)
368                 goto bad_file;
369         if (!(file->f_mode & FMODE_READ))
370                 goto out;
371         pos = merge_64(a4, a5);
372         ret = rw_verify_area(READ, file, &pos, count);
373         if (ret < 0)
374                 goto out;
375         ret = -EINVAL;
376         if (!file->f_op || !(read = file->f_op->read))
377                 goto out;
378         if (pos < 0)
379                 goto out;
380         ret = -ESPIPE;
381         if (!(file->f_mode & FMODE_PREAD))
382                 goto out;
383         ret = read(file, buf, count, &pos);
384         if (ret > 0)
385                 dnotify_parent(file->f_dentry, DN_ACCESS);
386 out:
387         fput(file);
388 bad_file:
389         return ret;
390 }
391
392 asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char __user * buf,
393                                 size_t count, u32 unused, u64 a4, u64 a5)
394 {
395         ssize_t ret;
396         struct file * file;
397         ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
398         loff_t pos;
399
400         ret = -EBADF;
401         file = fget(fd);
402         if (!file)
403                 goto bad_file;
404         if (!(file->f_mode & FMODE_WRITE))
405                 goto out;
406         pos = merge_64(a4, a5);
407         ret = rw_verify_area(WRITE, file, &pos, count);
408         if (ret < 0)
409                 goto out;
410         ret = -EINVAL;
411         if (!file->f_op || !(write = file->f_op->write))
412                 goto out;
413         if (pos < 0)
414                 goto out;
415
416         ret = -ESPIPE;
417         if (!(file->f_mode & FMODE_PWRITE))
418                 goto out;
419
420         ret = write(file, buf, count, &pos);
421         if (ret > 0)
422                 dnotify_parent(file->f_dentry, DN_MODIFY);
423 out:
424         fput(file);
425 bad_file:
426         return ret;
427 }
428
429 asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
430         struct compat_timespec __user *interval)
431 {
432         struct timespec t;
433         int ret;
434         mm_segment_t old_fs = get_fs ();
435
436         set_fs (KERNEL_DS);
437         ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
438         set_fs (old_fs);
439         if (put_user (t.tv_sec, &interval->tv_sec) ||
440             __put_user (t.tv_nsec, &interval->tv_nsec))
441                 return -EFAULT;
442         return ret;
443 }
444
445 struct msgbuf32 { s32 mtype; char mtext[1]; };
446
447 struct ipc_perm32
448 {
449         key_t             key;
450         __compat_uid_t  uid;
451         __compat_gid_t  gid;
452         __compat_uid_t  cuid;
453         __compat_gid_t  cgid;
454         compat_mode_t   mode;
455         unsigned short  seq;
456 };
457
458 struct ipc64_perm32 {
459         key_t key;
460         __compat_uid_t uid;
461         __compat_gid_t gid;
462         __compat_uid_t cuid;
463         __compat_gid_t cgid;
464         compat_mode_t   mode;
465         unsigned short  seq;
466         unsigned short __pad1;
467         unsigned int __unused1;
468         unsigned int __unused2;
469 };
470
471 struct semid_ds32 {
472         struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
473         compat_time_t   sem_otime;              /* last semop time */
474         compat_time_t   sem_ctime;              /* last change time */
475         u32 sem_base;              /* ptr to first semaphore in array */
476         u32 sem_pending;          /* pending operations to be processed */
477         u32 sem_pending_last;    /* last pending operation */
478         u32 undo;                  /* undo requests on this array */
479         unsigned short  sem_nsems;              /* no. of semaphores in array */
480 };
481
482 struct semid64_ds32 {
483         struct ipc64_perm32     sem_perm;
484         compat_time_t   sem_otime;
485         compat_time_t   sem_ctime;
486         unsigned int            sem_nsems;
487         unsigned int            __unused1;
488         unsigned int            __unused2;
489 };
490
491 struct msqid_ds32
492 {
493         struct ipc_perm32 msg_perm;
494         u32 msg_first;
495         u32 msg_last;
496         compat_time_t   msg_stime;
497         compat_time_t   msg_rtime;
498         compat_time_t   msg_ctime;
499         u32 wwait;
500         u32 rwait;
501         unsigned short msg_cbytes;
502         unsigned short msg_qnum;
503         unsigned short msg_qbytes;
504         compat_ipc_pid_t msg_lspid;
505         compat_ipc_pid_t msg_lrpid;
506 };
507
508 struct msqid64_ds32 {
509         struct ipc64_perm32 msg_perm;
510         compat_time_t msg_stime;
511         unsigned int __unused1;
512         compat_time_t msg_rtime;
513         unsigned int __unused2;
514         compat_time_t msg_ctime;
515         unsigned int __unused3;
516         unsigned int msg_cbytes;
517         unsigned int msg_qnum;
518         unsigned int msg_qbytes;
519         compat_pid_t msg_lspid;
520         compat_pid_t msg_lrpid;
521         unsigned int __unused4;
522         unsigned int __unused5;
523 };
524
525 struct shmid_ds32 {
526         struct ipc_perm32       shm_perm;
527         int                     shm_segsz;
528         compat_time_t           shm_atime;
529         compat_time_t           shm_dtime;
530         compat_time_t           shm_ctime;
531         compat_ipc_pid_t    shm_cpid;
532         compat_ipc_pid_t    shm_lpid;
533         unsigned short          shm_nattch;
534 };
535
536 struct shmid64_ds32 {
537         struct ipc64_perm32     shm_perm;
538         compat_size_t           shm_segsz;
539         compat_time_t           shm_atime;
540         compat_time_t           shm_dtime;
541         compat_time_t shm_ctime;
542         compat_pid_t shm_cpid;
543         compat_pid_t shm_lpid;
544         unsigned int shm_nattch;
545         unsigned int __unused1;
546         unsigned int __unused2;
547 };
548
549 struct ipc_kludge32 {
550         u32 msgp;
551         s32 msgtyp;
552 };
553
554 static int
555 do_sys32_semctl(int first, int second, int third, void __user *uptr)
556 {
557         union semun fourth;
558         u32 pad;
559         int err, err2;
560         struct semid64_ds s;
561         mm_segment_t old_fs;
562
563         if (!uptr)
564                 return -EINVAL;
565         err = -EFAULT;
566         if (get_user (pad, (u32 __user *)uptr))
567                 return err;
568         if ((third & ~IPC_64) == SETVAL)
569                 fourth.val = (int)pad;
570         else
571                 fourth.__pad = (void __user *)A(pad);
572         switch (third & ~IPC_64) {
573         case IPC_INFO:
574         case IPC_RMID:
575         case IPC_SET:
576         case SEM_INFO:
577         case GETVAL:
578         case GETPID:
579         case GETNCNT:
580         case GETZCNT:
581         case GETALL:
582         case SETVAL:
583         case SETALL:
584                 err = sys_semctl (first, second, third, fourth);
585                 break;
586
587         case IPC_STAT:
588         case SEM_STAT:
589                 fourth.__pad = (struct semid64_ds __user *)&s;
590                 old_fs = get_fs();
591                 set_fs(KERNEL_DS);
592                 err = sys_semctl(first, second, third | IPC_64, fourth);
593                 set_fs(old_fs);
594
595                 if (third & IPC_64) {
596                         struct semid64_ds32 __user *usp64 = (struct semid64_ds32 __user *) A(pad);
597
598                         if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
599                                 err = -EFAULT;
600                                 break;
601                         }
602                         err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key);
603                         err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid);
604                         err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid);
605                         err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid);
606                         err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid);
607                         err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode);
608                         err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq);
609                         err2 |= __put_user(s.sem_otime, &usp64->sem_otime);
610                         err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime);
611                         err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems);
612                 } else {
613                         struct semid_ds32 __user *usp32 = (struct semid_ds32 __user *) A(pad);
614
615                         if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
616                                 err = -EFAULT;
617                                 break;
618                         }
619                         err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key);
620                         err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid);
621                         err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid);
622                         err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid);
623                         err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid);
624                         err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode);
625                         err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq);
626                         err2 |= __put_user(s.sem_otime, &usp32->sem_otime);
627                         err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime);
628                         err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems);
629                 }
630                 if (err2)
631                         err = -EFAULT;
632                 break;
633
634         default:
635                 err = - EINVAL;
636                 break;
637         }
638
639         return err;
640 }
641
642 static int
643 do_sys32_msgsnd (int first, int second, int third, void __user *uptr)
644 {
645         struct msgbuf32 __user *up = (struct msgbuf32 __user *)uptr;
646         struct msgbuf *p;
647         mm_segment_t old_fs;
648         int err;
649
650         if (second < 0)
651                 return -EINVAL;
652         p = kmalloc (second + sizeof (struct msgbuf)
653                                     + 4, GFP_USER);
654         if (!p)
655                 return -ENOMEM;
656         err = get_user (p->mtype, &up->mtype);
657         if (err)
658                 goto out;
659         err |= __copy_from_user (p->mtext, &up->mtext, second);
660         if (err)
661                 goto out;
662         old_fs = get_fs ();
663         set_fs (KERNEL_DS);
664         err = sys_msgsnd (first, (struct msgbuf __user *)p, second, third);
665         set_fs (old_fs);
666 out:
667         kfree (p);
668
669         return err;
670 }
671
672 static int
673 do_sys32_msgrcv (int first, int second, int msgtyp, int third,
674                  int version, void __user *uptr)
675 {
676         struct msgbuf32 __user *up;
677         struct msgbuf *p;
678         mm_segment_t old_fs;
679         int err;
680
681         if (!version) {
682                 struct ipc_kludge32 __user *uipck = (struct ipc_kludge32 __user *)uptr;
683                 struct ipc_kludge32 ipck;
684
685                 err = -EINVAL;
686                 if (!uptr)
687                         goto out;
688                 err = -EFAULT;
689                 if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge32)))
690                         goto out;
691                 uptr = (void __user *)AA(ipck.msgp);
692                 msgtyp = ipck.msgtyp;
693         }
694
695         if (second < 0)
696                 return -EINVAL;
697         err = -ENOMEM;
698         p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
699         if (!p)
700                 goto out;
701         old_fs = get_fs ();
702         set_fs (KERNEL_DS);
703         err = sys_msgrcv (first, (struct msgbuf __user *)p, second + 4, msgtyp, third);
704         set_fs (old_fs);
705         if (err < 0)
706                 goto free_then_out;
707         up = (struct msgbuf32 __user *)uptr;
708         if (put_user (p->mtype, &up->mtype) ||
709             __copy_to_user (&up->mtext, p->mtext, err))
710                 err = -EFAULT;
711 free_then_out:
712         kfree (p);
713 out:
714         return err;
715 }
716
717 static int
718 do_sys32_msgctl (int first, int second, void __user *uptr)
719 {
720         int err = -EINVAL, err2;
721         struct msqid64_ds m;
722         struct msqid_ds32 __user *up32 = (struct msqid_ds32 __user *)uptr;
723         struct msqid64_ds32 __user *up64 = (struct msqid64_ds32 __user *)uptr;
724         mm_segment_t old_fs;
725
726         switch (second & ~IPC_64) {
727         case IPC_INFO:
728         case IPC_RMID:
729         case MSG_INFO:
730                 err = sys_msgctl (first, second, (struct msqid_ds __user *)uptr);
731                 break;
732
733         case IPC_SET:
734                 if (second & IPC_64) {
735                         if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) {
736                                 err = -EFAULT;
737                                 break;
738                         }
739                         err = __get_user(m.msg_perm.uid, &up64->msg_perm.uid);
740                         err |= __get_user(m.msg_perm.gid, &up64->msg_perm.gid);
741                         err |= __get_user(m.msg_perm.mode, &up64->msg_perm.mode);
742                         err |= __get_user(m.msg_qbytes, &up64->msg_qbytes);
743                 } else {
744                         if (!access_ok(VERIFY_READ, up32, sizeof(*up32))) {
745                                 err = -EFAULT;
746                                 break;
747                         }
748                         err = __get_user(m.msg_perm.uid, &up32->msg_perm.uid);
749                         err |= __get_user(m.msg_perm.gid, &up32->msg_perm.gid);
750                         err |= __get_user(m.msg_perm.mode, &up32->msg_perm.mode);
751                         err |= __get_user(m.msg_qbytes, &up32->msg_qbytes);
752                 }
753                 if (err)
754                         break;
755                 old_fs = get_fs();
756                 set_fs(KERNEL_DS);
757                 err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m);
758                 set_fs(old_fs);
759                 break;
760
761         case IPC_STAT:
762         case MSG_STAT:
763                 old_fs = get_fs();
764                 set_fs(KERNEL_DS);
765                 err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m);
766                 set_fs(old_fs);
767                 if (second & IPC_64) {
768                         if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
769                                 err = -EFAULT;
770                                 break;
771                         }
772                         err2 = __put_user(m.msg_perm.key, &up64->msg_perm.key);
773                         err2 |= __put_user(m.msg_perm.uid, &up64->msg_perm.uid);
774                         err2 |= __put_user(m.msg_perm.gid, &up64->msg_perm.gid);
775                         err2 |= __put_user(m.msg_perm.cuid, &up64->msg_perm.cuid);
776                         err2 |= __put_user(m.msg_perm.cgid, &up64->msg_perm.cgid);
777                         err2 |= __put_user(m.msg_perm.mode, &up64->msg_perm.mode);
778                         err2 |= __put_user(m.msg_perm.seq, &up64->msg_perm.seq);
779                         err2 |= __put_user(m.msg_stime, &up64->msg_stime);
780                         err2 |= __put_user(m.msg_rtime, &up64->msg_rtime);
781                         err2 |= __put_user(m.msg_ctime, &up64->msg_ctime);
782                         err2 |= __put_user(m.msg_cbytes, &up64->msg_cbytes);
783                         err2 |= __put_user(m.msg_qnum, &up64->msg_qnum);
784                         err2 |= __put_user(m.msg_qbytes, &up64->msg_qbytes);
785                         err2 |= __put_user(m.msg_lspid, &up64->msg_lspid);
786                         err2 |= __put_user(m.msg_lrpid, &up64->msg_lrpid);
787                         if (err2)
788                                 err = -EFAULT;
789                 } else {
790                         if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
791                                 err = -EFAULT;
792                                 break;
793                         }
794                         err2 = __put_user(m.msg_perm.key, &up32->msg_perm.key);
795                         err2 |= __put_user(m.msg_perm.uid, &up32->msg_perm.uid);
796                         err2 |= __put_user(m.msg_perm.gid, &up32->msg_perm.gid);
797                         err2 |= __put_user(m.msg_perm.cuid, &up32->msg_perm.cuid);
798                         err2 |= __put_user(m.msg_perm.cgid, &up32->msg_perm.cgid);
799                         err2 |= __put_user(m.msg_perm.mode, &up32->msg_perm.mode);
800                         err2 |= __put_user(m.msg_perm.seq, &up32->msg_perm.seq);
801                         err2 |= __put_user(m.msg_stime, &up32->msg_stime);
802                         err2 |= __put_user(m.msg_rtime, &up32->msg_rtime);
803                         err2 |= __put_user(m.msg_ctime, &up32->msg_ctime);
804                         err2 |= __put_user(m.msg_cbytes, &up32->msg_cbytes);
805                         err2 |= __put_user(m.msg_qnum, &up32->msg_qnum);
806                         err2 |= __put_user(m.msg_qbytes, &up32->msg_qbytes);
807                         err2 |= __put_user(m.msg_lspid, &up32->msg_lspid);
808                         err2 |= __put_user(m.msg_lrpid, &up32->msg_lrpid);
809                         if (err2)
810                                 err = -EFAULT;
811                 }
812                 break;
813         }
814
815         return err;
816 }
817
818 static int
819 do_sys32_shmat (int first, int second, int third, int version, void __user *uptr)
820 {
821         unsigned long raddr;
822         u32 __user *uaddr = (u32 __user *)A((u32)third);
823         int err = -EINVAL;
824
825         if (version == 1)
826                 return err;
827         err = do_shmat (first, uptr, second, &raddr);
828         if (err)
829                 return err;
830         err = put_user (raddr, uaddr);
831         return err;
832 }
833
834 struct shm_info32 {
835         int used_ids;
836         u32 shm_tot, shm_rss, shm_swp;
837         u32 swap_attempts, swap_successes;
838 };
839
840 static int
841 do_sys32_shmctl (int first, int second, void __user *uptr)
842 {
843         struct shmid64_ds32 __user *up64 = (struct shmid64_ds32 __user *)uptr;
844         struct shmid_ds32 __user *up32 = (struct shmid_ds32 __user *)uptr;
845         struct shm_info32 __user *uip = (struct shm_info32 __user *)uptr;
846         int err = -EFAULT, err2;
847         struct shmid64_ds s64;
848         mm_segment_t old_fs;
849         struct shm_info si;
850         struct shmid_ds s;
851
852         switch (second & ~IPC_64) {
853         case IPC_INFO:
854                 second = IPC_INFO; /* So that we don't have to translate it */
855         case IPC_RMID:
856         case SHM_LOCK:
857         case SHM_UNLOCK:
858                 err = sys_shmctl(first, second, (struct shmid_ds __user *)uptr);
859                 break;
860         case IPC_SET:
861                 if (second & IPC_64) {
862                         err = get_user(s.shm_perm.uid, &up64->shm_perm.uid);
863                         err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid);
864                         err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode);
865                 } else {
866                         err = get_user(s.shm_perm.uid, &up32->shm_perm.uid);
867                         err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid);
868                         err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode);
869                 }
870                 if (err)
871                         break;
872                 old_fs = get_fs();
873                 set_fs(KERNEL_DS);
874                 err = sys_shmctl(first, second & ~IPC_64, (struct shmid_ds __user *)&s);
875                 set_fs(old_fs);
876                 break;
877
878         case IPC_STAT:
879         case SHM_STAT:
880                 old_fs = get_fs();
881                 set_fs(KERNEL_DS);
882                 err = sys_shmctl(first, second | IPC_64, (void __user *) &s64);
883                 set_fs(old_fs);
884                 if (err < 0)
885                         break;
886                 if (second & IPC_64) {
887                         if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
888                                 err = -EFAULT;
889                                 break;
890                         }
891                         err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
892                         err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
893                         err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
894                         err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
895                         err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
896                         err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
897                         err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
898                         err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
899                         err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
900                         err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
901                         err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
902                         err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
903                         err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
904                         err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
905                 } else {
906                         if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
907                                 err = -EFAULT;
908                                 break;
909                         }
910                         err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
911                         err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
912                         err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
913                         err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
914                         err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
915                         err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
916                         err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
917                         err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
918                         err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
919                         err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
920                         err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
921                         err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
922                         err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
923                         err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
924                 }
925                 if (err2)
926                         err = -EFAULT;
927                 break;
928
929         case SHM_INFO:
930                 old_fs = get_fs();
931                 set_fs(KERNEL_DS);
932                 err = sys_shmctl(first, second, (void __user *)&si);
933                 set_fs(old_fs);
934                 if (err < 0)
935                         break;
936                 err2 = put_user(si.used_ids, &uip->used_ids);
937                 err2 |= __put_user(si.shm_tot, &uip->shm_tot);
938                 err2 |= __put_user(si.shm_rss, &uip->shm_rss);
939                 err2 |= __put_user(si.shm_swp, &uip->shm_swp);
940                 err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
941                 err2 |= __put_user (si.swap_successes, &uip->swap_successes);
942                 if (err2)
943                         err = -EFAULT;
944                 break;
945
946         default:
947                 err = -EINVAL;
948                 break;
949         }
950
951         return err;
952 }
953
954 static int sys32_semtimedop(int semid, struct sembuf __user *tsems, int nsems,
955                             const struct compat_timespec __user *timeout32)
956 {
957         struct compat_timespec t32;
958         struct timespec __user *t64 = compat_alloc_user_space(sizeof(*t64));
959
960         if (copy_from_user(&t32, timeout32, sizeof(t32)))
961                 return -EFAULT;
962
963         if (put_user(t32.tv_sec, &t64->tv_sec) ||
964             put_user(t32.tv_nsec, &t64->tv_nsec))
965                 return -EFAULT;
966
967         return sys_semtimedop(semid, tsems, nsems, t64);
968 }
969
970 asmlinkage long
971 sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
972 {
973         int version, err;
974
975         version = call >> 16; /* hack for backward compatibility */
976         call &= 0xffff;
977
978         switch (call) {
979         case SEMOP:
980                 /* struct sembuf is the same on 32 and 64bit :)) */
981                 err = sys_semtimedop (first, (struct sembuf __user *)AA(ptr), second,
982                                       NULL);
983                 break;
984         case SEMTIMEDOP:
985                 err = sys32_semtimedop (first, (struct sembuf __user *)AA(ptr), second,
986                                       (const struct compat_timespec __user *)AA(fifth));
987                 break;
988         case SEMGET:
989                 err = sys_semget (first, second, third);
990                 break;
991         case SEMCTL:
992                 err = do_sys32_semctl (first, second, third,
993                                        (void __user *)AA(ptr));
994                 break;
995
996         case MSGSND:
997                 err = do_sys32_msgsnd (first, second, third,
998                                        (void __user *)AA(ptr));
999                 break;
1000         case MSGRCV:
1001                 err = do_sys32_msgrcv (first, second, fifth, third,
1002                                        version, (void __user *)AA(ptr));
1003                 break;
1004         case MSGGET:
1005                 err = sys_msgget ((key_t) first, second);
1006                 break;
1007         case MSGCTL:
1008                 err = do_sys32_msgctl (first, second, (void __user *)AA(ptr));
1009                 break;
1010
1011         case SHMAT:
1012                 err = do_sys32_shmat (first, second, third,
1013                                       version, (void __user *)AA(ptr));
1014                 break;
1015         case SHMDT:
1016                 err = sys_shmdt ((char __user *)A(ptr));
1017                 break;
1018         case SHMGET:
1019                 err = sys_shmget (first, (unsigned)second, third);
1020                 break;
1021         case SHMCTL:
1022                 err = do_sys32_shmctl (first, second, (void __user *)AA(ptr));
1023                 break;
1024         default:
1025                 err = -EINVAL;
1026                 break;
1027         }
1028
1029         return err;
1030 }
1031
1032 asmlinkage long sys32_shmat(int shmid, char __user *shmaddr,
1033                           int shmflg, int32_t __user *addr)
1034 {
1035         unsigned long raddr;
1036         int err;
1037
1038         err = do_shmat(shmid, shmaddr, shmflg, &raddr);
1039         if (err)
1040                 return err;
1041
1042         return put_user(raddr, addr);
1043 }
1044
1045 struct sysctl_args32
1046 {
1047         compat_caddr_t name;
1048         int nlen;
1049         compat_caddr_t oldval;
1050         compat_caddr_t oldlenp;
1051         compat_caddr_t newval;
1052         compat_size_t newlen;
1053         unsigned int __unused[4];
1054 };
1055
1056 #ifdef CONFIG_SYSCTL
1057
1058 asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
1059 {
1060         struct sysctl_args32 tmp;
1061         int error;
1062         size_t oldlen;
1063         size_t __user *oldlenp = NULL;
1064         unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
1065
1066         if (copy_from_user(&tmp, args, sizeof(tmp)))
1067                 return -EFAULT;
1068
1069         if (tmp.oldval && tmp.oldlenp) {
1070                 /* Duh, this is ugly and might not work if sysctl_args
1071                    is in read-only memory, but do_sysctl does indirectly
1072                    a lot of uaccess in both directions and we'd have to
1073                    basically copy the whole sysctl.c here, and
1074                    glibc's __sysctl uses rw memory for the structure
1075                    anyway.  */
1076                 if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) ||
1077                     put_user(oldlen, (size_t __user *)addr))
1078                         return -EFAULT;
1079                 oldlenp = (size_t __user *)addr;
1080         }
1081
1082         lock_kernel();
1083         error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval),
1084                           oldlenp, (void __user *)A(tmp.newval), tmp.newlen);
1085         unlock_kernel();
1086         if (oldlenp) {
1087                 if (!error) {
1088                         if (get_user(oldlen, (size_t __user *)addr) ||
1089                             put_user(oldlen, (u32 __user *)A(tmp.oldlenp)))
1090                                 error = -EFAULT;
1091                 }
1092                 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
1093         }
1094         return error;
1095 }
1096
1097 #endif /* CONFIG_SYSCTL */
1098
1099 asmlinkage long sys32_newuname(struct new_utsname __user * name)
1100 {
1101         int ret = 0;
1102
1103         down_read(&uts_sem);
1104         if (copy_to_user(name,&system_utsname,sizeof *name))
1105                 ret = -EFAULT;
1106         up_read(&uts_sem);
1107
1108         if (current->personality == PER_LINUX32 && !ret)
1109                 if (copy_to_user(name->machine, "mips\0\0\0", 8))
1110                         ret = -EFAULT;
1111
1112         return ret;
1113 }
1114
1115 asmlinkage int sys32_personality(unsigned long personality)
1116 {
1117         int ret;
1118         if (current->personality == PER_LINUX32 && personality == PER_LINUX)
1119                 personality = PER_LINUX32;
1120         ret = sys_personality(personality);
1121         if (ret == PER_LINUX32)
1122                 ret = PER_LINUX;
1123         return ret;
1124 }
1125
1126 /* ustat compatibility */
1127 struct ustat32 {
1128         compat_daddr_t  f_tfree;
1129         compat_ino_t    f_tinode;
1130         char            f_fname[6];
1131         char            f_fpack[6];
1132 };
1133
1134 extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf);
1135
1136 asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32)
1137 {
1138         int err;
1139         struct ustat tmp;
1140         struct ustat32 tmp32;
1141         mm_segment_t old_fs = get_fs();
1142
1143         set_fs(KERNEL_DS);
1144         err = sys_ustat(dev, (struct ustat __user *)&tmp);
1145         set_fs (old_fs);
1146
1147         if (err)
1148                 goto out;
1149
1150         memset(&tmp32,0,sizeof(struct ustat32));
1151         tmp32.f_tfree = tmp.f_tfree;
1152         tmp32.f_tinode = tmp.f_tinode;
1153
1154         err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0;
1155
1156 out:
1157         return err;
1158 }
1159
1160 /* Handle adjtimex compatibility. */
1161
1162 struct timex32 {
1163         u32 modes;
1164         s32 offset, freq, maxerror, esterror;
1165         s32 status, constant, precision, tolerance;
1166         struct compat_timeval time;
1167         s32 tick;
1168         s32 ppsfreq, jitter, shift, stabil;
1169         s32 jitcnt, calcnt, errcnt, stbcnt;
1170         s32  :32; s32  :32; s32  :32; s32  :32;
1171         s32  :32; s32  :32; s32  :32; s32  :32;
1172         s32  :32; s32  :32; s32  :32; s32  :32;
1173 };
1174
1175 extern int do_adjtimex(struct timex *);
1176
1177 asmlinkage int sys32_adjtimex(struct timex32 __user *utp)
1178 {
1179         struct timex txc;
1180         int ret;
1181
1182         memset(&txc, 0, sizeof(struct timex));
1183
1184         if (get_user(txc.modes, &utp->modes) ||
1185            __get_user(txc.offset, &utp->offset) ||
1186            __get_user(txc.freq, &utp->freq) ||
1187            __get_user(txc.maxerror, &utp->maxerror) ||
1188            __get_user(txc.esterror, &utp->esterror) ||
1189            __get_user(txc.status, &utp->status) ||
1190            __get_user(txc.constant, &utp->constant) ||
1191            __get_user(txc.precision, &utp->precision) ||
1192            __get_user(txc.tolerance, &utp->tolerance) ||
1193            __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
1194            __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
1195            __get_user(txc.tick, &utp->tick) ||
1196            __get_user(txc.ppsfreq, &utp->ppsfreq) ||
1197            __get_user(txc.jitter, &utp->jitter) ||
1198            __get_user(txc.shift, &utp->shift) ||
1199            __get_user(txc.stabil, &utp->stabil) ||
1200            __get_user(txc.jitcnt, &utp->jitcnt) ||
1201            __get_user(txc.calcnt, &utp->calcnt) ||
1202            __get_user(txc.errcnt, &utp->errcnt) ||
1203            __get_user(txc.stbcnt, &utp->stbcnt))
1204                 return -EFAULT;
1205
1206         ret = do_adjtimex(&txc);
1207
1208         if (put_user(txc.modes, &utp->modes) ||
1209            __put_user(txc.offset, &utp->offset) ||
1210            __put_user(txc.freq, &utp->freq) ||
1211            __put_user(txc.maxerror, &utp->maxerror) ||
1212            __put_user(txc.esterror, &utp->esterror) ||
1213            __put_user(txc.status, &utp->status) ||
1214            __put_user(txc.constant, &utp->constant) ||
1215            __put_user(txc.precision, &utp->precision) ||
1216            __put_user(txc.tolerance, &utp->tolerance) ||
1217            __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
1218            __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
1219            __put_user(txc.tick, &utp->tick) ||
1220            __put_user(txc.ppsfreq, &utp->ppsfreq) ||
1221            __put_user(txc.jitter, &utp->jitter) ||
1222            __put_user(txc.shift, &utp->shift) ||
1223            __put_user(txc.stabil, &utp->stabil) ||
1224            __put_user(txc.jitcnt, &utp->jitcnt) ||
1225            __put_user(txc.calcnt, &utp->calcnt) ||
1226            __put_user(txc.errcnt, &utp->errcnt) ||
1227            __put_user(txc.stbcnt, &utp->stbcnt))
1228                 ret = -EFAULT;
1229
1230         return ret;
1231 }
1232
1233 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
1234         s32 count)
1235 {
1236         mm_segment_t old_fs = get_fs();
1237         int ret;
1238         off_t of;
1239
1240         if (offset && get_user(of, offset))
1241                 return -EFAULT;
1242
1243         set_fs(KERNEL_DS);
1244         ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count);
1245         set_fs(old_fs);
1246
1247         if (offset && put_user(of, offset))
1248                 return -EFAULT;
1249
1250         return ret;
1251 }
1252
1253 asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
1254                                    size_t count)
1255 {
1256         return sys_readahead(fd, merge_64(a2, a3), count);
1257 }
1258
1259 /* Argument list sizes for sys_socketcall */
1260 #define AL(x) ((x) * sizeof(unsigned int))
1261 static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
1262                                 AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
1263                                 AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
1264 #undef AL
1265
1266 /*
1267  *      System call vectors.
1268  *
1269  *      Argument checking cleaned up. Saved 20% in size.
1270  *  This function doesn't need to set the kernel lock because
1271  *  it is set by the callees.
1272  */
1273
1274 asmlinkage long sys32_socketcall(int call, unsigned int __user *args32)
1275 {
1276         unsigned int a[6];
1277         unsigned int a0,a1;
1278         int err;
1279
1280         extern asmlinkage long sys_socket(int family, int type, int protocol);
1281         extern asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
1282         extern asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen);
1283         extern asmlinkage long sys_listen(int fd, int backlog);
1284         extern asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen);
1285         extern asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
1286         extern asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
1287         extern asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec);
1288         extern asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags);
1289         extern asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags,
1290                                           struct sockaddr __user *addr, int addr_len);
1291         extern asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags);
1292         extern asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags,
1293                                             struct sockaddr __user *addr, int __user *addr_len);
1294         extern asmlinkage long sys_shutdown(int fd, int how);
1295         extern asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen);
1296         extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen);
1297         extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
1298         extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags);
1299
1300
1301         if(call<1||call>SYS_RECVMSG)
1302                 return -EINVAL;
1303
1304         /* copy_from_user should be SMP safe. */
1305         if (copy_from_user(a, args32, socketcall_nargs[call]))
1306                 return -EFAULT;
1307
1308         a0=a[0];
1309         a1=a[1];
1310
1311         switch(call)
1312         {
1313                 case SYS_SOCKET:
1314                         err = sys_socket(a0,a1,a[2]);
1315                         break;
1316                 case SYS_BIND:
1317                         err = sys_bind(a0,(struct sockaddr __user *)A(a1), a[2]);
1318                         break;
1319                 case SYS_CONNECT:
1320                         err = sys_connect(a0, (struct sockaddr __user *)A(a1), a[2]);
1321                         break;
1322                 case SYS_LISTEN:
1323                         err = sys_listen(a0,a1);
1324                         break;
1325                 case SYS_ACCEPT:
1326                         err = sys_accept(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
1327                         break;
1328                 case SYS_GETSOCKNAME:
1329                         err = sys_getsockname(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
1330                         break;
1331                 case SYS_GETPEERNAME:
1332                         err = sys_getpeername(a0, (struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
1333                         break;
1334                 case SYS_SOCKETPAIR:
1335                         err = sys_socketpair(a0,a1, a[2], (int __user *)A(a[3]));
1336                         break;
1337                 case SYS_SEND:
1338                         err = sys_send(a0, (void __user *)A(a1), a[2], a[3]);
1339                         break;
1340                 case SYS_SENDTO:
1341                         err = sys_sendto(a0,(void __user *)A(a1), a[2], a[3],
1342                                          (struct sockaddr __user *)A(a[4]), a[5]);
1343                         break;
1344                 case SYS_RECV:
1345                         err = sys_recv(a0, (void __user *)A(a1), a[2], a[3]);
1346                         break;
1347                 case SYS_RECVFROM:
1348                         err = sys_recvfrom(a0, (void __user *)A(a1), a[2], a[3],
1349                                            (struct sockaddr __user *)A(a[4]), (int __user *)A(a[5]));
1350                         break;
1351                 case SYS_SHUTDOWN:
1352                         err = sys_shutdown(a0,a1);
1353                         break;
1354                 case SYS_SETSOCKOPT:
1355                         err = sys_setsockopt(a0, a1, a[2], (char __user *)A(a[3]), a[4]);
1356                         break;
1357                 case SYS_GETSOCKOPT:
1358                         err = sys_getsockopt(a0, a1, a[2], (char __user *)A(a[3]), (int __user *)A(a[4]));
1359                         break;
1360                 case SYS_SENDMSG:
1361                         err = sys_sendmsg(a0, (struct msghdr __user *) A(a1), a[2]);
1362                         break;
1363                 case SYS_RECVMSG:
1364                         err = sys_recvmsg(a0, (struct msghdr __user *) A(a1), a[2]);
1365                         break;
1366                 default:
1367                         err = -EINVAL;
1368                         break;
1369         }
1370         return err;
1371 }
1372
1373 struct sigevent32 {
1374         u32 sigev_value;
1375         u32 sigev_signo;
1376         u32 sigev_notify;
1377         u32 payload[(64 / 4) - 3];
1378 };
1379
1380 extern asmlinkage long
1381 sys_timer_create(clockid_t which_clock,
1382                  struct sigevent __user *timer_event_spec,
1383                  timer_t __user * created_timer_id);
1384
1385 long
1386 sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id)
1387 {
1388         struct sigevent __user *p = NULL;
1389         if (se32) {
1390                 struct sigevent se;
1391                 p = compat_alloc_user_space(sizeof(struct sigevent));
1392                 memset(&se, 0, sizeof(struct sigevent));
1393                 if (get_user(se.sigev_value.sival_int,  &se32->sigev_value) ||
1394                     __get_user(se.sigev_signo, &se32->sigev_signo) ||
1395                     __get_user(se.sigev_notify, &se32->sigev_notify) ||
1396                     __copy_from_user(&se._sigev_un._pad, &se32->payload,
1397                                      sizeof(se32->payload)) ||
1398                     copy_to_user(p, &se, sizeof(se)))
1399                         return -EFAULT;
1400         }
1401         return sys_timer_create(clock, p, timer_id);
1402 }
1403
1404 save_static_function(sys32_clone);
1405 __attribute_used__ noinline static int
1406 _sys32_clone(nabi_no_regargs struct pt_regs regs)
1407 {
1408         unsigned long clone_flags;
1409         unsigned long newsp;
1410         int __user *parent_tidptr, *child_tidptr;
1411
1412         clone_flags = regs.regs[4];
1413         newsp = regs.regs[5];
1414         if (!newsp)
1415                 newsp = regs.regs[29];
1416         parent_tidptr = (int __user *) regs.regs[6];
1417
1418         /* Use __dummy4 instead of getting it off the stack, so that
1419            syscall() works.  */
1420         child_tidptr = (int __user *) __dummy4;
1421         return do_fork(clone_flags, newsp, &regs, 0,
1422                        parent_tidptr, child_tidptr);
1423 }
1424
1425 extern asmlinkage void sys_set_thread_area(u32 addr);
1426 asmlinkage void sys32_set_thread_area(u32 addr)
1427 {
1428         sys_set_thread_area(AA(addr));
1429 }