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