Merge with Linus' kernel.
[linux-2.6] / 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 *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 (!(flags & MAP_ANONYMOUS)) {
110                 error = -EBADF;
111                 file = fget(fd);
112                 if (!file)
113                         goto out;
114         }
115         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
116
117         down_write(&current->mm->mmap_sem);
118         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
119         up_write(&current->mm->mmap_sem);
120         if (file)
121                 fput(file);
122
123 out:
124         return error;
125 }
126
127
128 asmlinkage int sys_truncate64(const char *path, unsigned int high,
129                               unsigned int low)
130 {
131         if ((int)high < 0)
132                 return -EINVAL;
133         return sys_truncate(path, ((long) high << 32) | low);
134 }
135
136 asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high,
137                                unsigned int low)
138 {
139         if ((int)high < 0)
140                 return -EINVAL;
141         return sys_ftruncate(fd, ((long) high << 32) | low);
142 }
143
144 /*
145  * sys_execve() executes a new program.
146  */
147 asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)
148 {
149         int error;
150         char * filename;
151
152         filename = getname(compat_ptr(regs.regs[4]));
153         error = PTR_ERR(filename);
154         if (IS_ERR(filename))
155                 goto out;
156         error = compat_do_execve(filename, compat_ptr(regs.regs[5]),
157                                  compat_ptr(regs.regs[6]), &regs);
158         putname(filename);
159
160 out:
161         return error;
162 }
163
164 struct dirent32 {
165         unsigned int    d_ino;
166         unsigned int    d_off;
167         unsigned short  d_reclen;
168         char            d_name[NAME_MAX + 1];
169 };
170
171 static void
172 xlate_dirent(void *dirent64, void *dirent32, long n)
173 {
174         long off;
175         struct dirent *dirp;
176         struct dirent32 *dirp32;
177
178         off = 0;
179         while (off < n) {
180                 dirp = (struct dirent *)(dirent64 + off);
181                 dirp32 = (struct dirent32 *)(dirent32 + off);
182                 off += dirp->d_reclen;
183                 dirp32->d_ino = dirp->d_ino;
184                 dirp32->d_off = (unsigned int)dirp->d_off;
185                 dirp32->d_reclen = dirp->d_reclen;
186                 strncpy(dirp32->d_name, dirp->d_name, dirp->d_reclen - ((3 * 4) + 2));
187         }
188         return;
189 }
190
191 asmlinkage long
192 sys32_getdents(unsigned int fd, void * dirent32, unsigned int count)
193 {
194         long n;
195         void *dirent64;
196
197         dirent64 = (void *)((unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1));
198         if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0)
199                 return(n);
200         xlate_dirent(dirent64, dirent32, n);
201         return(n);
202 }
203
204 asmlinkage int old_readdir(unsigned int fd, void * dirent, unsigned int count);
205
206 asmlinkage int
207 sys32_readdir(unsigned int fd, void * dirent32, unsigned int count)
208 {
209         int n;
210         struct dirent dirent64;
211
212         if ((n = old_readdir(fd, &dirent64, count)) < 0)
213                 return(n);
214         xlate_dirent(&dirent64, dirent32, dirent64.d_reclen);
215         return(n);
216 }
217
218 asmlinkage int
219 sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options)
220 {
221         return compat_sys_wait4(pid, stat_addr, options, NULL);
222 }
223
224 asmlinkage long
225 sysn32_waitid(int which, compat_pid_t pid,
226               siginfo_t __user *uinfo, int options,
227               struct compat_rusage __user *uru)
228 {
229         struct rusage ru;
230         long ret;
231         mm_segment_t old_fs = get_fs();
232
233         set_fs (KERNEL_DS);
234         ret = sys_waitid(which, pid, uinfo, options,
235                          uru ? (struct rusage __user *) &ru : NULL);
236         set_fs (old_fs);
237
238         if (ret < 0 || uinfo->si_signo == 0)
239                 return ret;
240
241         if (uru)
242                 ret = put_compat_rusage(&ru, uru);
243         return ret;
244 }
245
246 struct sysinfo32 {
247         s32 uptime;
248         u32 loads[3];
249         u32 totalram;
250         u32 freeram;
251         u32 sharedram;
252         u32 bufferram;
253         u32 totalswap;
254         u32 freeswap;
255         u16 procs;
256         u32 totalhigh;
257         u32 freehigh;
258         u32 mem_unit;
259         char _f[8];
260 };
261
262 asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
263 {
264         struct sysinfo s;
265         int ret, err;
266         mm_segment_t old_fs = get_fs ();
267
268         set_fs (KERNEL_DS);
269         ret = sys_sysinfo(&s);
270         set_fs (old_fs);
271         err = put_user (s.uptime, &info->uptime);
272         err |= __put_user (s.loads[0], &info->loads[0]);
273         err |= __put_user (s.loads[1], &info->loads[1]);
274         err |= __put_user (s.loads[2], &info->loads[2]);
275         err |= __put_user (s.totalram, &info->totalram);
276         err |= __put_user (s.freeram, &info->freeram);
277         err |= __put_user (s.sharedram, &info->sharedram);
278         err |= __put_user (s.bufferram, &info->bufferram);
279         err |= __put_user (s.totalswap, &info->totalswap);
280         err |= __put_user (s.freeswap, &info->freeswap);
281         err |= __put_user (s.procs, &info->procs);
282         err |= __put_user (s.totalhigh, &info->totalhigh);
283         err |= __put_user (s.freehigh, &info->freehigh);
284         err |= __put_user (s.mem_unit, &info->mem_unit);
285         if (err)
286                 return -EFAULT;
287         return ret;
288 }
289
290 #define RLIM_INFINITY32 0x7fffffff
291 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
292
293 struct rlimit32 {
294         int     rlim_cur;
295         int     rlim_max;
296 };
297
298 #ifdef __MIPSEB__
299 asmlinkage long sys32_truncate64(const char * path, unsigned long __dummy,
300         int length_hi, int length_lo)
301 #endif
302 #ifdef __MIPSEL__
303 asmlinkage long sys32_truncate64(const char * path, unsigned long __dummy,
304         int length_lo, int length_hi)
305 #endif
306 {
307         loff_t length;
308
309         length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo;
310
311         return sys_truncate(path, length);
312 }
313
314 #ifdef __MIPSEB__
315 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
316         int length_hi, int length_lo)
317 #endif
318 #ifdef __MIPSEL__
319 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
320         int length_lo, int length_hi)
321 #endif
322 {
323         loff_t length;
324
325         length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo;
326
327         return sys_ftruncate(fd, length);
328 }
329
330 static inline long
331 get_tv32(struct timeval *o, struct compat_timeval *i)
332 {
333         return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
334                 (__get_user(o->tv_sec, &i->tv_sec) |
335                  __get_user(o->tv_usec, &i->tv_usec)));
336 }
337
338 static inline long
339 put_tv32(struct compat_timeval *o, struct timeval *i)
340 {
341         return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
342                 (__put_user(i->tv_sec, &o->tv_sec) |
343                  __put_user(i->tv_usec, &o->tv_usec)));
344 }
345
346 extern struct timezone sys_tz;
347
348 asmlinkage int
349 sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
350 {
351         if (tv) {
352                 struct timeval ktv;
353                 do_gettimeofday(&ktv);
354                 if (put_tv32(tv, &ktv))
355                         return -EFAULT;
356         }
357         if (tz) {
358                 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
359                         return -EFAULT;
360         }
361         return 0;
362 }
363
364 static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
365 {
366         long usec;
367
368         if (!access_ok(VERIFY_READ, i, sizeof(*i)))
369                 return -EFAULT;
370         if (__get_user(o->tv_sec, &i->tv_sec))
371                 return -EFAULT;
372         if (__get_user(usec, &i->tv_usec))
373                 return -EFAULT;
374         o->tv_nsec = usec * 1000;
375                 return 0;
376 }
377
378 asmlinkage int
379 sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
380 {
381         struct timespec kts;
382         struct timezone ktz;
383
384         if (tv) {
385                 if (get_ts32(&kts, tv))
386                         return -EFAULT;
387         }
388         if (tz) {
389                 if (copy_from_user(&ktz, tz, sizeof(ktz)))
390                         return -EFAULT;
391         }
392
393         return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
394 }
395
396 asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
397                             unsigned int offset_low, loff_t * result,
398                             unsigned int origin)
399 {
400         return sys_llseek(fd, offset_high, offset_low, result, origin);
401 }
402
403 /* From the Single Unix Spec: pread & pwrite act like lseek to pos + op +
404    lseek back to original location.  They fail just like lseek does on
405    non-seekable files.  */
406
407 asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf,
408                                size_t count, u32 unused, u64 a4, u64 a5)
409 {
410         ssize_t ret;
411         struct file * file;
412         ssize_t (*read)(struct file *, char *, size_t, loff_t *);
413         loff_t pos;
414
415         ret = -EBADF;
416         file = fget(fd);
417         if (!file)
418                 goto bad_file;
419         if (!(file->f_mode & FMODE_READ))
420                 goto out;
421         pos = merge_64(a4, a5);
422         ret = rw_verify_area(READ, file, &pos, count);
423         if (ret < 0)
424                 goto out;
425         ret = -EINVAL;
426         if (!file->f_op || !(read = file->f_op->read))
427                 goto out;
428         if (pos < 0)
429                 goto out;
430         ret = -ESPIPE;
431         if (!(file->f_mode & FMODE_PREAD))
432                 goto out;
433         ret = read(file, buf, count, &pos);
434         if (ret > 0)
435                 dnotify_parent(file->f_dentry, DN_ACCESS);
436 out:
437         fput(file);
438 bad_file:
439         return ret;
440 }
441
442 asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf,
443                                 size_t count, u32 unused, u64 a4, u64 a5)
444 {
445         ssize_t ret;
446         struct file * file;
447         ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
448         loff_t pos;
449
450         ret = -EBADF;
451         file = fget(fd);
452         if (!file)
453                 goto bad_file;
454         if (!(file->f_mode & FMODE_WRITE))
455                 goto out;
456         pos = merge_64(a4, a5);
457         ret = rw_verify_area(WRITE, file, &pos, count);
458         if (ret < 0)
459                 goto out;
460         ret = -EINVAL;
461         if (!file->f_op || !(write = file->f_op->write))
462                 goto out;
463         if (pos < 0)
464                 goto out;
465
466         ret = -ESPIPE;
467         if (!(file->f_mode & FMODE_PWRITE))
468                 goto out;
469
470         ret = write(file, buf, count, &pos);
471         if (ret > 0)
472                 dnotify_parent(file->f_dentry, DN_MODIFY);
473 out:
474         fput(file);
475 bad_file:
476         return ret;
477 }
478
479 asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
480         struct compat_timespec *interval)
481 {
482         struct timespec t;
483         int ret;
484         mm_segment_t old_fs = get_fs ();
485
486         set_fs (KERNEL_DS);
487         ret = sys_sched_rr_get_interval(pid, &t);
488         set_fs (old_fs);
489         if (put_user (t.tv_sec, &interval->tv_sec) ||
490             __put_user (t.tv_nsec, &interval->tv_nsec))
491                 return -EFAULT;
492         return ret;
493 }
494
495 struct msgbuf32 { s32 mtype; char mtext[1]; };
496
497 struct ipc_perm32
498 {
499         key_t             key;
500         __compat_uid_t  uid;
501         __compat_gid_t  gid;
502         __compat_uid_t  cuid;
503         __compat_gid_t  cgid;
504         compat_mode_t   mode;
505         unsigned short  seq;
506 };
507
508 struct ipc64_perm32 {
509         key_t key;
510         __compat_uid_t uid;
511         __compat_gid_t gid;
512         __compat_uid_t cuid;
513         __compat_gid_t cgid;
514         compat_mode_t   mode;
515         unsigned short  seq;
516         unsigned short __pad1;
517         unsigned int __unused1;
518         unsigned int __unused2;
519 };
520
521 struct semid_ds32 {
522         struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
523         compat_time_t   sem_otime;              /* last semop time */
524         compat_time_t   sem_ctime;              /* last change time */
525         u32 sem_base;              /* ptr to first semaphore in array */
526         u32 sem_pending;          /* pending operations to be processed */
527         u32 sem_pending_last;    /* last pending operation */
528         u32 undo;                  /* undo requests on this array */
529         unsigned short  sem_nsems;              /* no. of semaphores in array */
530 };
531
532 struct semid64_ds32 {
533         struct ipc64_perm32     sem_perm;
534         compat_time_t   sem_otime;
535         compat_time_t   sem_ctime;
536         unsigned int            sem_nsems;
537         unsigned int            __unused1;
538         unsigned int            __unused2;
539 };
540
541 struct msqid_ds32
542 {
543         struct ipc_perm32 msg_perm;
544         u32 msg_first;
545         u32 msg_last;
546         compat_time_t   msg_stime;
547         compat_time_t   msg_rtime;
548         compat_time_t   msg_ctime;
549         u32 wwait;
550         u32 rwait;
551         unsigned short msg_cbytes;
552         unsigned short msg_qnum;
553         unsigned short msg_qbytes;
554         compat_ipc_pid_t msg_lspid;
555         compat_ipc_pid_t msg_lrpid;
556 };
557
558 struct msqid64_ds32 {
559         struct ipc64_perm32 msg_perm;
560         compat_time_t msg_stime;
561         unsigned int __unused1;
562         compat_time_t msg_rtime;
563         unsigned int __unused2;
564         compat_time_t msg_ctime;
565         unsigned int __unused3;
566         unsigned int msg_cbytes;
567         unsigned int msg_qnum;
568         unsigned int msg_qbytes;
569         compat_pid_t msg_lspid;
570         compat_pid_t msg_lrpid;
571         unsigned int __unused4;
572         unsigned int __unused5;
573 };
574
575 struct shmid_ds32 {
576         struct ipc_perm32       shm_perm;
577         int                     shm_segsz;
578         compat_time_t           shm_atime;
579         compat_time_t           shm_dtime;
580         compat_time_t           shm_ctime;
581         compat_ipc_pid_t    shm_cpid;
582         compat_ipc_pid_t    shm_lpid;
583         unsigned short          shm_nattch;
584 };
585
586 struct shmid64_ds32 {
587         struct ipc64_perm32     shm_perm;
588         compat_size_t           shm_segsz;
589         compat_time_t           shm_atime;
590         compat_time_t           shm_dtime;
591         compat_time_t shm_ctime;
592         compat_pid_t shm_cpid;
593         compat_pid_t shm_lpid;
594         unsigned int shm_nattch;
595         unsigned int __unused1;
596         unsigned int __unused2;
597 };
598
599 struct ipc_kludge32 {
600         u32 msgp;
601         s32 msgtyp;
602 };
603
604 static int
605 do_sys32_semctl(int first, int second, int third, void *uptr)
606 {
607         union semun fourth;
608         u32 pad;
609         int err, err2;
610         struct semid64_ds s;
611         mm_segment_t old_fs;
612
613         if (!uptr)
614                 return -EINVAL;
615         err = -EFAULT;
616         if (get_user (pad, (u32 *)uptr))
617                 return err;
618         if ((third & ~IPC_64) == SETVAL)
619                 fourth.val = (int)pad;
620         else
621                 fourth.__pad = (void *)A(pad);
622         switch (third & ~IPC_64) {
623         case IPC_INFO:
624         case IPC_RMID:
625         case IPC_SET:
626         case SEM_INFO:
627         case GETVAL:
628         case GETPID:
629         case GETNCNT:
630         case GETZCNT:
631         case GETALL:
632         case SETVAL:
633         case SETALL:
634                 err = sys_semctl (first, second, third, fourth);
635                 break;
636
637         case IPC_STAT:
638         case SEM_STAT:
639                 fourth.__pad = &s;
640                 old_fs = get_fs();
641                 set_fs(KERNEL_DS);
642                 err = sys_semctl(first, second, third | IPC_64, fourth);
643                 set_fs(old_fs);
644
645                 if (third & IPC_64) {
646                         struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad);
647
648                         if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
649                                 err = -EFAULT;
650                                 break;
651                         }
652                         err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key);
653                         err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid);
654                         err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid);
655                         err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid);
656                         err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid);
657                         err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode);
658                         err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq);
659                         err2 |= __put_user(s.sem_otime, &usp64->sem_otime);
660                         err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime);
661                         err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems);
662                 } else {
663                         struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad);
664
665                         if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
666                                 err = -EFAULT;
667                                 break;
668                         }
669                         err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key);
670                         err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid);
671                         err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid);
672                         err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid);
673                         err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid);
674                         err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode);
675                         err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq);
676                         err2 |= __put_user(s.sem_otime, &usp32->sem_otime);
677                         err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime);
678                         err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems);
679                 }
680                 if (err2)
681                         err = -EFAULT;
682                 break;
683
684         default:
685                 err = - EINVAL;
686                 break;
687         }
688
689         return err;
690 }
691
692 static int
693 do_sys32_msgsnd (int first, int second, int third, void *uptr)
694 {
695         struct msgbuf32 *up = (struct msgbuf32 *)uptr;
696         struct msgbuf *p;
697         mm_segment_t old_fs;
698         int err;
699
700         if (second < 0)
701                 return -EINVAL;
702         p = kmalloc (second + sizeof (struct msgbuf)
703                                     + 4, GFP_USER);
704         if (!p)
705                 return -ENOMEM;
706         err = get_user (p->mtype, &up->mtype);
707         if (err)
708                 goto out;
709         err |= __copy_from_user (p->mtext, &up->mtext, second);
710         if (err)
711                 goto out;
712         old_fs = get_fs ();
713         set_fs (KERNEL_DS);
714         err = sys_msgsnd (first, p, second, third);
715         set_fs (old_fs);
716 out:
717         kfree (p);
718
719         return err;
720 }
721
722 static int
723 do_sys32_msgrcv (int first, int second, int msgtyp, int third,
724                  int version, void *uptr)
725 {
726         struct msgbuf32 *up;
727         struct msgbuf *p;
728         mm_segment_t old_fs;
729         int err;
730
731         if (!version) {
732                 struct ipc_kludge32 *uipck = (struct ipc_kludge32 *)uptr;
733                 struct ipc_kludge32 ipck;
734
735                 err = -EINVAL;
736                 if (!uptr)
737                         goto out;
738                 err = -EFAULT;
739                 if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge32)))
740                         goto out;
741                 uptr = (void *)AA(ipck.msgp);
742                 msgtyp = ipck.msgtyp;
743         }
744
745         if (second < 0)
746                 return -EINVAL;
747         err = -ENOMEM;
748         p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
749         if (!p)
750                 goto out;
751         old_fs = get_fs ();
752         set_fs (KERNEL_DS);
753         err = sys_msgrcv (first, p, second + 4, msgtyp, third);
754         set_fs (old_fs);
755         if (err < 0)
756                 goto free_then_out;
757         up = (struct msgbuf32 *)uptr;
758         if (put_user (p->mtype, &up->mtype) ||
759             __copy_to_user (&up->mtext, p->mtext, err))
760                 err = -EFAULT;
761 free_then_out:
762         kfree (p);
763 out:
764         return err;
765 }
766
767 static int
768 do_sys32_msgctl (int first, int second, void *uptr)
769 {
770         int err = -EINVAL, err2;
771         struct msqid64_ds m;
772         struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr;
773         struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr;
774         mm_segment_t old_fs;
775
776         switch (second & ~IPC_64) {
777         case IPC_INFO:
778         case IPC_RMID:
779         case MSG_INFO:
780                 err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
781                 break;
782
783         case IPC_SET:
784                 if (second & IPC_64) {
785                         if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) {
786                                 err = -EFAULT;
787                                 break;
788                         }
789                         err = __get_user(m.msg_perm.uid, &up64->msg_perm.uid);
790                         err |= __get_user(m.msg_perm.gid, &up64->msg_perm.gid);
791                         err |= __get_user(m.msg_perm.mode, &up64->msg_perm.mode);
792                         err |= __get_user(m.msg_qbytes, &up64->msg_qbytes);
793                 } else {
794                         if (!access_ok(VERIFY_READ, up32, sizeof(*up32))) {
795                                 err = -EFAULT;
796                                 break;
797                         }
798                         err = __get_user(m.msg_perm.uid, &up32->msg_perm.uid);
799                         err |= __get_user(m.msg_perm.gid, &up32->msg_perm.gid);
800                         err |= __get_user(m.msg_perm.mode, &up32->msg_perm.mode);
801                         err |= __get_user(m.msg_qbytes, &up32->msg_qbytes);
802                 }
803                 if (err)
804                         break;
805                 old_fs = get_fs();
806                 set_fs(KERNEL_DS);
807                 err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m);
808                 set_fs(old_fs);
809                 break;
810
811         case IPC_STAT:
812         case MSG_STAT:
813                 old_fs = get_fs();
814                 set_fs(KERNEL_DS);
815                 err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m);
816                 set_fs(old_fs);
817                 if (second & IPC_64) {
818                         if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
819                                 err = -EFAULT;
820                                 break;
821                         }
822                         err2 = __put_user(m.msg_perm.key, &up64->msg_perm.key);
823                         err2 |= __put_user(m.msg_perm.uid, &up64->msg_perm.uid);
824                         err2 |= __put_user(m.msg_perm.gid, &up64->msg_perm.gid);
825                         err2 |= __put_user(m.msg_perm.cuid, &up64->msg_perm.cuid);
826                         err2 |= __put_user(m.msg_perm.cgid, &up64->msg_perm.cgid);
827                         err2 |= __put_user(m.msg_perm.mode, &up64->msg_perm.mode);
828                         err2 |= __put_user(m.msg_perm.seq, &up64->msg_perm.seq);
829                         err2 |= __put_user(m.msg_stime, &up64->msg_stime);
830                         err2 |= __put_user(m.msg_rtime, &up64->msg_rtime);
831                         err2 |= __put_user(m.msg_ctime, &up64->msg_ctime);
832                         err2 |= __put_user(m.msg_cbytes, &up64->msg_cbytes);
833                         err2 |= __put_user(m.msg_qnum, &up64->msg_qnum);
834                         err2 |= __put_user(m.msg_qbytes, &up64->msg_qbytes);
835                         err2 |= __put_user(m.msg_lspid, &up64->msg_lspid);
836                         err2 |= __put_user(m.msg_lrpid, &up64->msg_lrpid);
837                         if (err2)
838                                 err = -EFAULT;
839                 } else {
840                         if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
841                                 err = -EFAULT;
842                                 break;
843                         }
844                         err2 = __put_user(m.msg_perm.key, &up32->msg_perm.key);
845                         err2 |= __put_user(m.msg_perm.uid, &up32->msg_perm.uid);
846                         err2 |= __put_user(m.msg_perm.gid, &up32->msg_perm.gid);
847                         err2 |= __put_user(m.msg_perm.cuid, &up32->msg_perm.cuid);
848                         err2 |= __put_user(m.msg_perm.cgid, &up32->msg_perm.cgid);
849                         err2 |= __put_user(m.msg_perm.mode, &up32->msg_perm.mode);
850                         err2 |= __put_user(m.msg_perm.seq, &up32->msg_perm.seq);
851                         err2 |= __put_user(m.msg_stime, &up32->msg_stime);
852                         err2 |= __put_user(m.msg_rtime, &up32->msg_rtime);
853                         err2 |= __put_user(m.msg_ctime, &up32->msg_ctime);
854                         err2 |= __put_user(m.msg_cbytes, &up32->msg_cbytes);
855                         err2 |= __put_user(m.msg_qnum, &up32->msg_qnum);
856                         err2 |= __put_user(m.msg_qbytes, &up32->msg_qbytes);
857                         err2 |= __put_user(m.msg_lspid, &up32->msg_lspid);
858                         err2 |= __put_user(m.msg_lrpid, &up32->msg_lrpid);
859                         if (err2)
860                                 err = -EFAULT;
861                 }
862                 break;
863         }
864
865         return err;
866 }
867
868 static int
869 do_sys32_shmat (int first, int second, int third, int version, void *uptr)
870 {
871         unsigned long raddr;
872         u32 *uaddr = (u32 *)A((u32)third);
873         int err = -EINVAL;
874
875         if (version == 1)
876                 return err;
877         err = do_shmat (first, uptr, second, &raddr);
878         if (err)
879                 return err;
880         err = put_user (raddr, uaddr);
881         return err;
882 }
883
884 struct shm_info32 {
885         int used_ids;
886         u32 shm_tot, shm_rss, shm_swp;
887         u32 swap_attempts, swap_successes;
888 };
889
890 static int
891 do_sys32_shmctl (int first, int second, void *uptr)
892 {
893         struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
894         struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
895         struct shm_info32 *uip = (struct shm_info32 *)uptr;
896         int err = -EFAULT, err2;
897         struct shmid64_ds s64;
898         mm_segment_t old_fs;
899         struct shm_info si;
900         struct shmid_ds s;
901
902         switch (second & ~IPC_64) {
903         case IPC_INFO:
904                 second = IPC_INFO; /* So that we don't have to translate it */
905         case IPC_RMID:
906         case SHM_LOCK:
907         case SHM_UNLOCK:
908                 err = sys_shmctl(first, second, (struct shmid_ds *)uptr);
909                 break;
910         case IPC_SET:
911                 if (second & IPC_64) {
912                         err = get_user(s.shm_perm.uid, &up64->shm_perm.uid);
913                         err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid);
914                         err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode);
915                 } else {
916                         err = get_user(s.shm_perm.uid, &up32->shm_perm.uid);
917                         err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid);
918                         err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode);
919                 }
920                 if (err)
921                         break;
922                 old_fs = get_fs();
923                 set_fs(KERNEL_DS);
924                 err = sys_shmctl(first, second & ~IPC_64, &s);
925                 set_fs(old_fs);
926                 break;
927
928         case IPC_STAT:
929         case SHM_STAT:
930                 old_fs = get_fs();
931                 set_fs(KERNEL_DS);
932                 err = sys_shmctl(first, second | IPC_64, (void *) &s64);
933                 set_fs(old_fs);
934                 if (err < 0)
935                         break;
936                 if (second & IPC_64) {
937                         if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
938                                 err = -EFAULT;
939                                 break;
940                         }
941                         err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
942                         err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
943                         err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
944                         err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
945                         err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
946                         err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
947                         err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
948                         err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
949                         err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
950                         err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
951                         err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
952                         err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
953                         err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
954                         err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
955                 } else {
956                         if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
957                                 err = -EFAULT;
958                                 break;
959                         }
960                         err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
961                         err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
962                         err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
963                         err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
964                         err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
965                         err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
966                         err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
967                         err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
968                         err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
969                         err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
970                         err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
971                         err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
972                         err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
973                         err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
974                 }
975                 if (err2)
976                         err = -EFAULT;
977                 break;
978
979         case SHM_INFO:
980                 old_fs = get_fs();
981                 set_fs(KERNEL_DS);
982                 err = sys_shmctl(first, second, (void *)&si);
983                 set_fs(old_fs);
984                 if (err < 0)
985                         break;
986                 err2 = put_user(si.used_ids, &uip->used_ids);
987                 err2 |= __put_user(si.shm_tot, &uip->shm_tot);
988                 err2 |= __put_user(si.shm_rss, &uip->shm_rss);
989                 err2 |= __put_user(si.shm_swp, &uip->shm_swp);
990                 err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
991                 err2 |= __put_user (si.swap_successes, &uip->swap_successes);
992                 if (err2)
993                         err = -EFAULT;
994                 break;
995
996         default:
997                 err = -EINVAL;
998                 break;
999         }
1000
1001         return err;
1002 }
1003
1004 static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems,
1005                             const struct compat_timespec *timeout32)
1006 {
1007         struct compat_timespec t32;
1008         struct timespec *t64 = compat_alloc_user_space(sizeof(*t64));
1009
1010         if (copy_from_user(&t32, timeout32, sizeof(t32)))
1011                 return -EFAULT;
1012
1013         if (put_user(t32.tv_sec, &t64->tv_sec) ||
1014             put_user(t32.tv_nsec, &t64->tv_nsec))
1015                 return -EFAULT;
1016
1017         return sys_semtimedop(semid, tsems, nsems, t64);
1018 }
1019
1020 asmlinkage long
1021 sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
1022 {
1023         int version, err;
1024
1025         version = call >> 16; /* hack for backward compatibility */
1026         call &= 0xffff;
1027
1028         switch (call) {
1029         case SEMOP:
1030                 /* struct sembuf is the same on 32 and 64bit :)) */
1031                 err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second,
1032                                       NULL);
1033                 break;
1034         case SEMTIMEDOP:
1035                 err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second,
1036                                       (const struct compat_timespec __user *)AA(fifth));
1037                 break;
1038         case SEMGET:
1039                 err = sys_semget (first, second, third);
1040                 break;
1041         case SEMCTL:
1042                 err = do_sys32_semctl (first, second, third,
1043                                        (void *)AA(ptr));
1044                 break;
1045
1046         case MSGSND:
1047                 err = do_sys32_msgsnd (first, second, third,
1048                                        (void *)AA(ptr));
1049                 break;
1050         case MSGRCV:
1051                 err = do_sys32_msgrcv (first, second, fifth, third,
1052                                        version, (void *)AA(ptr));
1053                 break;
1054         case MSGGET:
1055                 err = sys_msgget ((key_t) first, second);
1056                 break;
1057         case MSGCTL:
1058                 err = do_sys32_msgctl (first, second, (void *)AA(ptr));
1059                 break;
1060
1061         case SHMAT:
1062                 err = do_sys32_shmat (first, second, third,
1063                                       version, (void *)AA(ptr));
1064                 break;
1065         case SHMDT:
1066                 err = sys_shmdt ((char *)A(ptr));
1067                 break;
1068         case SHMGET:
1069                 err = sys_shmget (first, (unsigned)second, third);
1070                 break;
1071         case SHMCTL:
1072                 err = do_sys32_shmctl (first, second, (void *)AA(ptr));
1073                 break;
1074         default:
1075                 err = -EINVAL;
1076                 break;
1077         }
1078
1079         return err;
1080 }
1081
1082 asmlinkage long sys32_shmat(int shmid, char __user *shmaddr,
1083                           int shmflg, int32_t *addr)
1084 {
1085         unsigned long raddr;
1086         int err;
1087
1088         err = do_shmat(shmid, shmaddr, shmflg, &raddr);
1089         if (err)
1090                 return err;
1091
1092         return put_user(raddr, addr);
1093 }
1094
1095 struct sysctl_args32
1096 {
1097         compat_caddr_t name;
1098         int nlen;
1099         compat_caddr_t oldval;
1100         compat_caddr_t oldlenp;
1101         compat_caddr_t newval;
1102         compat_size_t newlen;
1103         unsigned int __unused[4];
1104 };
1105
1106 #ifdef CONFIG_SYSCTL
1107
1108 asmlinkage long sys32_sysctl(struct sysctl_args32 *args)
1109 {
1110         struct sysctl_args32 tmp;
1111         int error;
1112         size_t oldlen, *oldlenp = NULL;
1113         unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
1114
1115         if (copy_from_user(&tmp, args, sizeof(tmp)))
1116                 return -EFAULT;
1117
1118         if (tmp.oldval && tmp.oldlenp) {
1119                 /* Duh, this is ugly and might not work if sysctl_args
1120                    is in read-only memory, but do_sysctl does indirectly
1121                    a lot of uaccess in both directions and we'd have to
1122                    basically copy the whole sysctl.c here, and
1123                    glibc's __sysctl uses rw memory for the structure
1124                    anyway.  */
1125                 if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
1126                     put_user(oldlen, (size_t *)addr))
1127                         return -EFAULT;
1128                 oldlenp = (size_t *)addr;
1129         }
1130
1131         lock_kernel();
1132         error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
1133                           oldlenp, (void *)A(tmp.newval), tmp.newlen);
1134         unlock_kernel();
1135         if (oldlenp) {
1136                 if (!error) {
1137                         if (get_user(oldlen, (size_t *)addr) ||
1138                             put_user(oldlen, (u32 *)A(tmp.oldlenp)))
1139                                 error = -EFAULT;
1140                 }
1141                 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
1142         }
1143         return error;
1144 }
1145
1146 #endif /* CONFIG_SYSCTL */
1147
1148 asmlinkage long sys32_newuname(struct new_utsname * name)
1149 {
1150         int ret = 0;
1151
1152         down_read(&uts_sem);
1153         if (copy_to_user(name,&system_utsname,sizeof *name))
1154                 ret = -EFAULT;
1155         up_read(&uts_sem);
1156
1157         if (current->personality == PER_LINUX32 && !ret)
1158                 if (copy_to_user(name->machine, "mips\0\0\0", 8))
1159                         ret = -EFAULT;
1160
1161         return ret;
1162 }
1163
1164 asmlinkage int sys32_personality(unsigned long personality)
1165 {
1166         int ret;
1167         if (current->personality == PER_LINUX32 && personality == PER_LINUX)
1168                 personality = PER_LINUX32;
1169         ret = sys_personality(personality);
1170         if (ret == PER_LINUX32)
1171                 ret = PER_LINUX;
1172         return ret;
1173 }
1174
1175 /* ustat compatibility */
1176 struct ustat32 {
1177         compat_daddr_t  f_tfree;
1178         compat_ino_t    f_tinode;
1179         char            f_fname[6];
1180         char            f_fpack[6];
1181 };
1182
1183 extern asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf);
1184
1185 asmlinkage int sys32_ustat(dev_t dev, struct ustat32 * ubuf32)
1186 {
1187         int err;
1188         struct ustat tmp;
1189         struct ustat32 tmp32;
1190         mm_segment_t old_fs = get_fs();
1191
1192         set_fs(KERNEL_DS);
1193         err = sys_ustat(dev, &tmp);
1194         set_fs (old_fs);
1195
1196         if (err)
1197                 goto out;
1198
1199         memset(&tmp32,0,sizeof(struct ustat32));
1200         tmp32.f_tfree = tmp.f_tfree;
1201         tmp32.f_tinode = tmp.f_tinode;
1202
1203         err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0;
1204
1205 out:
1206         return err;
1207 }
1208
1209 /* Handle adjtimex compatibility. */
1210
1211 struct timex32 {
1212         u32 modes;
1213         s32 offset, freq, maxerror, esterror;
1214         s32 status, constant, precision, tolerance;
1215         struct compat_timeval time;
1216         s32 tick;
1217         s32 ppsfreq, jitter, shift, stabil;
1218         s32 jitcnt, calcnt, errcnt, stbcnt;
1219         s32  :32; s32  :32; s32  :32; s32  :32;
1220         s32  :32; s32  :32; s32  :32; s32  :32;
1221         s32  :32; s32  :32; s32  :32; s32  :32;
1222 };
1223
1224 extern int do_adjtimex(struct timex *);
1225
1226 asmlinkage int sys32_adjtimex(struct timex32 *utp)
1227 {
1228         struct timex txc;
1229         int ret;
1230
1231         memset(&txc, 0, sizeof(struct timex));
1232
1233         if (get_user(txc.modes, &utp->modes) ||
1234            __get_user(txc.offset, &utp->offset) ||
1235            __get_user(txc.freq, &utp->freq) ||
1236            __get_user(txc.maxerror, &utp->maxerror) ||
1237            __get_user(txc.esterror, &utp->esterror) ||
1238            __get_user(txc.status, &utp->status) ||
1239            __get_user(txc.constant, &utp->constant) ||
1240            __get_user(txc.precision, &utp->precision) ||
1241            __get_user(txc.tolerance, &utp->tolerance) ||
1242            __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
1243            __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
1244            __get_user(txc.tick, &utp->tick) ||
1245            __get_user(txc.ppsfreq, &utp->ppsfreq) ||
1246            __get_user(txc.jitter, &utp->jitter) ||
1247            __get_user(txc.shift, &utp->shift) ||
1248            __get_user(txc.stabil, &utp->stabil) ||
1249            __get_user(txc.jitcnt, &utp->jitcnt) ||
1250            __get_user(txc.calcnt, &utp->calcnt) ||
1251            __get_user(txc.errcnt, &utp->errcnt) ||
1252            __get_user(txc.stbcnt, &utp->stbcnt))
1253                 return -EFAULT;
1254
1255         ret = do_adjtimex(&txc);
1256
1257         if (put_user(txc.modes, &utp->modes) ||
1258            __put_user(txc.offset, &utp->offset) ||
1259            __put_user(txc.freq, &utp->freq) ||
1260            __put_user(txc.maxerror, &utp->maxerror) ||
1261            __put_user(txc.esterror, &utp->esterror) ||
1262            __put_user(txc.status, &utp->status) ||
1263            __put_user(txc.constant, &utp->constant) ||
1264            __put_user(txc.precision, &utp->precision) ||
1265            __put_user(txc.tolerance, &utp->tolerance) ||
1266            __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
1267            __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
1268            __put_user(txc.tick, &utp->tick) ||
1269            __put_user(txc.ppsfreq, &utp->ppsfreq) ||
1270            __put_user(txc.jitter, &utp->jitter) ||
1271            __put_user(txc.shift, &utp->shift) ||
1272            __put_user(txc.stabil, &utp->stabil) ||
1273            __put_user(txc.jitcnt, &utp->jitcnt) ||
1274            __put_user(txc.calcnt, &utp->calcnt) ||
1275            __put_user(txc.errcnt, &utp->errcnt) ||
1276            __put_user(txc.stbcnt, &utp->stbcnt))
1277                 ret = -EFAULT;
1278
1279         return ret;
1280 }
1281
1282 asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset,
1283         s32 count)
1284 {
1285         mm_segment_t old_fs = get_fs();
1286         int ret;
1287         off_t of;
1288
1289         if (offset && get_user(of, offset))
1290                 return -EFAULT;
1291
1292         set_fs(KERNEL_DS);
1293         ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
1294         set_fs(old_fs);
1295
1296         if (offset && put_user(of, offset))
1297                 return -EFAULT;
1298
1299         return ret;
1300 }
1301
1302 asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
1303                                    size_t count)
1304 {
1305         return sys_readahead(fd, merge_64(a2, a3), count);
1306 }
1307
1308 /* Argument list sizes for sys_socketcall */
1309 #define AL(x) ((x) * sizeof(unsigned int))
1310 static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
1311                                 AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
1312                                 AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
1313 #undef AL
1314
1315 /*
1316  *      System call vectors.
1317  *
1318  *      Argument checking cleaned up. Saved 20% in size.
1319  *  This function doesn't need to set the kernel lock because
1320  *  it is set by the callees.
1321  */
1322
1323 asmlinkage long sys32_socketcall(int call, unsigned int *args32)
1324 {
1325         unsigned int a[6];
1326         unsigned int a0,a1;
1327         int err;
1328
1329         extern asmlinkage long sys_socket(int family, int type, int protocol);
1330         extern asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
1331         extern asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen);
1332         extern asmlinkage long sys_listen(int fd, int backlog);
1333         extern asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen);
1334         extern asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
1335         extern asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
1336         extern asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec);
1337         extern asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags);
1338         extern asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags,
1339                                           struct sockaddr __user *addr, int addr_len);
1340         extern asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags);
1341         extern asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags,
1342                                             struct sockaddr __user *addr, int __user *addr_len);
1343         extern asmlinkage long sys_shutdown(int fd, int how);
1344         extern asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen);
1345         extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int *optlen);
1346         extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
1347         extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags);
1348
1349
1350         if(call<1||call>SYS_RECVMSG)
1351                 return -EINVAL;
1352
1353         /* copy_from_user should be SMP safe. */
1354         if (copy_from_user(a, args32, socketcall_nargs[call]))
1355                 return -EFAULT;
1356
1357         a0=a[0];
1358         a1=a[1];
1359
1360         switch(call)
1361         {
1362                 case SYS_SOCKET:
1363                         err = sys_socket(a0,a1,a[2]);
1364                         break;
1365                 case SYS_BIND:
1366                         err = sys_bind(a0,(struct sockaddr __user *)A(a1), a[2]);
1367                         break;
1368                 case SYS_CONNECT:
1369                         err = sys_connect(a0, (struct sockaddr __user *)A(a1), a[2]);
1370                         break;
1371                 case SYS_LISTEN:
1372                         err = sys_listen(a0,a1);
1373                         break;
1374                 case SYS_ACCEPT:
1375                         err = sys_accept(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
1376                         break;
1377                 case SYS_GETSOCKNAME:
1378                         err = sys_getsockname(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
1379                         break;
1380                 case SYS_GETPEERNAME:
1381                         err = sys_getpeername(a0, (struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
1382                         break;
1383                 case SYS_SOCKETPAIR:
1384                         err = sys_socketpair(a0,a1, a[2], (int __user *)A(a[3]));
1385                         break;
1386                 case SYS_SEND:
1387                         err = sys_send(a0, (void __user *)A(a1), a[2], a[3]);
1388                         break;
1389                 case SYS_SENDTO:
1390                         err = sys_sendto(a0,(void __user *)A(a1), a[2], a[3],
1391                                          (struct sockaddr __user *)A(a[4]), a[5]);
1392                         break;
1393                 case SYS_RECV:
1394                         err = sys_recv(a0, (void __user *)A(a1), a[2], a[3]);
1395                         break;
1396                 case SYS_RECVFROM:
1397                         err = sys_recvfrom(a0, (void __user *)A(a1), a[2], a[3],
1398                                            (struct sockaddr __user *)A(a[4]), (int __user *)A(a[5]));
1399                         break;
1400                 case SYS_SHUTDOWN:
1401                         err = sys_shutdown(a0,a1);
1402                         break;
1403                 case SYS_SETSOCKOPT:
1404                         err = sys_setsockopt(a0, a1, a[2], (char __user *)A(a[3]), a[4]);
1405                         break;
1406                 case SYS_GETSOCKOPT:
1407                         err = sys_getsockopt(a0, a1, a[2], (char __user *)A(a[3]), (int __user *)A(a[4]));
1408                         break;
1409                 case SYS_SENDMSG:
1410                         err = sys_sendmsg(a0, (struct msghdr __user *) A(a1), a[2]);
1411                         break;
1412                 case SYS_RECVMSG:
1413                         err = sys_recvmsg(a0, (struct msghdr __user *) A(a1), a[2]);
1414                         break;
1415                 default:
1416                         err = -EINVAL;
1417                         break;
1418         }
1419         return err;
1420 }
1421
1422 struct sigevent32 {
1423         u32 sigev_value;
1424         u32 sigev_signo;
1425         u32 sigev_notify;
1426         u32 payload[(64 / 4) - 3];
1427 };
1428
1429 extern asmlinkage long
1430 sys_timer_create(clockid_t which_clock,
1431                  struct sigevent __user *timer_event_spec,
1432                  timer_t __user * created_timer_id);
1433
1434 long
1435 sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id)
1436 {
1437         struct sigevent __user *p = NULL;
1438         if (se32) {
1439                 struct sigevent se;
1440                 p = compat_alloc_user_space(sizeof(struct sigevent));
1441                 memset(&se, 0, sizeof(struct sigevent));
1442                 if (get_user(se.sigev_value.sival_int,  &se32->sigev_value) ||
1443                     __get_user(se.sigev_signo, &se32->sigev_signo) ||
1444                     __get_user(se.sigev_notify, &se32->sigev_notify) ||
1445                     __copy_from_user(&se._sigev_un._pad, &se32->payload,
1446                                      sizeof(se32->payload)) ||
1447                     copy_to_user(p, &se, sizeof(se)))
1448                         return -EFAULT;
1449         }
1450         return sys_timer_create(clock, p, timer_id);
1451 }
1452
1453 asmlinkage long
1454 sysn32_rt_sigtimedwait(const sigset_t __user *uthese,
1455                        siginfo_t __user *uinfo,
1456                        const struct compat_timespec __user *uts32,
1457                        size_t sigsetsize)
1458 {
1459         struct timespec __user *uts = NULL;
1460
1461         if (uts32) {
1462                 struct timespec ts;
1463                 uts = compat_alloc_user_space(sizeof(struct timespec));
1464                 if (get_user(ts.tv_sec, &uts32->tv_sec) ||
1465                     get_user(ts.tv_nsec, &uts32->tv_nsec) ||
1466                     copy_to_user (uts, &ts, sizeof (ts)))
1467                         return -EFAULT;
1468         }
1469         return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize);
1470 }
1471
1472 save_static_function(sys32_clone);
1473 __attribute_used__ noinline static int
1474 _sys32_clone(nabi_no_regargs struct pt_regs regs)
1475 {
1476         unsigned long clone_flags;
1477         unsigned long newsp;
1478         int __user *parent_tidptr, *child_tidptr;
1479
1480         clone_flags = regs.regs[4];
1481         newsp = regs.regs[5];
1482         if (!newsp)
1483                 newsp = regs.regs[29];
1484         parent_tidptr = (int *) regs.regs[6];
1485
1486         /* Use __dummy4 instead of getting it off the stack, so that
1487            syscall() works.  */
1488         child_tidptr = (int __user *) __dummy4;
1489         return do_fork(clone_flags, newsp, &regs, 0,
1490                        parent_tidptr, child_tidptr);
1491 }
1492
1493 extern asmlinkage void sys_set_thread_area(u32 addr);
1494 asmlinkage void sys32_set_thread_area(u32 addr)
1495 {
1496         sys_set_thread_area(AA(addr));
1497 }