1/*
2 * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on
3 *             sys_sparc32
4 *
5 * Copyright (C) 2000		VA Linux Co
6 * Copyright (C) 2000		Don Dugger <n0ano@valinux.com>
7 * Copyright (C) 1999 		Arun Sharma <arun.sharma@intel.com>
8 * Copyright (C) 1997,1998 	Jakub Jelinek (jj@sunsite.mff.cuni.cz)
9 * Copyright (C) 1997 		David S. Miller (davem@caip.rutgers.edu)
10 * Copyright (C) 2000		Hewlett-Packard Co.
11 * Copyright (C) 2000		David Mosberger-Tang <davidm@hpl.hp.com>
12 * Copyright (C) 2000,2001	Andi Kleen, SuSE Labs (x86-64 port)
13 *
14 * These routines maintain argument size conversion between 32bit and 64bit
15 * environment. In 2.5 most of this should be moved to a generic directory.
16 *
17 * This file assumes that there is a hole at the end of user address space.
18 * $Id: sys_ia32.c,v 1.1.1.1 2008/10/15 03:26:20 james26_jang Exp $
19 */
20
21#include <linux/config.h>
22#include <linux/kernel.h>
23#include <linux/sched.h>
24#include <linux/fs.h>
25#include <linux/file.h>
26#include <linux/signal.h>
27#include <linux/utime.h>
28#include <linux/resource.h>
29#include <linux/times.h>
30#include <linux/utsname.h>
31#include <linux/timex.h>
32#include <linux/smp.h>
33#include <linux/smp_lock.h>
34#include <linux/sem.h>
35#include <linux/msg.h>
36#include <linux/mm.h>
37#include <linux/shm.h>
38#include <linux/slab.h>
39#include <linux/uio.h>
40#include <linux/nfs_fs.h>
41#include <linux/smb_fs.h>
42#include <linux/smb_mount.h>
43#include <linux/ncp_fs.h>
44#include <linux/quota.h>
45#include <linux/module.h>
46#include <linux/sunrpc/svc.h>
47#include <linux/nfsd/nfsd.h>
48#include <linux/nfsd/cache.h>
49#include <linux/nfsd/xdr.h>
50#include <linux/nfsd/syscall.h>
51#include <linux/poll.h>
52#include <linux/personality.h>
53#include <linux/stat.h>
54#include <linux/ipc.h>
55#include <linux/rwsem.h>
56#include <linux/binfmts.h>
57#include <linux/init.h>
58#include <asm/mman.h>
59#include <asm/types.h>
60#include <asm/uaccess.h>
61#include <asm/semaphore.h>
62#include <asm/ipc.h>
63#include <asm/atomic.h>
64
65#include <net/scm.h>
66#include <net/sock.h>
67#include <asm/ia32.h>
68
69#define A(__x)		((unsigned long)(__x))
70#define AA(__x)		((unsigned long)(__x))
71#define ROUND_UP(x,a)	((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
72#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
73
74#undef high2lowuid
75#undef high2lowgid
76#undef low2highuid
77#undef low2highgid
78
79#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
80#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
81#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
82#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
83extern int overflowuid,overflowgid;
84
85
86static int
87putstat(struct stat32 *ubuf, struct stat *kbuf)
88{
89	if (verify_area(VERIFY_WRITE, ubuf, sizeof(struct stat32)) ||
90	    __put_user (kbuf->st_dev, &ubuf->st_dev) ||
91	    __put_user (kbuf->st_ino, &ubuf->st_ino) ||
92	    __put_user (kbuf->st_mode, &ubuf->st_mode) ||
93	    __put_user (kbuf->st_nlink, &ubuf->st_nlink) ||
94	    __put_user (kbuf->st_uid, &ubuf->st_uid) ||
95	    __put_user (kbuf->st_gid, &ubuf->st_gid) ||
96	    __put_user (kbuf->st_rdev, &ubuf->st_rdev) ||
97	    __put_user (kbuf->st_size, &ubuf->st_size) ||
98	    __put_user (kbuf->st_atime, &ubuf->st_atime) ||
99	    __put_user (kbuf->st_mtime, &ubuf->st_mtime) ||
100	    __put_user (kbuf->st_ctime, &ubuf->st_ctime) ||
101	    __put_user (kbuf->st_blksize, &ubuf->st_blksize) ||
102	    __put_user (kbuf->st_blocks, &ubuf->st_blocks))
103		return -EFAULT;
104	return 0;
105}
106
107extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
108
109asmlinkage long
110sys32_newstat(char * filename, struct stat32 *statbuf)
111{
112	int ret;
113	struct stat s;
114	mm_segment_t old_fs = get_fs();
115
116	set_fs (KERNEL_DS);
117	ret = sys_newstat(filename, &s);
118	set_fs (old_fs);
119	if (putstat (statbuf, &s))
120		return -EFAULT;
121	return ret;
122}
123
124extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
125
126asmlinkage long
127sys32_newlstat(char * filename, struct stat32 *statbuf)
128{
129	int ret;
130	struct stat s;
131	mm_segment_t old_fs = get_fs();
132
133	set_fs (KERNEL_DS);
134	ret = sys_newlstat(filename, &s);
135	set_fs (old_fs);
136	if (putstat (statbuf, &s))
137		return -EFAULT;
138	return ret;
139}
140
141extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
142
143asmlinkage long
144sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
145{
146	int ret;
147	struct stat s;
148	mm_segment_t old_fs = get_fs();
149
150	set_fs (KERNEL_DS);
151	ret = sys_newfstat(fd, &s);
152	set_fs (old_fs);
153	if (putstat (statbuf, &s))
154		return -EFAULT;
155	return ret;
156}
157
158/* Another set for IA32/LFS -- x86_64 struct stat is different due to
159   support for 64bit inode numbers. */
160
161static int
162putstat64(struct stat64 *ubuf, struct stat *kbuf)
163{
164	if (verify_area(VERIFY_WRITE, ubuf, sizeof(struct stat64)) ||
165	    __put_user (kbuf->st_dev, &ubuf->st_dev) ||
166	    __put_user (kbuf->st_ino, &ubuf->__st_ino) ||
167	    __put_user (kbuf->st_ino, &ubuf->st_ino) ||
168	    __put_user (kbuf->st_mode, &ubuf->st_mode) ||
169	    __put_user (kbuf->st_nlink, &ubuf->st_nlink) ||
170	    __put_user (kbuf->st_uid, &ubuf->st_uid) ||
171	    __put_user (kbuf->st_gid, &ubuf->st_gid) ||
172	    __put_user (kbuf->st_rdev, &ubuf->st_rdev) ||
173	    __put_user (kbuf->st_size, &ubuf->st_size) ||
174	    __put_user (kbuf->st_atime, &ubuf->st_atime) ||
175	    __put_user (kbuf->st_mtime, &ubuf->st_mtime) ||
176	    __put_user (kbuf->st_ctime, &ubuf->st_ctime) ||
177	    __put_user (kbuf->st_blksize, &ubuf->st_blksize) ||
178	    __put_user (kbuf->st_blocks, &ubuf->st_blocks))
179		return -EFAULT;
180	return 0;
181}
182
183asmlinkage long
184sys32_stat64(char * filename, struct stat64 *statbuf)
185{
186	int ret;
187	struct stat s;
188	mm_segment_t old_fs = get_fs();
189
190	set_fs (KERNEL_DS);
191	ret = sys_newstat(filename, &s);
192	set_fs (old_fs);
193	if (putstat64 (statbuf, &s))
194		return -EFAULT;
195	return ret;
196}
197
198asmlinkage long
199sys32_lstat64(char * filename, struct stat64 *statbuf)
200{
201	int ret;
202	struct stat s;
203	mm_segment_t old_fs = get_fs();
204
205	set_fs (KERNEL_DS);
206	ret = sys_newlstat(filename, &s);
207	set_fs (old_fs);
208	if (putstat64 (statbuf, &s))
209		return -EFAULT;
210	return ret;
211}
212
213asmlinkage long
214sys32_fstat64(unsigned int fd, struct stat64 *statbuf)
215{
216	int ret;
217	struct stat s;
218	mm_segment_t old_fs = get_fs();
219
220	set_fs (KERNEL_DS);
221	ret = sys_newfstat(fd, &s);
222	set_fs (old_fs);
223	if (putstat64 (statbuf, &s))
224		return -EFAULT;
225	return ret;
226}
227
228
229
230/*
231 * Linux/i386 didn't use to be able to handle more than
232 * 4 system call parameters, so these system calls used a memory
233 * block for parameter passing..
234 */
235
236struct mmap_arg_struct {
237	unsigned int addr;
238	unsigned int len;
239	unsigned int prot;
240	unsigned int flags;
241	unsigned int fd;
242	unsigned int offset;
243};
244
245asmlinkage __u32
246sys32_mmap(struct mmap_arg_struct *arg)
247{
248	struct mmap_arg_struct a;
249	struct file *file = NULL;
250	unsigned long retval;
251	struct mm_struct *mm ;
252
253	if (copy_from_user(&a, arg, sizeof(a)))
254		return -EFAULT;
255
256	if (a.offset & ~PAGE_MASK)
257		return -EINVAL;
258
259	if (!(a.flags & MAP_ANONYMOUS)) {
260		file = fget(a.fd);
261		if (!file)
262			return -EBADF;
263	}
264	if (a.prot & PROT_READ)
265		a.prot |= PROT_EXEC;
266
267	a.flags |= MAP_32BIT;
268
269	mm = current->mm;
270	down_write(&mm->mmap_sem);
271	retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset>>PAGE_SHIFT);
272	if (file)
273		fput(file);
274
275	/* Should not happen */
276	if (retval >= 0xFFFFFFFF && (long)retval > 0) {
277		do_munmap(mm, retval, a.len);
278		retval = -ENOMEM;
279	}
280	up_write(&mm->mmap_sem);
281
282	return retval;
283}
284
285extern asmlinkage long sys_mprotect(unsigned long start,size_t len,unsigned long prot);
286
287asmlinkage int sys32_mprotect(unsigned long start, size_t len, unsigned long prot)
288{
289	if (prot & PROT_READ)
290		prot |= PROT_EXEC;
291	return sys_mprotect(start,len,prot);
292}
293
294asmlinkage long
295sys32_pipe(int *fd)
296{
297	int retval;
298	int fds[2];
299
300	retval = do_pipe(fds);
301	if (retval)
302		goto out;
303	if (copy_to_user(fd, fds, sizeof(fds)))
304		retval = -EFAULT;
305  out:
306	return retval;
307}
308
309asmlinkage long
310sys32_rt_sigaction(int sig, struct sigaction32 *act,
311		   struct sigaction32 *oact,  unsigned int sigsetsize)
312{
313	struct k_sigaction new_ka, old_ka;
314	int ret;
315	sigset32_t set32;
316
317	if (sigsetsize != sizeof(sigset32_t))
318		return -EINVAL;
319
320	if (act) {
321		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
322		    __get_user((long)new_ka.sa.sa_handler, &act->sa_handler) ||
323		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
324		    __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer)||
325		    __copy_from_user(&set32, &act->sa_mask, sizeof(sigset32_t)))
326			return -EFAULT;
327
328		switch (_NSIG_WORDS) {
329		case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
330				| (((long)set32.sig[7]) << 32);
331		case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
332				| (((long)set32.sig[5]) << 32);
333		case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
334				| (((long)set32.sig[3]) << 32);
335		case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
336				| (((long)set32.sig[1]) << 32);
337		}
338	}
339
340	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
341
342	if (!ret && oact) {
343		switch (_NSIG_WORDS) {
344		case 4:
345			set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
346			set32.sig[6] = old_ka.sa.sa_mask.sig[3];
347		case 3:
348			set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
349			set32.sig[4] = old_ka.sa.sa_mask.sig[2];
350		case 2:
351			set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
352			set32.sig[2] = old_ka.sa.sa_mask.sig[1];
353		case 1:
354			set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
355			set32.sig[0] = old_ka.sa.sa_mask.sig[0];
356		}
357		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
358		    __put_user((long)old_ka.sa.sa_handler, &oact->sa_handler) ||
359		    __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer) ||
360		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
361		    __copy_to_user(&oact->sa_mask, &set32, sizeof(sigset32_t)))
362			return -EFAULT;
363	}
364
365	return ret;
366}
367
368asmlinkage long
369sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
370{
371        struct k_sigaction new_ka, old_ka;
372        int ret;
373
374        if (act) {
375		old_sigset32_t mask;
376
377		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
378		    __get_user((long)new_ka.sa.sa_handler, &act->sa_handler) ||
379		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
380		    __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer) ||
381		    __get_user(mask, &act->sa_mask))
382			return -EFAULT;
383		siginitset(&new_ka.sa.sa_mask, mask);
384        }
385
386        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
387
388	if (!ret && oact) {
389		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
390		    __put_user((long)old_ka.sa.sa_handler, &oact->sa_handler) ||
391		    __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer) ||
392		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
393		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
394			return -EFAULT;
395        }
396
397	return ret;
398}
399
400extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,
401					  size_t sigsetsize);
402
403asmlinkage long
404sys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset,
405		     unsigned int sigsetsize)
406{
407	sigset_t s;
408	sigset32_t s32;
409	int ret;
410	mm_segment_t old_fs = get_fs();
411
412	if (set) {
413		if (copy_from_user (&s32, set, sizeof(sigset32_t)))
414			return -EFAULT;
415		switch (_NSIG_WORDS) {
416		case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
417		case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
418		case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
419		case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
420		}
421	}
422	set_fs (KERNEL_DS);
423	ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL,
424				 sigsetsize);
425	set_fs (old_fs);
426	if (ret) return ret;
427	if (oset) {
428		switch (_NSIG_WORDS) {
429		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
430		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
431		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
432		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
433		}
434		if (copy_to_user (oset, &s32, sizeof(sigset32_t)))
435			return -EFAULT;
436	}
437	return 0;
438}
439
440static int
441put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
442{
443	if (verify_area(VERIFY_WRITE, ubuf, sizeof(struct statfs32)) ||
444	    __put_user (kbuf->f_type, &ubuf->f_type) ||
445	    __put_user (kbuf->f_bsize, &ubuf->f_bsize) ||
446	    __put_user (kbuf->f_blocks, &ubuf->f_blocks) ||
447	    __put_user (kbuf->f_bfree, &ubuf->f_bfree) ||
448	    __put_user (kbuf->f_bavail, &ubuf->f_bavail) ||
449	    __put_user (kbuf->f_files, &ubuf->f_files) ||
450	    __put_user (kbuf->f_ffree, &ubuf->f_ffree) ||
451	    __put_user (kbuf->f_namelen, &ubuf->f_namelen) ||
452	    __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
453	    __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]))
454		return -EFAULT;
455	return 0;
456}
457
458extern asmlinkage long sys_statfs(const char * path, struct statfs * buf);
459
460asmlinkage long
461sys32_statfs(const char * path, struct statfs32 *buf)
462{
463	int ret;
464	struct statfs s;
465	mm_segment_t old_fs = get_fs();
466
467	set_fs (KERNEL_DS);
468	ret = sys_statfs((const char *)path, &s);
469	set_fs (old_fs);
470	if (put_statfs(buf, &s))
471		return -EFAULT;
472	return ret;
473}
474
475extern asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf);
476
477asmlinkage long
478sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
479{
480	int ret;
481	struct statfs s;
482	mm_segment_t old_fs = get_fs();
483
484	set_fs (KERNEL_DS);
485	ret = sys_fstatfs(fd, &s);
486	set_fs (old_fs);
487	if (put_statfs(buf, &s))
488		return -EFAULT;
489	return ret;
490}
491
492struct timeval32
493{
494    int tv_sec, tv_usec;
495};
496
497struct itimerval32
498{
499    struct timeval32 it_interval;
500    struct timeval32 it_value;
501};
502
503static inline long
504get_tv32(struct timeval *o, struct timeval32 *i)
505{
506	int err = -EFAULT;
507	if (access_ok(VERIFY_READ, i, sizeof(*i))) {
508		err = __get_user(o->tv_sec, &i->tv_sec);
509		err |= __get_user(o->tv_usec, &i->tv_usec);
510	}
511	return err;
512}
513
514static inline long
515put_tv32(struct timeval32 *o, struct timeval *i)
516{
517	int err = -EFAULT;
518	if (access_ok(VERIFY_WRITE, o, sizeof(*o))) {
519		err = __put_user(i->tv_sec, &o->tv_sec);
520		err |= __put_user(i->tv_usec, &o->tv_usec);
521	}
522	return err;
523}
524
525static inline long
526get_it32(struct itimerval *o, struct itimerval32 *i)
527{
528	int err = -EFAULT;
529	if (access_ok(VERIFY_READ, i, sizeof(*i))) {
530		err = __get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec);
531		err |= __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec);
532		err |= __get_user(o->it_value.tv_sec, &i->it_value.tv_sec);
533		err |= __get_user(o->it_value.tv_usec, &i->it_value.tv_usec);
534	}
535	return err;
536}
537
538static inline long
539put_it32(struct itimerval32 *o, struct itimerval *i)
540{
541	int err = -EFAULT;
542	if (access_ok(VERIFY_WRITE, o, sizeof(*o))) {
543		err = __put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec);
544		err |= __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec);
545		err |= __put_user(i->it_value.tv_sec, &o->it_value.tv_sec);
546		err |= __put_user(i->it_value.tv_usec, &o->it_value.tv_usec);
547	}
548	return err;
549}
550
551extern int do_getitimer(int which, struct itimerval *value);
552
553asmlinkage long
554sys32_getitimer(int which, struct itimerval32 *it)
555{
556	struct itimerval kit;
557	int error;
558
559	error = do_getitimer(which, &kit);
560	if (!error && put_it32(it, &kit))
561		error = -EFAULT;
562
563	return error;
564}
565
566extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
567
568asmlinkage long
569sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
570{
571	struct itimerval kin, kout;
572	int error;
573
574	if (in) {
575		if (get_it32(&kin, in))
576			return -EFAULT;
577	} else
578		memset(&kin, 0, sizeof(kin));
579
580	error = do_setitimer(which, &kin, out ? &kout : NULL);
581	if (error || !out)
582		return error;
583	if (put_it32(out, &kout))
584		return -EFAULT;
585
586	return 0;
587
588}
589asmlinkage unsigned long
590sys32_alarm(unsigned int seconds)
591{
592	struct itimerval it_new, it_old;
593	unsigned int oldalarm;
594
595	it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
596	it_new.it_value.tv_sec = seconds;
597	it_new.it_value.tv_usec = 0;
598	do_setitimer(ITIMER_REAL, &it_new, &it_old);
599	oldalarm = it_old.it_value.tv_sec;
600	/* ehhh.. We can't return 0 if we have an alarm pending.. */
601	/* And we'd better return too much than too little anyway */
602	if (it_old.it_value.tv_usec)
603		oldalarm++;
604	return oldalarm;
605}
606
607/* Translations due to time_t size differences.  Which affects all
608   sorts of things, like timeval and itimerval.  */
609
610struct utimbuf_32 {
611	int	atime;
612	int	mtime;
613};
614
615extern asmlinkage long sys_utimes(char * filename, struct timeval * utimes);
616extern asmlinkage long sys_gettimeofday (struct timeval *tv, struct timezone *tz);
617
618extern struct timezone sys_tz;
619extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
620
621asmlinkage long
622sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
623{
624	if (tv) {
625		struct timeval ktv;
626		do_gettimeofday(&ktv);
627		if (put_tv32(tv, &ktv))
628			return -EFAULT;
629	}
630	if (tz) {
631		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
632			return -EFAULT;
633	}
634	return 0;
635}
636
637asmlinkage long
638sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
639{
640	struct timeval ktv;
641	struct timezone ktz;
642
643 	if (tv) {
644		if (get_tv32(&ktv, tv))
645			return -EFAULT;
646	}
647	if (tz) {
648		if (copy_from_user(&ktz, tz, sizeof(ktz)))
649			return -EFAULT;
650	}
651
652	return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
653}
654
655struct linux32_dirent {
656	u32	d_ino;
657	u32	d_off;
658	u16	d_reclen;
659	char	d_name[1];
660};
661
662struct old_linux32_dirent {
663	u32	d_ino;
664	u32	d_offset;
665	u16	d_namlen;
666	char	d_name[1];
667};
668
669struct getdents32_callback {
670	struct linux32_dirent * current_dir;
671	struct linux32_dirent * previous;
672	int count;
673	int error;
674};
675
676struct readdir32_callback {
677	struct old_linux32_dirent * dirent;
678	int count;
679};
680
681static int
682filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
683	   unsigned int d_type)
684{
685	struct linux32_dirent * dirent;
686	struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
687	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
688
689	buf->error = -EINVAL;	/* only used if we fail.. */
690	if (reclen > buf->count)
691		return -EINVAL;
692	dirent = buf->previous;
693	if (dirent)
694		put_user(offset, &dirent->d_off);
695	dirent = buf->current_dir;
696	buf->previous = dirent;
697	put_user(ino, &dirent->d_ino);
698	put_user(reclen, &dirent->d_reclen);
699	copy_to_user(dirent->d_name, name, namlen);
700	put_user(0, dirent->d_name + namlen);
701	((char *) dirent) += reclen;
702	buf->current_dir = dirent;
703	buf->count -= reclen;
704	return 0;
705}
706
707asmlinkage long
708sys32_getdents (unsigned int fd, void * dirent, unsigned int count)
709{
710	struct file * file;
711	struct linux32_dirent * lastdirent;
712	struct getdents32_callback buf;
713	int error;
714
715	error = -EBADF;
716	file = fget(fd);
717	if (!file)
718		goto out;
719
720	buf.current_dir = (struct linux32_dirent *) dirent;
721	buf.previous = NULL;
722	buf.count = count;
723	buf.error = 0;
724
725	error = vfs_readdir(file, filldir32, &buf);
726	if (error < 0)
727		goto out_putf;
728	error = buf.error;
729	lastdirent = buf.previous;
730	if (lastdirent) {
731		put_user(file->f_pos, &lastdirent->d_off);
732		error = count - buf.count;
733	}
734
735out_putf:
736	fput(file);
737out:
738	return error;
739}
740
741static int
742fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, unsigned d_type)
743{
744	struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
745	struct old_linux32_dirent * dirent;
746
747	if (buf->count)
748		return -EINVAL;
749	buf->count++;
750	dirent = buf->dirent;
751	put_user(ino, &dirent->d_ino);
752	put_user(offset, &dirent->d_offset);
753	put_user(namlen, &dirent->d_namlen);
754	copy_to_user(dirent->d_name, name, namlen);
755	put_user(0, dirent->d_name + namlen);
756	return 0;
757}
758
759asmlinkage long
760sys32_oldreaddir (unsigned int fd, void * dirent, unsigned int count)
761{
762	int error;
763	struct file * file;
764	struct readdir32_callback buf;
765
766	error = -EBADF;
767	file = fget(fd);
768	if (!file)
769		goto out;
770
771	buf.count = 0;
772	buf.dirent = dirent;
773
774	error = vfs_readdir(file, fillonedir32, &buf);
775	if (error >= 0)
776		error = buf.count;
777	fput(file);
778out:
779	return error;
780}
781
782/*
783 * We can actually return ERESTARTSYS instead of EINTR, but I'd
784 * like to be certain this leads to no problems. So I return
785 * EINTR just for safety.
786 *
787 * Update: ERESTARTSYS breaks at least the xview clock binary, so
788 * I'm trying ERESTARTNOHAND which restart only when you want to.
789 */
790#define MAX_SELECT_SECONDS \
791	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
792#define ROUND_UP_TIME(x,y) (((x)+(y)-1)/(y))
793
794asmlinkage long
795sys32_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval32 *tvp32)
796{
797	fd_set_bits fds;
798	char *bits;
799	long timeout;
800	int ret, size;
801
802	timeout = MAX_SCHEDULE_TIMEOUT;
803	if (tvp32) {
804		time_t sec, usec;
805
806		get_user(sec, &tvp32->tv_sec);
807		get_user(usec, &tvp32->tv_usec);
808
809		ret = -EINVAL;
810		if (sec < 0 || usec < 0)
811			goto out_nofds;
812
813		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
814			timeout = ROUND_UP_TIME(usec, 1000000/HZ);
815			timeout += sec * (unsigned long) HZ;
816		}
817	}
818
819	ret = -EINVAL;
820	if (n < 0)
821		goto out_nofds;
822
823	if (n > current->files->max_fdset)
824		n = current->files->max_fdset;
825
826	/*
827	 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
828	 * since we used fdset we need to allocate memory in units of
829	 * long-words.
830	 */
831	ret = -ENOMEM;
832	size = FDS_BYTES(n);
833	bits = kmalloc(6 * size, GFP_KERNEL);
834	if (!bits)
835		goto out_nofds;
836	fds.in      = (unsigned long *)  bits;
837	fds.out     = (unsigned long *) (bits +   size);
838	fds.ex      = (unsigned long *) (bits + 2*size);
839	fds.res_in  = (unsigned long *) (bits + 3*size);
840	fds.res_out = (unsigned long *) (bits + 4*size);
841	fds.res_ex  = (unsigned long *) (bits + 5*size);
842
843	if ((ret = get_fd_set(n, inp, fds.in)) ||
844	    (ret = get_fd_set(n, outp, fds.out)) ||
845	    (ret = get_fd_set(n, exp, fds.ex)))
846		goto out;
847	zero_fd_set(n, fds.res_in);
848	zero_fd_set(n, fds.res_out);
849	zero_fd_set(n, fds.res_ex);
850
851	ret = do_select(n, &fds, &timeout);
852
853	if (tvp32 && !(current->personality & STICKY_TIMEOUTS)) {
854		time_t sec = 0, usec = 0;
855		if (timeout) {
856			sec = timeout / HZ;
857			usec = timeout % HZ;
858			usec *= (1000000/HZ);
859		}
860		put_user(sec, (int *)&tvp32->tv_sec);
861		put_user(usec, (int *)&tvp32->tv_usec);
862	}
863
864	if (ret < 0)
865		goto out;
866	if (!ret) {
867		ret = -ERESTARTNOHAND;
868		if (signal_pending(current))
869			goto out;
870		ret = 0;
871	}
872
873	set_fd_set(n, inp, fds.res_in);
874	set_fd_set(n, outp, fds.res_out);
875	set_fd_set(n, exp, fds.res_ex);
876
877out:
878	kfree(bits);
879out_nofds:
880	return ret;
881}
882
883struct sel_arg_struct {
884	unsigned int n;
885	unsigned int inp;
886	unsigned int outp;
887	unsigned int exp;
888	unsigned int tvp;
889};
890
891asmlinkage long
892sys32_old_select(struct sel_arg_struct *arg)
893{
894	struct sel_arg_struct a;
895
896	if (copy_from_user(&a, arg, sizeof(a)))
897		return -EFAULT;
898	return sys32_select(a.n, (fd_set *)A(a.inp), (fd_set *)A(a.outp), (fd_set *)A(a.exp),
899			    (struct timeval32 *)A(a.tvp));
900}
901
902struct timespec32 {
903	int 	tv_sec;
904	int	tv_nsec;
905};
906
907extern asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
908
909asmlinkage long
910sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
911{
912	struct timespec t;
913	int ret;
914	mm_segment_t old_fs = get_fs ();
915
916	if (verify_area(VERIFY_READ, rqtp, sizeof(struct timespec32)) ||
917	    __get_user (t.tv_sec, &rqtp->tv_sec) ||
918	    __get_user (t.tv_nsec, &rqtp->tv_nsec))
919		return -EFAULT;
920	set_fs (KERNEL_DS);
921	ret = sys_nanosleep(&t, rmtp ? &t : NULL);
922	set_fs (old_fs);
923	if (rmtp && ret == -EINTR) {
924		if (verify_area(VERIFY_WRITE, rmtp, sizeof(struct timespec32)) ||
925		    __put_user (t.tv_sec, &rmtp->tv_sec) ||
926	    	    __put_user (t.tv_nsec, &rmtp->tv_nsec))
927			return -EFAULT;
928	}
929	return ret;
930}
931
932asmlinkage ssize_t sys_readv(unsigned long,const struct iovec *,unsigned long);
933asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long);
934
935struct iovec *
936get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type)
937{
938	int i;
939	u32 buf, len;
940	struct iovec *ivp, *iov;
941
942	/* Get the "struct iovec" from user memory */
943
944	if (!count)
945		return 0;
946	if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
947		return(struct iovec *)0;
948	if (count > UIO_MAXIOV)
949		return(struct iovec *)0;
950	if (count > UIO_FASTIOV) {
951		iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
952		if (!iov)
953			return((struct iovec *)0);
954	} else
955		iov = iov_buf;
956
957	ivp = iov;
958	for (i = 0; i < count; i++) {
959		if (__get_user(len, &iov32->iov_len) ||
960		    __get_user(buf, &iov32->iov_base)) {
961			if (iov != iov_buf)
962				kfree(iov);
963			return((struct iovec *)0);
964		}
965		if (verify_area(type, (void *)A(buf), len)) {
966			if (iov != iov_buf)
967				kfree(iov);
968			return((struct iovec *)0);
969		}
970		ivp->iov_base = (void *)A(buf);
971		ivp->iov_len = (__kernel_size_t)len;
972		iov32++;
973		ivp++;
974	}
975	return(iov);
976}
977
978asmlinkage long
979sys32_readv(int fd, struct iovec32 *vector, u32 count)
980{
981	struct iovec iovstack[UIO_FASTIOV];
982	struct iovec *iov;
983	int ret;
984	mm_segment_t old_fs = get_fs();
985
986	if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE)) == (struct iovec *)0)
987		return -EFAULT;
988	set_fs(KERNEL_DS);
989	ret = sys_readv(fd, iov, count);
990	set_fs(old_fs);
991	if (iov != iovstack)
992		kfree(iov);
993	return ret;
994}
995
996asmlinkage long
997sys32_writev(int fd, struct iovec32 *vector, u32 count)
998{
999	struct iovec iovstack[UIO_FASTIOV];
1000	struct iovec *iov;
1001	int ret;
1002	mm_segment_t old_fs = get_fs();
1003
1004	if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ)) == (struct iovec *)0)
1005		return -EFAULT;
1006	set_fs(KERNEL_DS);
1007	ret = sys_writev(fd, iov, count);
1008	set_fs(old_fs);
1009	if (iov != iovstack)
1010		kfree(iov);
1011	return ret;
1012}
1013
1014#define RLIM_INFINITY32	0xffffffff
1015#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
1016
1017struct rlimit32 {
1018	int	rlim_cur;
1019	int	rlim_max;
1020};
1021
1022extern asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim);
1023
1024asmlinkage long
1025sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
1026{
1027	struct rlimit r;
1028	int ret;
1029	mm_segment_t old_fs;
1030
1031	old_fs = get_fs();
1032	set_fs(KERNEL_DS);
1033	ret = sys_getrlimit(resource, &r);
1034	set_fs(old_fs);
1035	if (!ret) {
1036		if (verify_area(VERIFY_WRITE, rlim, sizeof(struct rlimit32)) ||
1037		    __put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur) ||
1038		    __put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max))
1039			ret = -EFAULT;
1040	}
1041	return ret;
1042}
1043
1044extern asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim);
1045
1046asmlinkage long
1047sys32_old_getrlimit(unsigned int resource, struct rlimit32 *rlim)
1048{
1049	struct rlimit r;
1050	int ret;
1051	mm_segment_t old_fs;
1052
1053	old_fs = get_fs();
1054	set_fs(KERNEL_DS);
1055	ret = sys_old_getrlimit(resource, &r);
1056	set_fs(old_fs);
1057	if (!ret) {
1058		if (verify_area(VERIFY_WRITE, rlim, sizeof(struct rlimit32)) ||
1059		    __put_user(r.rlim_cur, &rlim->rlim_cur) ||
1060		    __put_user(r.rlim_max, &rlim->rlim_max))
1061			ret = -EFAULT;
1062	}
1063	return ret;
1064}
1065
1066extern asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim);
1067
1068asmlinkage long
1069sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
1070{
1071	struct rlimit r;
1072	int ret;
1073	mm_segment_t old_fs = get_fs ();
1074
1075	if (resource >= RLIM_NLIMITS) return -EINVAL;
1076	if (verify_area(VERIFY_READ, rlim, sizeof(struct rlimit32)) ||
1077	    __get_user (r.rlim_cur, &rlim->rlim_cur) ||
1078	    __get_user (r.rlim_max, &rlim->rlim_max))
1079		return -EFAULT;
1080	if (r.rlim_cur == RLIM_INFINITY32)
1081		r.rlim_cur = RLIM_INFINITY;
1082	if (r.rlim_max == RLIM_INFINITY32)
1083		r.rlim_max = RLIM_INFINITY;
1084	set_fs (KERNEL_DS);
1085	ret = sys_setrlimit(resource, &r);
1086	set_fs (old_fs);
1087	return ret;
1088}
1089
1090/*
1091 * sys_time() can be implemented in user-level using
1092 * sys_gettimeofday().  IA64 did this but i386 Linux did not
1093 * so we have to implement this system call here.
1094 */
1095asmlinkage long sys32_time(int * tloc)
1096{
1097	int i;
1098
1099	/* SMP: This is fairly trivial. We grab CURRENT_TIME and
1100	   stuff it to user space. No side effects */
1101	i = CURRENT_TIME;
1102	if (tloc) {
1103		if (put_user(i,tloc))
1104			i = -EFAULT;
1105	}
1106	return i;
1107}
1108
1109struct rusage32 {
1110        struct timeval32 ru_utime;
1111        struct timeval32 ru_stime;
1112        int    ru_maxrss;
1113        int    ru_ixrss;
1114        int    ru_idrss;
1115        int    ru_isrss;
1116        int    ru_minflt;
1117        int    ru_majflt;
1118        int    ru_nswap;
1119        int    ru_inblock;
1120        int    ru_oublock;
1121        int    ru_msgsnd;
1122        int    ru_msgrcv;
1123        int    ru_nsignals;
1124        int    ru_nvcsw;
1125        int    ru_nivcsw;
1126};
1127
1128static int
1129put_rusage (struct rusage32 *ru, struct rusage *r)
1130{
1131	if (verify_area(VERIFY_WRITE, ru, sizeof(struct rusage32)) ||
1132	    __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) ||
1133	    __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec) ||
1134	    __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec) ||
1135	    __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec) ||
1136	    __put_user (r->ru_maxrss, &ru->ru_maxrss) ||
1137	    __put_user (r->ru_ixrss, &ru->ru_ixrss) ||
1138	    __put_user (r->ru_idrss, &ru->ru_idrss) ||
1139	    __put_user (r->ru_isrss, &ru->ru_isrss) ||
1140	    __put_user (r->ru_minflt, &ru->ru_minflt) ||
1141	    __put_user (r->ru_majflt, &ru->ru_majflt) ||
1142	    __put_user (r->ru_nswap, &ru->ru_nswap) ||
1143	    __put_user (r->ru_inblock, &ru->ru_inblock) ||
1144	    __put_user (r->ru_oublock, &ru->ru_oublock) ||
1145	    __put_user (r->ru_msgsnd, &ru->ru_msgsnd) ||
1146	    __put_user (r->ru_msgrcv, &ru->ru_msgrcv) ||
1147	    __put_user (r->ru_nsignals, &ru->ru_nsignals) ||
1148	    __put_user (r->ru_nvcsw, &ru->ru_nvcsw) ||
1149	    __put_user (r->ru_nivcsw, &ru->ru_nivcsw))
1150		return -EFAULT;
1151	return 0;
1152}
1153
1154extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr,
1155				int options, struct rusage * ru);
1156
1157asmlinkage long
1158sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options,
1159	    struct rusage32 *ru)
1160{
1161	if (!ru)
1162		return sys_wait4(pid, stat_addr, options, NULL);
1163	else {
1164		struct rusage r;
1165		int ret;
1166		unsigned int status;
1167		mm_segment_t old_fs = get_fs();
1168
1169		set_fs (KERNEL_DS);
1170		ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
1171		set_fs (old_fs);
1172		if (put_rusage (ru, &r)) return -EFAULT;
1173		if (stat_addr && put_user (status, stat_addr))
1174			return -EFAULT;
1175		return ret;
1176	}
1177}
1178
1179asmlinkage long
1180sys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options)
1181{
1182	return sys32_wait4(pid, stat_addr, options, NULL);
1183}
1184
1185
1186extern asmlinkage long
1187sys_getrusage(int who, struct rusage *ru);
1188
1189asmlinkage long
1190sys32_getrusage(int who, struct rusage32 *ru)
1191{
1192	struct rusage r;
1193	int ret;
1194	mm_segment_t old_fs = get_fs();
1195
1196	set_fs (KERNEL_DS);
1197	ret = sys_getrusage(who, &r);
1198	set_fs (old_fs);
1199	if (put_rusage (ru, &r)) return -EFAULT;
1200	return ret;
1201}
1202
1203struct tms32 {
1204	__kernel_clock_t32 tms_utime;
1205	__kernel_clock_t32 tms_stime;
1206	__kernel_clock_t32 tms_cutime;
1207	__kernel_clock_t32 tms_cstime;
1208};
1209
1210extern int sys_times(struct tms *);
1211
1212asmlinkage long
1213sys32_times(struct tms32 *tbuf)
1214{
1215	struct tms t;
1216	long ret;
1217	mm_segment_t old_fs = get_fs ();
1218
1219	set_fs (KERNEL_DS);
1220	ret = sys_times(tbuf ? &t : NULL);
1221	set_fs (old_fs);
1222	if (tbuf) {
1223		if (verify_area(VERIFY_WRITE, tbuf, sizeof(struct tms32)) ||
1224		    __put_user (t.tms_utime, &tbuf->tms_utime) ||
1225		    __put_user (t.tms_stime, &tbuf->tms_stime) ||
1226		    __put_user (t.tms_cutime, &tbuf->tms_cutime) ||
1227		    __put_user (t.tms_cstime, &tbuf->tms_cstime))
1228			return -EFAULT;
1229	}
1230	return ret;
1231}
1232
1233
1234static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
1235{
1236	int err;
1237
1238	err = get_user(kfl->l_type, &ufl->l_type);
1239	err |= __get_user(kfl->l_whence, &ufl->l_whence);
1240	err |= __get_user(kfl->l_start, &ufl->l_start);
1241	err |= __get_user(kfl->l_len, &ufl->l_len);
1242	err |= __get_user(kfl->l_pid, &ufl->l_pid);
1243	return err;
1244}
1245
1246static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
1247{
1248	int err;
1249
1250	err = __put_user(kfl->l_type, &ufl->l_type);
1251	err |= __put_user(kfl->l_whence, &ufl->l_whence);
1252	err |= __put_user(kfl->l_start, &ufl->l_start);
1253	err |= __put_user(kfl->l_len, &ufl->l_len);
1254	err |= __put_user(kfl->l_pid, &ufl->l_pid);
1255	return err;
1256}
1257
1258extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
1259asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg);
1260
1261
1262asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
1263{
1264	switch (cmd) {
1265	case F_GETLK:
1266	case F_SETLK:
1267	case F_SETLKW:
1268		{
1269			struct flock f;
1270			mm_segment_t old_fs;
1271			long ret;
1272
1273			if (get_flock(&f, (struct flock32 *)arg))
1274				return -EFAULT;
1275			old_fs = get_fs(); set_fs (KERNEL_DS);
1276			ret = sys_fcntl(fd, cmd, (unsigned long)&f);
1277			set_fs (old_fs);
1278			if (ret) return ret;
1279			if (put_flock(&f, (struct flock32 *)arg))
1280				return -EFAULT;
1281			return 0;
1282		}
1283	case F_GETLK64:
1284	case F_SETLK64:
1285	case F_SETLKW64:
1286		return sys32_fcntl64(fd,cmd,arg);
1287
1288	default:
1289		return sys_fcntl(fd, cmd, (unsigned long)arg);
1290	}
1291}
1292
1293static inline int get_flock64(struct ia32_flock64 *fl32, struct flock *fl64)
1294{
1295	if (access_ok(fl32, sizeof(struct ia32_flock64), VERIFY_WRITE)) {
1296		int ret = __get_user(fl64->l_type, &fl32->l_type);
1297		ret |= __get_user(fl64->l_whence, &fl32->l_whence);
1298		ret |= __get_user(fl64->l_start, &fl32->l_start);
1299		ret |= __get_user(fl64->l_len, &fl32->l_len);
1300		ret |= __get_user(fl64->l_pid, &fl32->l_pid);
1301		return ret;
1302	}
1303	return -EFAULT;
1304}
1305
1306static inline int put_flock64(struct ia32_flock64 *fl32, struct flock *fl64)
1307{
1308	if (access_ok(fl32, sizeof(struct ia32_flock64), VERIFY_WRITE)) {
1309		int ret = __put_user(fl64->l_type, &fl32->l_type);
1310		ret |= __put_user(fl64->l_whence, &fl32->l_whence);
1311		ret |= __put_user(fl64->l_start, &fl32->l_start);
1312		ret |= __put_user(fl64->l_len, &fl32->l_len);
1313		ret |= __put_user(fl64->l_pid, &fl32->l_pid);
1314		return ret;
1315	}
1316	return -EFAULT;
1317}
1318
1319asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
1320{
1321	struct flock fl64;
1322	mm_segment_t oldfs = get_fs();
1323	int ret = 0;
1324	int oldcmd = cmd;
1325	unsigned long oldarg = arg;
1326
1327	switch (cmd) {
1328	case F_GETLK64:
1329		cmd = F_GETLK;
1330		goto cnv;
1331	case F_SETLK64:
1332		cmd = F_SETLK;
1333		goto cnv;
1334	case F_SETLKW64:
1335		cmd = F_SETLKW;
1336	cnv:
1337		ret = get_flock64((struct ia32_flock64 *)arg, &fl64);
1338		arg = (unsigned long)&fl64;
1339		set_fs(KERNEL_DS);
1340		break;
1341	case F_GETLK:
1342	case F_SETLK:
1343	case F_SETLKW:
1344		return sys32_fcntl(fd,cmd,arg);
1345	}
1346	if (!ret)
1347		ret = sys_fcntl(fd, cmd, arg);
1348	set_fs(oldfs);
1349	if (oldcmd == F_GETLK64 && !ret)
1350		ret = put_flock64((struct ia32_flock64 *)oldarg, &fl64);
1351	return ret;
1352}
1353
1354int sys32_ni_syscall(int call)
1355{
1356	printk(KERN_INFO "IA32 syscall %d from %s not implemented\n", call,
1357	       current->comm);
1358	return -ENOSYS;
1359}
1360
1361/* 32-bit timeval and related flotsam.  */
1362
1363extern asmlinkage long sys_utime(char * filename, struct utimbuf * times);
1364
1365struct utimbuf32 {
1366	__kernel_time_t32 actime, modtime;
1367};
1368
1369asmlinkage long
1370sys32_utime(char * filename, struct utimbuf32 *times)
1371{
1372	struct utimbuf t;
1373	mm_segment_t old_fs;
1374	int ret;
1375	char *filenam;
1376
1377	if (!times)
1378		return sys_utime(filename, NULL);
1379	if (verify_area(VERIFY_READ, times, sizeof(struct utimbuf32)) ||
1380	    __get_user (t.actime, &times->actime) ||
1381	    __get_user (t.modtime, &times->modtime))
1382		return -EFAULT;
1383	filenam = getname (filename);
1384	ret = PTR_ERR(filenam);
1385	if (!IS_ERR(filenam)) {
1386		old_fs = get_fs();
1387		set_fs (KERNEL_DS);
1388		ret = sys_utime(filenam, &t);
1389		set_fs (old_fs);
1390		putname(filenam);
1391	}
1392	return ret;
1393}
1394
1395extern asmlinkage long sys_sysfs(int option, unsigned long arg1,
1396				unsigned long arg2);
1397
1398asmlinkage long
1399sys32_sysfs(int option, u32 arg1, u32 arg2)
1400{
1401	return sys_sysfs(option, arg1, arg2);
1402}
1403
1404extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
1405				unsigned long new_flags, void *data);
1406
1407static char *badfs[] = {
1408	"smbfs", "ncpfs", NULL
1409};
1410
1411static int checktype(char *user_type)
1412{
1413	int err = 0;
1414	char **s,*kernel_type = getname(user_type);
1415	if (!kernel_type || IS_ERR(kernel_type))
1416		return -EFAULT;
1417	for (s = badfs; *s; ++s)
1418		if (!strcmp(kernel_type, *s)) {
1419			printk(KERN_ERR "mount32: unsupported fs `%s' -- use 64bit mount\n", *s);
1420			err = -EINVAL;
1421			break;
1422		}
1423	putname(user_type);
1424	return err;
1425}
1426
1427asmlinkage long
1428sys32_mount(char *dev_name, char *dir_name, char *type,
1429	    unsigned long new_flags, u32 data)
1430{
1431	int err;
1432	if(!capable(CAP_SYS_ADMIN))
1433		return -EPERM;
1434	err = checktype(type);
1435	if (err)
1436		return err;
1437	return sys_mount(dev_name, dir_name, type, new_flags, (void *)AA(data));
1438}
1439
1440struct sysinfo32 {
1441        s32 uptime;
1442        u32 loads[3];
1443        u32 totalram;
1444        u32 freeram;
1445        u32 sharedram;
1446        u32 bufferram;
1447        u32 totalswap;
1448        u32 freeswap;
1449        unsigned short procs;
1450        char _f[22];
1451};
1452
1453extern asmlinkage long sys_sysinfo(struct sysinfo *info);
1454
1455asmlinkage long
1456sys32_sysinfo(struct sysinfo32 *info)
1457{
1458	struct sysinfo s;
1459	int ret;
1460	mm_segment_t old_fs = get_fs ();
1461
1462	set_fs (KERNEL_DS);
1463	ret = sys_sysinfo(&s);
1464	set_fs (old_fs);
1465	if (verify_area(VERIFY_WRITE, info, sizeof(struct sysinfo32)) ||
1466	    __put_user (s.uptime, &info->uptime) ||
1467	    __put_user (s.loads[0], &info->loads[0]) ||
1468	    __put_user (s.loads[1], &info->loads[1]) ||
1469	    __put_user (s.loads[2], &info->loads[2]) ||
1470	    __put_user (s.totalram, &info->totalram) ||
1471	    __put_user (s.freeram, &info->freeram) ||
1472	    __put_user (s.sharedram, &info->sharedram) ||
1473	    __put_user (s.bufferram, &info->bufferram) ||
1474	    __put_user (s.totalswap, &info->totalswap) ||
1475	    __put_user (s.freeswap, &info->freeswap) ||
1476	    __put_user (s.procs, &info->procs))
1477		return -EFAULT;
1478	return 0;
1479}
1480
1481extern asmlinkage long sys_sched_rr_get_interval(pid_t pid,
1482						struct timespec *interval);
1483
1484asmlinkage long
1485sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
1486{
1487	struct timespec t;
1488	int ret;
1489	mm_segment_t old_fs = get_fs ();
1490
1491	set_fs (KERNEL_DS);
1492	ret = sys_sched_rr_get_interval(pid, &t);
1493	set_fs (old_fs);
1494	if (verify_area(VERIFY_WRITE, interval, sizeof(struct timespec32)) ||
1495	    __put_user (t.tv_sec, &interval->tv_sec) ||
1496	    __put_user (t.tv_nsec, &interval->tv_nsec))
1497		return -EFAULT;
1498	return ret;
1499}
1500
1501extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set,
1502				      old_sigset_t *oset);
1503
1504asmlinkage long
1505sys32_sigprocmask(int how, old_sigset32_t *set, old_sigset32_t *oset)
1506{
1507	old_sigset_t s;
1508	int ret;
1509	mm_segment_t old_fs = get_fs();
1510
1511	if (set && get_user (s, set)) return -EFAULT;
1512	set_fs (KERNEL_DS);
1513	ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
1514	set_fs (old_fs);
1515	if (ret) return ret;
1516	if (oset && put_user (s, oset)) return -EFAULT;
1517	return 0;
1518}
1519
1520extern asmlinkage long sys_sigpending(old_sigset_t *set);
1521
1522asmlinkage long
1523sys32_sigpending(old_sigset32_t *set)
1524{
1525	old_sigset_t s;
1526	int ret;
1527	mm_segment_t old_fs = get_fs();
1528
1529	set_fs (KERNEL_DS);
1530	ret = sys_sigpending(&s);
1531	set_fs (old_fs);
1532	if (put_user (s, set)) return -EFAULT;
1533	return ret;
1534}
1535
1536extern asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
1537
1538asmlinkage long
1539sys32_rt_sigpending(sigset32_t *set, __kernel_size_t32 sigsetsize)
1540{
1541	sigset_t s;
1542	sigset32_t s32;
1543	int ret;
1544	mm_segment_t old_fs = get_fs();
1545
1546	set_fs (KERNEL_DS);
1547	ret = sys_rt_sigpending(&s, sigsetsize);
1548	set_fs (old_fs);
1549	if (!ret) {
1550		switch (_NSIG_WORDS) {
1551		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
1552		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
1553		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
1554		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
1555		}
1556		if (copy_to_user (set, &s32, sizeof(sigset32_t)))
1557			return -EFAULT;
1558	}
1559	return ret;
1560}
1561
1562siginfo_t32 *
1563siginfo64to32(siginfo_t32 *d, siginfo_t *s)
1564{
1565	memset (d, 0, sizeof(siginfo_t32));
1566	d->si_signo = s->si_signo;
1567	d->si_errno = s->si_errno;
1568	d->si_code = s->si_code;
1569	if (s->si_signo >= SIGRTMIN) {
1570		d->si_pid = s->si_pid;
1571		d->si_uid = s->si_uid;
1572		d->si_int = s->si_int;
1573	} else switch (s->si_signo) {
1574	case SIGCHLD:
1575		d->si_pid = s->si_pid;
1576		d->si_status = s->si_status;
1577		d->si_utime = s->si_utime;
1578		d->si_stime = s->si_stime;
1579		break;
1580	case SIGSEGV:
1581	case SIGBUS:
1582	case SIGFPE:
1583	case SIGILL:
1584		d->si_addr = (long)(s->si_addr);
1585//		d->si_trapno = s->si_trapno;
1586		break;
1587	case SIGPOLL:
1588		d->si_band = s->si_band;
1589		d->si_fd = s->si_fd;
1590		break;
1591	default:
1592		d->si_pid = s->si_pid;
1593		d->si_uid = s->si_uid;
1594		break;
1595	}
1596	return d;
1597}
1598
1599siginfo_t *
1600siginfo32to64(siginfo_t *d, siginfo_t32 *s)
1601{
1602	d->si_signo = s->si_signo;
1603	d->si_errno = s->si_errno;
1604	d->si_code = s->si_code;
1605	if (s->si_signo >= SIGRTMIN) {
1606		d->si_pid = s->si_pid;
1607		d->si_uid = s->si_uid;
1608		d->si_int = s->si_int;
1609	} else switch (s->si_signo) {
1610	case SIGCHLD:
1611		d->si_pid = s->si_pid;
1612		d->si_status = s->si_status;
1613		d->si_utime = s->si_utime;
1614		d->si_stime = s->si_stime;
1615		break;
1616	case SIGSEGV:
1617	case SIGBUS:
1618	case SIGFPE:
1619	case SIGILL:
1620		d->si_addr = (void *)A(s->si_addr);
1621//		d->si_trapno = s->si_trapno;
1622		break;
1623	case SIGPOLL:
1624		d->si_band = s->si_band;
1625		d->si_fd = s->si_fd;
1626		break;
1627	default:
1628		d->si_pid = s->si_pid;
1629		d->si_uid = s->si_uid;
1630		break;
1631	}
1632	return d;
1633}
1634
1635extern asmlinkage long
1636sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
1637		    const struct timespec *uts, size_t sigsetsize);
1638
1639asmlinkage long
1640sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
1641		      struct timespec32 *uts, __kernel_size_t32 sigsetsize)
1642{
1643	sigset_t s;
1644	sigset32_t s32;
1645	struct timespec t;
1646	int ret;
1647	mm_segment_t old_fs = get_fs();
1648	siginfo_t info;
1649	siginfo_t32 info32;
1650
1651	if (copy_from_user (&s32, uthese, sizeof(sigset32_t)))
1652		return -EFAULT;
1653	switch (_NSIG_WORDS) {
1654	case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
1655	case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
1656	case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
1657	case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
1658	}
1659	if (uts) {
1660		if (verify_area(VERIFY_READ, uts, sizeof(struct timespec32)) ||
1661		    __get_user (t.tv_sec, &uts->tv_sec) ||
1662		    __get_user (t.tv_nsec, &uts->tv_nsec))
1663			return -EFAULT;
1664	}
1665	set_fs (KERNEL_DS);
1666	ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
1667	set_fs (old_fs);
1668	if (ret >= 0 && uinfo) {
1669		if (copy_to_user (uinfo, siginfo64to32(&info32, &info),
1670				  sizeof(siginfo_t32)))
1671			return -EFAULT;
1672	}
1673	return ret;
1674}
1675
1676extern asmlinkage long
1677sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
1678
1679asmlinkage long
1680sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
1681{
1682	siginfo_t info;
1683	siginfo_t32 info32;
1684	int ret;
1685	mm_segment_t old_fs = get_fs();
1686
1687	if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32)))
1688		return -EFAULT;
1689	siginfo32to64(&info, &info32);
1690	set_fs (KERNEL_DS);
1691	ret = sys_rt_sigqueueinfo(pid, sig, &info);
1692	set_fs (old_fs);
1693	return ret;
1694}
1695
1696extern void check_pending(int signum);
1697
1698asmlinkage long sys_utimes(char *, struct timeval *);
1699
1700asmlinkage long
1701sys32_utimes(char *filename, struct timeval32 *tvs)
1702{
1703	char *kfilename;
1704	struct timeval ktvs[2];
1705	mm_segment_t old_fs;
1706	int ret;
1707
1708	kfilename = getname(filename);
1709	ret = PTR_ERR(kfilename);
1710	if (!IS_ERR(kfilename)) {
1711		if (tvs) {
1712			if (get_tv32(&ktvs[0], tvs) ||
1713			    get_tv32(&ktvs[1], 1+tvs))
1714				return -EFAULT;
1715		}
1716
1717		old_fs = get_fs();
1718		set_fs(KERNEL_DS);
1719		ret = sys_utimes(kfilename, &ktvs[0]);
1720		set_fs(old_fs);
1721
1722		putname(kfilename);
1723	}
1724	return ret;
1725}
1726
1727/* These are here just in case some old ia32 binary calls it. */
1728asmlinkage long
1729sys32_pause(void)
1730{
1731	current->state = TASK_INTERRUPTIBLE;
1732	schedule();
1733	return -ERESTARTNOHAND;
1734}
1735
1736
1737struct sysctl_ia32 {
1738	unsigned int	name;
1739	int		nlen;
1740	unsigned int	oldval;
1741	unsigned int	oldlenp;
1742	unsigned int	newval;
1743	unsigned int	newlen;
1744	unsigned int	__unused[4];
1745};
1746
1747
1748asmlinkage long
1749sys32_sysctl(struct sysctl_ia32 *args32)
1750{
1751#ifndef CONFIG_SYSCTL
1752	return -ENOSYS;
1753#else
1754	struct sysctl_ia32 a32;
1755	mm_segment_t old_fs = get_fs ();
1756	void *oldvalp, *newvalp;
1757	size_t oldlen;
1758	int *namep;
1759	long ret;
1760	extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
1761		     void *newval, size_t newlen);
1762
1763
1764	if (copy_from_user(&a32, args32, sizeof (a32)))
1765		return -EFAULT;
1766
1767	/*
1768	 * We need to pre-validate these because we have to disable address checking
1769	 * before calling do_sysctl() because of OLDLEN but we can't run the risk of the
1770	 * user specifying bad addresses here.  Well, since we're dealing with 32 bit
1771	 * addresses, we KNOW that access_ok() will always succeed, so this is an
1772	 * expensive NOP, but so what...
1773	 */
1774	namep = (int *) A(a32.name);
1775	oldvalp = (void *) A(a32.oldval);
1776	newvalp = (void *) A(a32.newval);
1777
1778	if ((oldvalp && get_user(oldlen, (int *) A(a32.oldlenp)))
1779	    || !access_ok(VERIFY_WRITE, namep, 0)
1780	    || !access_ok(VERIFY_WRITE, oldvalp, 0)
1781	    || !access_ok(VERIFY_WRITE, newvalp, 0))
1782		return -EFAULT;
1783
1784	set_fs(KERNEL_DS);
1785	lock_kernel();
1786	ret = do_sysctl(namep, a32.nlen, oldvalp, &oldlen, newvalp, (size_t) a32.newlen);
1787	unlock_kernel();
1788	set_fs(old_fs);
1789
1790	if (oldvalp && put_user (oldlen, (int *) A(a32.oldlenp)))
1791		return -EFAULT;
1792
1793	return ret;
1794#endif
1795}
1796
1797extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
1798				    size_t count, loff_t pos);
1799
1800extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
1801				     size_t count, loff_t pos);
1802
1803typedef __kernel_ssize_t32 ssize_t32;
1804
1805
1806/* warning: next two assume little endian */
1807asmlinkage ssize_t32
1808sys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count,
1809	    u32 poslo, u32 poshi)
1810{
1811	return sys_pread(fd, ubuf, count,
1812			 ((loff_t)AA(poshi) << 32) | AA(poslo));
1813}
1814
1815asmlinkage ssize_t32
1816sys32_pwrite(unsigned int fd, char *ubuf, __kernel_size_t32 count,
1817	     u32 poslo, u32 poshi)
1818{
1819	return sys_pwrite(fd, ubuf, count,
1820			  ((loff_t)AA(poshi) << 32) | AA(poslo));
1821}
1822
1823
1824extern asmlinkage long sys_personality(unsigned long);
1825
1826asmlinkage long
1827sys32_personality(unsigned long personality)
1828{
1829	int ret;
1830	if (personality(current->personality) == PER_LINUX32 &&
1831		personality == PER_LINUX)
1832		personality = PER_LINUX32;
1833	ret = sys_personality(personality);
1834	if (ret == PER_LINUX32)
1835		ret = PER_LINUX;
1836	return ret;
1837}
1838
1839extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset,
1840				       size_t count);
1841
1842asmlinkage long
1843sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
1844{
1845	mm_segment_t old_fs = get_fs();
1846	int ret;
1847	off_t of;
1848
1849	if (offset && get_user(of, offset))
1850		return -EFAULT;
1851
1852	set_fs(KERNEL_DS);
1853	ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
1854	set_fs(old_fs);
1855
1856	if (!ret && offset && put_user(of, offset))
1857		return -EFAULT;
1858
1859	return ret;
1860}
1861
1862/* Handle adjtimex compatability. */
1863
1864struct timex32 {
1865	u32 modes;
1866	s32 offset, freq, maxerror, esterror;
1867	s32 status, constant, precision, tolerance;
1868	struct timeval32 time;
1869	s32 tick;
1870	s32 ppsfreq, jitter, shift, stabil;
1871	s32 jitcnt, calcnt, errcnt, stbcnt;
1872	s32  :32; s32  :32; s32  :32; s32  :32;
1873	s32  :32; s32  :32; s32  :32; s32  :32;
1874	s32  :32; s32  :32; s32  :32; s32  :32;
1875};
1876
1877extern int do_adjtimex(struct timex *);
1878
1879asmlinkage long
1880sys32_adjtimex(struct timex32 *utp)
1881{
1882	struct timex txc;
1883	int ret;
1884
1885	memset(&txc, 0, sizeof(struct timex));
1886
1887	if(verify_area(VERIFY_READ, utp, sizeof(struct timex32)) ||
1888	   __get_user(txc.modes, &utp->modes) ||
1889	   __get_user(txc.offset, &utp->offset) ||
1890	   __get_user(txc.freq, &utp->freq) ||
1891	   __get_user(txc.maxerror, &utp->maxerror) ||
1892	   __get_user(txc.esterror, &utp->esterror) ||
1893	   __get_user(txc.status, &utp->status) ||
1894	   __get_user(txc.constant, &utp->constant) ||
1895	   __get_user(txc.precision, &utp->precision) ||
1896	   __get_user(txc.tolerance, &utp->tolerance) ||
1897	   __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
1898	   __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
1899	   __get_user(txc.tick, &utp->tick) ||
1900	   __get_user(txc.ppsfreq, &utp->ppsfreq) ||
1901	   __get_user(txc.jitter, &utp->jitter) ||
1902	   __get_user(txc.shift, &utp->shift) ||
1903	   __get_user(txc.stabil, &utp->stabil) ||
1904	   __get_user(txc.jitcnt, &utp->jitcnt) ||
1905	   __get_user(txc.calcnt, &utp->calcnt) ||
1906	   __get_user(txc.errcnt, &utp->errcnt) ||
1907	   __get_user(txc.stbcnt, &utp->stbcnt))
1908		return -EFAULT;
1909
1910	ret = do_adjtimex(&txc);
1911
1912	if(verify_area(VERIFY_WRITE, utp, sizeof(struct timex32)) ||
1913	   __put_user(txc.modes, &utp->modes) ||
1914	   __put_user(txc.offset, &utp->offset) ||
1915	   __put_user(txc.freq, &utp->freq) ||
1916	   __put_user(txc.maxerror, &utp->maxerror) ||
1917	   __put_user(txc.esterror, &utp->esterror) ||
1918	   __put_user(txc.status, &utp->status) ||
1919	   __put_user(txc.constant, &utp->constant) ||
1920	   __put_user(txc.precision, &utp->precision) ||
1921	   __put_user(txc.tolerance, &utp->tolerance) ||
1922	   __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
1923	   __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
1924	   __put_user(txc.tick, &utp->tick) ||
1925	   __put_user(txc.ppsfreq, &utp->ppsfreq) ||
1926	   __put_user(txc.jitter, &utp->jitter) ||
1927	   __put_user(txc.shift, &utp->shift) ||
1928	   __put_user(txc.stabil, &utp->stabil) ||
1929	   __put_user(txc.jitcnt, &utp->jitcnt) ||
1930	   __put_user(txc.calcnt, &utp->calcnt) ||
1931	   __put_user(txc.errcnt, &utp->errcnt) ||
1932	   __put_user(txc.stbcnt, &utp->stbcnt))
1933		ret = -EFAULT;
1934
1935	return ret;
1936}
1937
1938
1939/* common code for old and new mmaps */
1940static inline long do_mmap2(
1941	unsigned long addr, unsigned long len,
1942	unsigned long prot, unsigned long flags,
1943	unsigned long fd, unsigned long pgoff)
1944{
1945	int error = -EBADF;
1946	struct file * file = NULL;
1947
1948	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
1949	if (!(flags & MAP_ANONYMOUS)) {
1950		file = fget(fd);
1951		if (!file)
1952			goto out;
1953	}
1954
1955	down_write(&current->mm->mmap_sem);
1956	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
1957	up_write(&current->mm->mmap_sem);
1958
1959	if (file)
1960		fput(file);
1961out:
1962	return error;
1963}
1964
1965asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len,
1966	unsigned long prot, unsigned long flags,
1967	unsigned long fd, unsigned long pgoff)
1968{
1969	return do_mmap2(addr, len, prot, flags, fd, pgoff);
1970}
1971
1972
1973asmlinkage long sys32_olduname(struct oldold_utsname * name)
1974{
1975	int error;
1976
1977	if (!name)
1978		return -EFAULT;
1979	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
1980		return -EFAULT;
1981
1982  	down_read(&uts_sem);
1983
1984	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
1985	 __put_user(0,name->sysname+__OLD_UTS_LEN);
1986	 __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
1987	 __put_user(0,name->nodename+__OLD_UTS_LEN);
1988	 __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
1989	 __put_user(0,name->release+__OLD_UTS_LEN);
1990	 __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
1991	 __put_user(0,name->version+__OLD_UTS_LEN);
1992	 {
1993		 char *arch = (personality(current->personality) == PER_LINUX32)
1994			 ? "i686" : "x86_64";
1995
1996		 __copy_to_user(&name->machine,arch,strlen(arch)+1);
1997	 }
1998
1999	 up_read(&uts_sem);
2000
2001	 error = error ? -EFAULT : 0;
2002
2003	 return error;
2004}
2005
2006asmlinkage long sys32_uname(struct old_utsname * name)
2007{
2008	int err;
2009	down_read(&uts_sem);
2010	err=copy_to_user(name, &system_utsname, sizeof (*name));
2011	up_read(&uts_sem);
2012	if (personality(current->personality) == PER_LINUX32)
2013		err = copy_to_user(name->machine, "i686", 5);
2014	return err?-EFAULT:0;
2015}
2016
2017extern int sys_ustat(dev_t, struct ustat *);
2018
2019int sys32_ustat(dev_t dev, struct ustat32 *u32p)
2020{
2021	struct ustat u;
2022	mm_segment_t seg;
2023	int ret;
2024
2025	seg = get_fs();
2026	set_fs(KERNEL_DS);
2027	ret = sys_ustat(dev,&u);
2028	set_fs(seg);
2029	if (ret >= 0) {
2030		if (!access_ok(VERIFY_WRITE,u32p,sizeof(struct ustat32)) ||
2031		    __put_user((__u32) u.f_tfree, &u32p->f_tfree) ||
2032		    __put_user((__u32) u.f_tinode, &u32p->f_tfree) ||
2033		    __copy_to_user(&u32p->f_fname, u.f_fname, sizeof(u.f_fname)) ||
2034		    __copy_to_user(&u32p->f_fpack, u.f_fpack, sizeof(u.f_fpack)))
2035			ret = -EFAULT;
2036	}
2037	return ret;
2038}
2039
2040static int nargs(u32 src, char **dst)
2041{
2042	int cnt;
2043	u32 val;
2044
2045	cnt = 0;
2046	do {
2047		int ret = get_user(val, (__u32 *)(u64)src);
2048		if (ret)
2049			return ret;
2050		if (dst)
2051			dst[cnt] = (char *)(u64)val;
2052		cnt++;
2053		src += 4;
2054		if (cnt >= (MAX_ARG_PAGES*PAGE_SIZE)/sizeof(void*))
2055			return -E2BIG;
2056	} while(val);
2057	if (dst)
2058		dst[cnt-1] = 0;
2059	return cnt;
2060}
2061
2062int sys32_execve(char *name, u32 argv, u32 envp, struct pt_regs regs)
2063{
2064	mm_segment_t oldseg;
2065	char **buf;
2066	int na,ne;
2067	int ret;
2068	unsigned sz;
2069
2070	na = nargs(argv, NULL);
2071	if (na < 0)
2072		return -EFAULT;
2073	ne = nargs(envp, NULL);
2074	if (ne < 0)
2075		return -EFAULT;
2076
2077	sz = (na+ne)*sizeof(void *);
2078	if (sz > PAGE_SIZE)
2079		buf = vmalloc(sz);
2080	else
2081		buf = kmalloc(sz, GFP_KERNEL);
2082	if (!buf)
2083		return -ENOMEM;
2084
2085	ret = nargs(argv, buf);
2086	if (ret < 0)
2087		goto free;
2088
2089	ret = nargs(envp, buf + na);
2090	if (ret < 0)
2091		goto free;
2092
2093	name = getname(name);
2094	ret = PTR_ERR(name);
2095	if (IS_ERR(name))
2096		goto free;
2097
2098	oldseg = get_fs();
2099	set_fs(KERNEL_DS);
2100	ret = do_execve(name, buf, buf+na, &regs);
2101	set_fs(oldseg);
2102
2103	if (ret == 0)
2104		current->ptrace &= ~PT_DTRACE;
2105
2106	putname(name);
2107
2108free:
2109	if (sz > PAGE_SIZE)
2110		vfree(buf);
2111	else
2112		kfree(buf);
2113	return ret;
2114}
2115
2116asmlinkage int sys32_fork(struct pt_regs regs)
2117{
2118	return do_fork(SIGCHLD, regs.rsp, &regs, 0);
2119}
2120
2121asmlinkage int sys32_clone(unsigned int clone_flags, unsigned int newsp, struct pt_regs regs)
2122{
2123	if (!newsp)
2124		newsp = regs.rsp;
2125	return do_fork(clone_flags, newsp, &regs, 0);
2126}
2127
2128/*
2129 * This is trivial, and on the face of it looks like it
2130 * could equally well be done in user mode.
2131 *
2132 * Not so, for quite unobvious reasons - register pressure.
2133 * In user mode vfork() cannot have a stack frame, and if
2134 * done by calling the "clone()" system call directly, you
2135 * do not have enough call-clobbered registers to hold all
2136 * the information you need.
2137 */
2138asmlinkage int sys32_vfork(struct pt_regs regs)
2139{
2140	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, &regs, 0);
2141}
2142
2143/*
2144 * Some system calls that need sign extended arguments. This could be done by a generic wrapper.
2145 */
2146
2147extern off_t sys_lseek (unsigned int fd, off_t offset, unsigned int origin);
2148
2149int sys32_lseek (unsigned int fd, int offset, unsigned int whence)
2150{
2151	return sys_lseek(fd, offset, whence);
2152}
2153
2154extern int sys_kill(pid_t pid, int sig);
2155
2156int sys32_kill(int pid, int sig)
2157{
2158	return sys_kill(pid, sig);
2159}
2160
2161
2162#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
2163/* Stuff for NFS server syscalls... */
2164struct nfsctl_svc32 {
2165	u16			svc32_port;
2166	s32			svc32_nthreads;
2167};
2168
2169struct nfsctl_client32 {
2170	s8			cl32_ident[NFSCLNT_IDMAX+1];
2171	s32			cl32_naddr;
2172	struct in_addr		cl32_addrlist[NFSCLNT_ADDRMAX];
2173	s32			cl32_fhkeytype;
2174	s32			cl32_fhkeylen;
2175	u8			cl32_fhkey[NFSCLNT_KEYMAX];
2176};
2177
2178struct nfsctl_export32 {
2179	s8			ex32_client[NFSCLNT_IDMAX+1];
2180	s8			ex32_path[NFS_MAXPATHLEN+1];
2181	__kernel_dev_t32	ex32_dev;
2182	__kernel_ino_t32	ex32_ino;
2183	s32			ex32_flags;
2184	__kernel_uid_t32	ex32_anon_uid;
2185	__kernel_gid_t32	ex32_anon_gid;
2186};
2187
2188struct nfsctl_uidmap32 {
2189	u32			ug32_ident;   /* char * */
2190	__kernel_uid_t32	ug32_uidbase;
2191	s32			ug32_uidlen;
2192	u32			ug32_udimap;  /* uid_t * */
2193	__kernel_uid_t32	ug32_gidbase;
2194	s32			ug32_gidlen;
2195	u32			ug32_gdimap;  /* gid_t * */
2196};
2197
2198struct nfsctl_fhparm32 {
2199	struct sockaddr		gf32_addr;
2200	__kernel_dev_t32	gf32_dev;
2201	__kernel_ino_t32	gf32_ino;
2202	s32			gf32_version;
2203};
2204
2205struct nfsctl_fdparm32 {
2206	struct sockaddr		gd32_addr;
2207	s8			gd32_path[NFS_MAXPATHLEN+1];
2208	s32			gd32_version;
2209};
2210
2211struct nfsctl_fsparm32 {
2212	struct sockaddr		gd32_addr;
2213	s8			gd32_path[NFS_MAXPATHLEN+1];
2214	s32			gd32_maxlen;
2215};
2216
2217struct nfsctl_arg32 {
2218	s32			ca32_version;	/* safeguard */
2219	union {
2220		struct nfsctl_svc32	u32_svc;
2221		struct nfsctl_client32	u32_client;
2222		struct nfsctl_export32	u32_export;
2223		struct nfsctl_uidmap32	u32_umap;
2224		struct nfsctl_fhparm32	u32_getfh;
2225		struct nfsctl_fdparm32	u32_getfd;
2226		struct nfsctl_fsparm32	u32_getfs;
2227	} u;
2228#define ca32_svc	u.u32_svc
2229#define ca32_client	u.u32_client
2230#define ca32_export	u.u32_export
2231#define ca32_umap	u.u32_umap
2232#define ca32_getfh	u.u32_getfh
2233#define ca32_getfd	u.u32_getfd
2234#define ca32_getfs	u.u32_getfs
2235#define ca32_authd	u.u32_authd
2236};
2237
2238union nfsctl_res32 {
2239	__u8			cr32_getfh[NFS_FHSIZE];
2240	struct knfsd_fh		cr32_getfs;
2241};
2242
2243static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
2244{
2245	int err;
2246
2247	err = get_user(karg->ca_version, &arg32->ca32_version);
2248	err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
2249	err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
2250	return err;
2251}
2252
2253static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
2254{
2255	int err;
2256
2257	err = get_user(karg->ca_version, &arg32->ca32_version);
2258	err |= copy_from_user(&karg->ca_client.cl_ident[0],
2259			  &arg32->ca32_client.cl32_ident[0],
2260			  NFSCLNT_IDMAX);
2261	err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
2262	err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
2263			  &arg32->ca32_client.cl32_addrlist[0],
2264			  (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
2265	err |= __get_user(karg->ca_client.cl_fhkeytype,
2266		      &arg32->ca32_client.cl32_fhkeytype);
2267	err |= __get_user(karg->ca_client.cl_fhkeylen,
2268		      &arg32->ca32_client.cl32_fhkeylen);
2269	err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
2270			  &arg32->ca32_client.cl32_fhkey[0],
2271			  NFSCLNT_KEYMAX);
2272	return err;
2273}
2274
2275static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
2276{
2277	int err;
2278
2279	err = get_user(karg->ca_version, &arg32->ca32_version);
2280	err |= copy_from_user(&karg->ca_export.ex_client[0],
2281			  &arg32->ca32_export.ex32_client[0],
2282			  NFSCLNT_IDMAX);
2283	err |= copy_from_user(&karg->ca_export.ex_path[0],
2284			  &arg32->ca32_export.ex32_path[0],
2285			  NFS_MAXPATHLEN);
2286	err |= __get_user(karg->ca_export.ex_dev,
2287		      &arg32->ca32_export.ex32_dev);
2288	err |= __get_user(karg->ca_export.ex_ino,
2289		      &arg32->ca32_export.ex32_ino);
2290	err |= __get_user(karg->ca_export.ex_flags,
2291		      &arg32->ca32_export.ex32_flags);
2292	err |= __get_user(karg->ca_export.ex_anon_uid,
2293		      &arg32->ca32_export.ex32_anon_uid);
2294	err |= __get_user(karg->ca_export.ex_anon_gid,
2295		      &arg32->ca32_export.ex32_anon_gid);
2296	karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
2297	karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
2298	return err;
2299}
2300
2301static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
2302{
2303	u32 uaddr;
2304	int i;
2305	int err;
2306
2307	memset(karg, 0, sizeof(*karg));
2308	if(get_user(karg->ca_version, &arg32->ca32_version))
2309		return -EFAULT;
2310	karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
2311	if(!karg->ca_umap.ug_ident)
2312		return -ENOMEM;
2313	err = get_user(uaddr, &arg32->ca32_umap.ug32_ident);
2314	if(strncpy_from_user(karg->ca_umap.ug_ident,
2315			     (char *)A(uaddr), PAGE_SIZE) <= 0)
2316		return -EFAULT;
2317	err |= __get_user(karg->ca_umap.ug_uidbase,
2318		      &arg32->ca32_umap.ug32_uidbase);
2319	err |= __get_user(karg->ca_umap.ug_uidlen,
2320		      &arg32->ca32_umap.ug32_uidlen);
2321	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
2322	if (err)
2323		return -EFAULT;
2324	karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
2325					  GFP_USER);
2326	if(!karg->ca_umap.ug_udimap)
2327		return -ENOMEM;
2328	for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
2329		err |= __get_user(karg->ca_umap.ug_udimap[i],
2330			      &(((__kernel_uid_t32 *)A(uaddr))[i]));
2331	err |= __get_user(karg->ca_umap.ug_gidbase,
2332		      &arg32->ca32_umap.ug32_gidbase);
2333	err |= __get_user(karg->ca_umap.ug_uidlen,
2334		      &arg32->ca32_umap.ug32_gidlen);
2335	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
2336	if (err)
2337		return -EFAULT;
2338	karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
2339					  GFP_USER);
2340	if(!karg->ca_umap.ug_gdimap)
2341		return -ENOMEM;
2342	for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
2343		err |= __get_user(karg->ca_umap.ug_gdimap[i],
2344			      &(((__kernel_gid_t32 *)A(uaddr))[i]));
2345
2346	return err;
2347}
2348
2349static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
2350{
2351	int err;
2352
2353	err = get_user(karg->ca_version, &arg32->ca32_version);
2354	err |= copy_from_user(&karg->ca_getfh.gf_addr,
2355			  &arg32->ca32_getfh.gf32_addr,
2356			  (sizeof(struct sockaddr)));
2357	err |= __get_user(karg->ca_getfh.gf_dev,
2358		      &arg32->ca32_getfh.gf32_dev);
2359	err |= __get_user(karg->ca_getfh.gf_ino,
2360		      &arg32->ca32_getfh.gf32_ino);
2361	err |= __get_user(karg->ca_getfh.gf_version,
2362		      &arg32->ca32_getfh.gf32_version);
2363	return err;
2364}
2365
2366static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
2367{
2368	int err;
2369
2370	err = get_user(karg->ca_version, &arg32->ca32_version);
2371	err |= copy_from_user(&karg->ca_getfd.gd_addr,
2372			  &arg32->ca32_getfd.gd32_addr,
2373			  (sizeof(struct sockaddr)));
2374	err |= copy_from_user(&karg->ca_getfd.gd_path,
2375			  &arg32->ca32_getfd.gd32_path,
2376			  (NFS_MAXPATHLEN+1));
2377	err |= get_user(karg->ca_getfd.gd_version,
2378		      &arg32->ca32_getfd.gd32_version);
2379	return err;
2380}
2381
2382static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
2383{
2384	int err;
2385
2386	err = get_user(karg->ca_version, &arg32->ca32_version);
2387	err |= copy_from_user(&karg->ca_getfs.gd_addr,
2388			  &arg32->ca32_getfs.gd32_addr,
2389			  (sizeof(struct sockaddr)));
2390	err |= copy_from_user(&karg->ca_getfs.gd_path,
2391			  &arg32->ca32_getfs.gd32_path,
2392			  (NFS_MAXPATHLEN+1));
2393	err |= get_user(karg->ca_getfs.gd_maxlen,
2394		      &arg32->ca32_getfs.gd32_maxlen);
2395	return err;
2396}
2397
2398/* This really doesn't need translations, we are only passing
2399 * back a union which contains opaque nfs file handle data.
2400 */
2401static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
2402{
2403	return copy_to_user(res32, kres, sizeof(*res32));
2404}
2405
2406int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
2407{
2408	struct nfsctl_arg *karg = NULL;
2409	union nfsctl_res *kres = NULL;
2410	mm_segment_t oldfs;
2411	int err;
2412
2413	karg = kmalloc(sizeof(*karg), GFP_USER);
2414	if(!karg)
2415		return -ENOMEM;
2416	if(res32) {
2417		kres = kmalloc(sizeof(*kres), GFP_USER);
2418		if(!kres) {
2419			kfree(karg);
2420			return -ENOMEM;
2421		}
2422	}
2423	switch(cmd) {
2424	case NFSCTL_SVC:
2425		err = nfs_svc32_trans(karg, arg32);
2426		break;
2427	case NFSCTL_ADDCLIENT:
2428		err = nfs_clnt32_trans(karg, arg32);
2429		break;
2430	case NFSCTL_DELCLIENT:
2431		err = nfs_clnt32_trans(karg, arg32);
2432		break;
2433	case NFSCTL_EXPORT:
2434	case NFSCTL_UNEXPORT:
2435		err = nfs_exp32_trans(karg, arg32);
2436		break;
2437	/* This one is unimplemented, be we're ready for it. */
2438	case NFSCTL_UGIDUPDATE:
2439		err = nfs_uud32_trans(karg, arg32);
2440		break;
2441	case NFSCTL_GETFH:
2442		err = nfs_getfh32_trans(karg, arg32);
2443		break;
2444	case NFSCTL_GETFD:
2445		err = nfs_getfd32_trans(karg, arg32);
2446		break;
2447	case NFSCTL_GETFS:
2448		err = nfs_getfs32_trans(karg, arg32);
2449		break;
2450	default:
2451		err = -EINVAL;
2452		break;
2453	}
2454	if(err)
2455		goto done;
2456	oldfs = get_fs();
2457	set_fs(KERNEL_DS);
2458	err = sys_nfsservctl(cmd, karg, kres);
2459	set_fs(oldfs);
2460
2461	if (err)
2462		goto done;
2463
2464	if((cmd == NFSCTL_GETFH) ||
2465	   (cmd == NFSCTL_GETFD) ||
2466	   (cmd == NFSCTL_GETFS))
2467		err = nfs_getfh32_res_trans(kres, res32);
2468
2469done:
2470	if(karg) {
2471		if(cmd == NFSCTL_UGIDUPDATE) {
2472			if(karg->ca_umap.ug_ident)
2473				kfree(karg->ca_umap.ug_ident);
2474			if(karg->ca_umap.ug_udimap)
2475				kfree(karg->ca_umap.ug_udimap);
2476			if(karg->ca_umap.ug_gdimap)
2477				kfree(karg->ca_umap.ug_gdimap);
2478		}
2479		kfree(karg);
2480	}
2481	if(kres)
2482		kfree(kres);
2483	return err;
2484}
2485#else /* !NFSD */
2486extern asmlinkage long sys_ni_syscall(void);
2487int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
2488{
2489	return sys_ni_syscall();
2490}
2491#endif
2492
2493int sys32_module_warning(void)
2494{
2495	static long warn_time = -(60*HZ);
2496	if (time_before(warn_time + 60*HZ,jiffies) && strcmp(current->comm,"klogd")) {
2497		printk(KERN_INFO "%s: 32bit modutils not supported on 64bit kernel\n",
2498		       current->comm);
2499		warn_time = jiffies;
2500	}
2501	return -ENOSYS ;
2502}
2503
2504struct exec_domain ia32_exec_domain = {
2505	name: "linux/x86",
2506	pers_low: PER_LINUX32,
2507	pers_high: PER_LINUX32,
2508};
2509
2510static int __init ia32_init (void)
2511{
2512	printk("IA32 emulation $Id: sys_ia32.c,v 1.1.1.1 2008/10/15 03:26:20 james26_jang Exp $\n");
2513	ia32_exec_domain.signal_map = default_exec_domain.signal_map;
2514	ia32_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
2515	register_exec_domain(&ia32_exec_domain);
2516	return 0;
2517}
2518
2519__initcall(ia32_init);
2520