085a8c35f149423b75b5c83bd7a75bdd02acbae1
[linux-2.6.git] / arch / x86 / ia32 / sys_ia32.c
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,2002 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  *
19  * Some of the functions are LE specific currently. These are
20  * hopefully all marked.  This should be fixed.
21  */
22
23 #include <linux/kernel.h>
24 #include <linux/sched.h>
25 #include <linux/fs.h>
26 #include <linux/file.h>
27 #include <linux/signal.h>
28 #include <linux/syscalls.h>
29 #include <linux/times.h>
30 #include <linux/utsname.h>
31 #include <linux/smp_lock.h>
32 #include <linux/mm.h>
33 #include <linux/uio.h>
34 #include <linux/poll.h>
35 #include <linux/personality.h>
36 #include <linux/stat.h>
37 #include <linux/rwsem.h>
38 #include <linux/compat.h>
39 #include <linux/vfs.h>
40 #include <linux/ptrace.h>
41 #include <linux/highuid.h>
42 #include <linux/sysctl.h>
43 #include <asm/mman.h>
44 #include <asm/types.h>
45 #include <asm/uaccess.h>
46 #include <asm/atomic.h>
47 #include <asm/vgtod.h>
48 #include <asm/sys_ia32.h>
49
50 #define AA(__x)         ((unsigned long)(__x))
51
52
53 asmlinkage long sys32_truncate64(char __user *filename,
54                                  unsigned long offset_low,
55                                  unsigned long offset_high)
56 {
57        return sys_truncate(filename, ((loff_t) offset_high << 32) | offset_low);
58 }
59
60 asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long offset_low,
61                                   unsigned long offset_high)
62 {
63        return sys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low);
64 }
65
66 /*
67  * Another set for IA32/LFS -- x86_64 struct stat is different due to
68  * support for 64bit inode numbers.
69  */
70 static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat)
71 {
72         typeof(ubuf->st_uid) uid = 0;
73         typeof(ubuf->st_gid) gid = 0;
74         SET_UID(uid, stat->uid);
75         SET_GID(gid, stat->gid);
76         if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64)) ||
77             __put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) ||
78             __put_user(stat->ino, &ubuf->__st_ino) ||
79             __put_user(stat->ino, &ubuf->st_ino) ||
80             __put_user(stat->mode, &ubuf->st_mode) ||
81             __put_user(stat->nlink, &ubuf->st_nlink) ||
82             __put_user(uid, &ubuf->st_uid) ||
83             __put_user(gid, &ubuf->st_gid) ||
84             __put_user(huge_encode_dev(stat->rdev), &ubuf->st_rdev) ||
85             __put_user(stat->size, &ubuf->st_size) ||
86             __put_user(stat->atime.tv_sec, &ubuf->st_atime) ||
87             __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec) ||
88             __put_user(stat->mtime.tv_sec, &ubuf->st_mtime) ||
89             __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec) ||
90             __put_user(stat->ctime.tv_sec, &ubuf->st_ctime) ||
91             __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec) ||
92             __put_user(stat->blksize, &ubuf->st_blksize) ||
93             __put_user(stat->blocks, &ubuf->st_blocks))
94                 return -EFAULT;
95         return 0;
96 }
97
98 asmlinkage long sys32_stat64(char __user *filename,
99                              struct stat64 __user *statbuf)
100 {
101         struct kstat stat;
102         int ret = vfs_stat(filename, &stat);
103
104         if (!ret)
105                 ret = cp_stat64(statbuf, &stat);
106         return ret;
107 }
108
109 asmlinkage long sys32_lstat64(char __user *filename,
110                               struct stat64 __user *statbuf)
111 {
112         struct kstat stat;
113         int ret = vfs_lstat(filename, &stat);
114         if (!ret)
115                 ret = cp_stat64(statbuf, &stat);
116         return ret;
117 }
118
119 asmlinkage long sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf)
120 {
121         struct kstat stat;
122         int ret = vfs_fstat(fd, &stat);
123         if (!ret)
124                 ret = cp_stat64(statbuf, &stat);
125         return ret;
126 }
127
128 asmlinkage long sys32_fstatat(unsigned int dfd, char __user *filename,
129                               struct stat64 __user *statbuf, int flag)
130 {
131         struct kstat stat;
132         int error;
133
134         error = vfs_fstatat(dfd, filename, &stat, flag);
135         if (error)
136                 return error;
137         return cp_stat64(statbuf, &stat);
138 }
139
140 /*
141  * Linux/i386 didn't use to be able to handle more than
142  * 4 system call parameters, so these system calls used a memory
143  * block for parameter passing..
144  */
145
146 struct mmap_arg_struct {
147         unsigned int addr;
148         unsigned int len;
149         unsigned int prot;
150         unsigned int flags;
151         unsigned int fd;
152         unsigned int offset;
153 };
154
155 asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg)
156 {
157         struct mmap_arg_struct a;
158         struct file *file = NULL;
159         unsigned long retval;
160         struct mm_struct *mm ;
161
162         if (copy_from_user(&a, arg, sizeof(a)))
163                 return -EFAULT;
164
165         if (a.offset & ~PAGE_MASK)
166                 return -EINVAL;
167
168         if (!(a.flags & MAP_ANONYMOUS)) {
169                 file = fget(a.fd);
170                 if (!file)
171                         return -EBADF;
172         }
173
174         mm = current->mm;
175         down_write(&mm->mmap_sem);
176         retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags,
177                                a.offset>>PAGE_SHIFT);
178         if (file)
179                 fput(file);
180
181         up_write(&mm->mmap_sem);
182
183         return retval;
184 }
185
186 asmlinkage long sys32_mprotect(unsigned long start, size_t len,
187                                unsigned long prot)
188 {
189         return sys_mprotect(start, len, prot);
190 }
191
192 asmlinkage long sys32_pipe(int __user *fd)
193 {
194         int retval;
195         int fds[2];
196
197         retval = do_pipe_flags(fds, 0);
198         if (retval)
199                 goto out;
200         if (copy_to_user(fd, fds, sizeof(fds)))
201                 retval = -EFAULT;
202 out:
203         return retval;
204 }
205
206 asmlinkage long sys32_rt_sigaction(int sig, struct sigaction32 __user *act,
207                                    struct sigaction32 __user *oact,
208                                    unsigned int sigsetsize)
209 {
210         struct k_sigaction new_ka, old_ka;
211         int ret;
212         compat_sigset_t set32;
213
214         /* XXX: Don't preclude handling different sized sigset_t's.  */
215         if (sigsetsize != sizeof(compat_sigset_t))
216                 return -EINVAL;
217
218         if (act) {
219                 compat_uptr_t handler, restorer;
220
221                 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
222                     __get_user(handler, &act->sa_handler) ||
223                     __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
224                     __get_user(restorer, &act->sa_restorer) ||
225                     __copy_from_user(&set32, &act->sa_mask,
226                                      sizeof(compat_sigset_t)))
227                         return -EFAULT;
228                 new_ka.sa.sa_handler = compat_ptr(handler);
229                 new_ka.sa.sa_restorer = compat_ptr(restorer);
230
231                 /*
232                  * FIXME: here we rely on _COMPAT_NSIG_WORS to be >=
233                  * than _NSIG_WORDS << 1
234                  */
235                 switch (_NSIG_WORDS) {
236                 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
237                                 | (((long)set32.sig[7]) << 32);
238                 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
239                                 | (((long)set32.sig[5]) << 32);
240                 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
241                                 | (((long)set32.sig[3]) << 32);
242                 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
243                                 | (((long)set32.sig[1]) << 32);
244                 }
245         }
246
247         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
248
249         if (!ret && oact) {
250                 /*
251                  * FIXME: here we rely on _COMPAT_NSIG_WORS to be >=
252                  * than _NSIG_WORDS << 1
253                  */
254                 switch (_NSIG_WORDS) {
255                 case 4:
256                         set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
257                         set32.sig[6] = old_ka.sa.sa_mask.sig[3];
258                 case 3:
259                         set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
260                         set32.sig[4] = old_ka.sa.sa_mask.sig[2];
261                 case 2:
262                         set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
263                         set32.sig[2] = old_ka.sa.sa_mask.sig[1];
264                 case 1:
265                         set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
266                         set32.sig[0] = old_ka.sa.sa_mask.sig[0];
267                 }
268                 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
269                     __put_user(ptr_to_compat(old_ka.sa.sa_handler),
270                                &oact->sa_handler) ||
271                     __put_user(ptr_to_compat(old_ka.sa.sa_restorer),
272                                &oact->sa_restorer) ||
273                     __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
274                     __copy_to_user(&oact->sa_mask, &set32,
275                                    sizeof(compat_sigset_t)))
276                         return -EFAULT;
277         }
278
279         return ret;
280 }
281
282 asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 __user *act,
283                                 struct old_sigaction32 __user *oact)
284 {
285         struct k_sigaction new_ka, old_ka;
286         int ret;
287
288         if (act) {
289                 compat_old_sigset_t mask;
290                 compat_uptr_t handler, restorer;
291
292                 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
293                     __get_user(handler, &act->sa_handler) ||
294                     __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
295                     __get_user(restorer, &act->sa_restorer) ||
296                     __get_user(mask, &act->sa_mask))
297                         return -EFAULT;
298
299                 new_ka.sa.sa_handler = compat_ptr(handler);
300                 new_ka.sa.sa_restorer = compat_ptr(restorer);
301
302                 siginitset(&new_ka.sa.sa_mask, mask);
303         }
304
305         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
306
307         if (!ret && oact) {
308                 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
309                     __put_user(ptr_to_compat(old_ka.sa.sa_handler),
310                                &oact->sa_handler) ||
311                     __put_user(ptr_to_compat(old_ka.sa.sa_restorer),
312                                &oact->sa_restorer) ||
313                     __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
314                     __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
315                         return -EFAULT;
316         }
317
318         return ret;
319 }
320
321 asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
322                                      compat_sigset_t __user *oset,
323                                      unsigned int sigsetsize)
324 {
325         sigset_t s;
326         compat_sigset_t s32;
327         int ret;
328         mm_segment_t old_fs = get_fs();
329
330         if (set) {
331                 if (copy_from_user(&s32, set, sizeof(compat_sigset_t)))
332                         return -EFAULT;
333                 switch (_NSIG_WORDS) {
334                 case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
335                 case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
336                 case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
337                 case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
338                 }
339         }
340         set_fs(KERNEL_DS);
341         ret = sys_rt_sigprocmask(how,
342                                  set ? (sigset_t __user *)&s : NULL,
343                                  oset ? (sigset_t __user *)&s : NULL,
344                                  sigsetsize);
345         set_fs(old_fs);
346         if (ret)
347                 return ret;
348         if (oset) {
349                 switch (_NSIG_WORDS) {
350                 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
351                 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
352                 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
353                 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
354                 }
355                 if (copy_to_user(oset, &s32, sizeof(compat_sigset_t)))
356                         return -EFAULT;
357         }
358         return 0;
359 }
360
361 asmlinkage long sys32_alarm(unsigned int seconds)
362 {
363         return alarm_setitimer(seconds);
364 }
365
366 struct sel_arg_struct {
367         unsigned int n;
368         unsigned int inp;
369         unsigned int outp;
370         unsigned int exp;
371         unsigned int tvp;
372 };
373
374 asmlinkage long sys32_old_select(struct sel_arg_struct __user *arg)
375 {
376         struct sel_arg_struct a;
377
378         if (copy_from_user(&a, arg, sizeof(a)))
379                 return -EFAULT;
380         return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp),
381                                  compat_ptr(a.exp), compat_ptr(a.tvp));
382 }
383
384 asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr,
385                               int options)
386 {
387         return compat_sys_wait4(pid, stat_addr, options, NULL);
388 }
389
390 /* 32-bit timeval and related flotsam.  */
391
392 asmlinkage long sys32_sysfs(int option, u32 arg1, u32 arg2)
393 {
394         return sys_sysfs(option, arg1, arg2);
395 }
396
397 asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid,
398                                     struct compat_timespec __user *interval)
399 {
400         struct timespec t;
401         int ret;
402         mm_segment_t old_fs = get_fs();
403
404         set_fs(KERNEL_DS);
405         ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
406         set_fs(old_fs);
407         if (put_compat_timespec(&t, interval))
408                 return -EFAULT;
409         return ret;
410 }
411
412 asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
413                                     compat_size_t sigsetsize)
414 {
415         sigset_t s;
416         compat_sigset_t s32;
417         int ret;
418         mm_segment_t old_fs = get_fs();
419
420         set_fs(KERNEL_DS);
421         ret = sys_rt_sigpending((sigset_t __user *)&s, sigsetsize);
422         set_fs(old_fs);
423         if (!ret) {
424                 switch (_NSIG_WORDS) {
425                 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
426                 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
427                 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
428                 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
429                 }
430                 if (copy_to_user(set, &s32, sizeof(compat_sigset_t)))
431                         return -EFAULT;
432         }
433         return ret;
434 }
435
436 asmlinkage long sys32_rt_sigqueueinfo(int pid, int sig,
437                                       compat_siginfo_t __user *uinfo)
438 {
439         siginfo_t info;
440         int ret;
441         mm_segment_t old_fs = get_fs();
442
443         if (copy_siginfo_from_user32(&info, uinfo))
444                 return -EFAULT;
445         set_fs(KERNEL_DS);
446         ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
447         set_fs(old_fs);
448         return ret;
449 }
450
451 #ifdef CONFIG_SYSCTL_SYSCALL
452 struct sysctl_ia32 {
453         unsigned int    name;
454         int             nlen;
455         unsigned int    oldval;
456         unsigned int    oldlenp;
457         unsigned int    newval;
458         unsigned int    newlen;
459         unsigned int    __unused[4];
460 };
461
462
463 asmlinkage long sys32_sysctl(struct sysctl_ia32 __user *args32)
464 {
465         struct sysctl_ia32 a32;
466         mm_segment_t old_fs = get_fs();
467         void __user *oldvalp, *newvalp;
468         size_t oldlen;
469         int __user *namep;
470         long ret;
471
472         if (copy_from_user(&a32, args32, sizeof(a32)))
473                 return -EFAULT;
474
475         /*
476          * We need to pre-validate these because we have to disable
477          * address checking before calling do_sysctl() because of
478          * OLDLEN but we can't run the risk of the user specifying bad
479          * addresses here.  Well, since we're dealing with 32 bit
480          * addresses, we KNOW that access_ok() will always succeed, so
481          * this is an expensive NOP, but so what...
482          */
483         namep = compat_ptr(a32.name);
484         oldvalp = compat_ptr(a32.oldval);
485         newvalp =  compat_ptr(a32.newval);
486
487         if ((oldvalp && get_user(oldlen, (int __user *)compat_ptr(a32.oldlenp)))
488             || !access_ok(VERIFY_WRITE, namep, 0)
489             || !access_ok(VERIFY_WRITE, oldvalp, 0)
490             || !access_ok(VERIFY_WRITE, newvalp, 0))
491                 return -EFAULT;
492
493         set_fs(KERNEL_DS);
494         lock_kernel();
495         ret = do_sysctl(namep, a32.nlen, oldvalp, (size_t __user *)&oldlen,
496                         newvalp, (size_t) a32.newlen);
497         unlock_kernel();
498         set_fs(old_fs);
499
500         if (oldvalp && put_user(oldlen, (int __user *)compat_ptr(a32.oldlenp)))
501                 return -EFAULT;
502
503         return ret;
504 }
505 #endif
506
507 /* warning: next two assume little endian */
508 asmlinkage long sys32_pread(unsigned int fd, char __user *ubuf, u32 count,
509                             u32 poslo, u32 poshi)
510 {
511         return sys_pread64(fd, ubuf, count,
512                          ((loff_t)AA(poshi) << 32) | AA(poslo));
513 }
514
515 asmlinkage long sys32_pwrite(unsigned int fd, char __user *ubuf, u32 count,
516                              u32 poslo, u32 poshi)
517 {
518         return sys_pwrite64(fd, ubuf, count,
519                           ((loff_t)AA(poshi) << 32) | AA(poslo));
520 }
521
522
523 asmlinkage long sys32_personality(unsigned long personality)
524 {
525         int ret;
526
527         if (personality(current->personality) == PER_LINUX32 &&
528                 personality == PER_LINUX)
529                 personality = PER_LINUX32;
530         ret = sys_personality(personality);
531         if (ret == PER_LINUX32)
532                 ret = PER_LINUX;
533         return ret;
534 }
535
536 asmlinkage long sys32_sendfile(int out_fd, int in_fd,
537                                compat_off_t __user *offset, s32 count)
538 {
539         mm_segment_t old_fs = get_fs();
540         int ret;
541         off_t of;
542
543         if (offset && get_user(of, offset))
544                 return -EFAULT;
545
546         set_fs(KERNEL_DS);
547         ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL,
548                            count);
549         set_fs(old_fs);
550
551         if (offset && put_user(of, offset))
552                 return -EFAULT;
553         return ret;
554 }
555
556 asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len,
557                             unsigned long prot, unsigned long flags,
558                             unsigned long fd, unsigned long pgoff)
559 {
560         struct mm_struct *mm = current->mm;
561         unsigned long error;
562         struct file *file = NULL;
563
564         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
565         if (!(flags & MAP_ANONYMOUS)) {
566                 file = fget(fd);
567                 if (!file)
568                         return -EBADF;
569         }
570
571         down_write(&mm->mmap_sem);
572         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
573         up_write(&mm->mmap_sem);
574
575         if (file)
576                 fput(file);
577         return error;
578 }
579
580 asmlinkage long sys32_olduname(struct oldold_utsname __user *name)
581 {
582         char *arch = "x86_64";
583         int err;
584
585         if (!name)
586                 return -EFAULT;
587         if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
588                 return -EFAULT;
589
590         down_read(&uts_sem);
591
592         err = __copy_to_user(&name->sysname, &utsname()->sysname,
593                              __OLD_UTS_LEN);
594         err |= __put_user(0, name->sysname+__OLD_UTS_LEN);
595         err |= __copy_to_user(&name->nodename, &utsname()->nodename,
596                               __OLD_UTS_LEN);
597         err |= __put_user(0, name->nodename+__OLD_UTS_LEN);
598         err |= __copy_to_user(&name->release, &utsname()->release,
599                               __OLD_UTS_LEN);
600         err |= __put_user(0, name->release+__OLD_UTS_LEN);
601         err |= __copy_to_user(&name->version, &utsname()->version,
602                               __OLD_UTS_LEN);
603         err |= __put_user(0, name->version+__OLD_UTS_LEN);
604
605         if (personality(current->personality) == PER_LINUX32)
606                 arch = "i686";
607
608         err |= __copy_to_user(&name->machine, arch, strlen(arch) + 1);
609
610         up_read(&uts_sem);
611
612         err = err ? -EFAULT : 0;
613
614         return err;
615 }
616
617 long sys32_uname(struct old_utsname __user *name)
618 {
619         int err;
620
621         if (!name)
622                 return -EFAULT;
623         down_read(&uts_sem);
624         err = copy_to_user(name, utsname(), sizeof(*name));
625         up_read(&uts_sem);
626         if (personality(current->personality) == PER_LINUX32)
627                 err |= copy_to_user(&name->machine, "i686", 5);
628
629         return err ? -EFAULT : 0;
630 }
631
632 asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
633                              compat_uptr_t __user *envp, struct pt_regs *regs)
634 {
635         long error;
636         char *filename;
637
638         filename = getname(name);
639         error = PTR_ERR(filename);
640         if (IS_ERR(filename))
641                 return error;
642         error = compat_do_execve(filename, argv, envp, regs);
643         putname(filename);
644         return error;
645 }
646
647 asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
648                             struct pt_regs *regs)
649 {
650         void __user *parent_tid = (void __user *)regs->dx;
651         void __user *child_tid = (void __user *)regs->di;
652
653         if (!newsp)
654                 newsp = regs->sp;
655         return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
656 }
657
658 /*
659  * Some system calls that need sign extended arguments. This could be
660  * done by a generic wrapper.
661  */
662 long sys32_lseek(unsigned int fd, int offset, unsigned int whence)
663 {
664         return sys_lseek(fd, offset, whence);
665 }
666
667 long sys32_kill(int pid, int sig)
668 {
669         return sys_kill(pid, sig);
670 }
671
672 long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high,
673                         __u32 len_low, __u32 len_high, int advice)
674 {
675         return sys_fadvise64_64(fd,
676                                (((u64)offset_high)<<32) | offset_low,
677                                (((u64)len_high)<<32) | len_low,
678                                 advice);
679 }
680
681 long sys32_vm86_warning(void)
682 {
683         struct task_struct *me = current;
684         static char lastcomm[sizeof(me->comm)];
685
686         if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) {
687                 compat_printk(KERN_INFO
688                               "%s: vm86 mode not supported on 64 bit kernel\n",
689                               me->comm);
690                 strncpy(lastcomm, me->comm, sizeof(lastcomm));
691         }
692         return -ENOSYS;
693 }
694
695 long sys32_lookup_dcookie(u32 addr_low, u32 addr_high,
696                           char __user *buf, size_t len)
697 {
698         return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len);
699 }
700
701 asmlinkage ssize_t sys32_readahead(int fd, unsigned off_lo, unsigned off_hi,
702                                    size_t count)
703 {
704         return sys_readahead(fd, ((u64)off_hi << 32) | off_lo, count);
705 }
706
707 asmlinkage long sys32_sync_file_range(int fd, unsigned off_low, unsigned off_hi,
708                                       unsigned n_low, unsigned n_hi,  int flags)
709 {
710         return sys_sync_file_range(fd,
711                                    ((u64)off_hi << 32) | off_low,
712                                    ((u64)n_hi << 32) | n_low, flags);
713 }
714
715 asmlinkage long sys32_fadvise64(int fd, unsigned offset_lo, unsigned offset_hi,
716                                 size_t len, int advice)
717 {
718         return sys_fadvise64_64(fd, ((u64)offset_hi << 32) | offset_lo,
719                                 len, advice);
720 }
721
722 asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_lo,
723                                 unsigned offset_hi, unsigned len_lo,
724                                 unsigned len_hi)
725 {
726         return sys_fallocate(fd, mode, ((u64)offset_hi << 32) | offset_lo,
727                              ((u64)len_hi << 32) | len_lo);
728 }