x86/entry/32: Use IA32-specific wrappers for syscalls taking 64-bit arguments
authorBrian Gerst <brgerst@gmail.com>
Fri, 13 Mar 2020 19:51:41 +0000 (15:51 -0400)
committerThomas Gleixner <tglx@linutronix.de>
Sat, 21 Mar 2020 15:03:24 +0000 (16:03 +0100)
For the 32-bit syscall interface, 64-bit arguments (loff_t) are passed via
a pair of 32-bit registers.  These register pairs end up in consecutive stack
slots, which matches the C ABI for 64-bit arguments.  But when accessing the
registers directly from pt_regs, the wrapper needs to manually reassemble the
64-bit value.  These wrappers already exist for 32-bit compat, so make them
available to 32-bit native in preparation for enabling pt_regs-based syscalls.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
Link: https://lkml.kernel.org/r/20200313195144.164260-16-brgerst@gmail.com
arch/x86/entry/syscalls/syscall_32.tbl
arch/x86/ia32/Makefile
arch/x86/ia32/sys_ia32.c [deleted file]
arch/x86/kernel/Makefile
arch/x86/kernel/sys_ia32.c [new file with mode: 0644]
arch/x86/um/Makefile

index 0b8e24cb981ddfeb580c491d85c7c27ebc45d52c..54581ac671b41ab0280f5690df817d7c2763283b 100644 (file)
 177    i386    rt_sigtimedwait         sys_rt_sigtimedwait_time32      compat_sys_rt_sigtimedwait_time32
 178    i386    rt_sigqueueinfo         sys_rt_sigqueueinfo             compat_sys_rt_sigqueueinfo
 179    i386    rt_sigsuspend           sys_rt_sigsuspend               compat_sys_rt_sigsuspend
-180    i386    pread64                 sys_pread64                     compat_sys_ia32_pread64
-181    i386    pwrite64                sys_pwrite64                    compat_sys_ia32_pwrite64
+180    i386    pread64                 sys_ia32_pread64
+181    i386    pwrite64                sys_ia32_pwrite64
 182    i386    chown                   sys_chown16
 183    i386    getcwd                  sys_getcwd
 184    i386    capget                  sys_capget
 190    i386    vfork                   sys_vfork
 191    i386    ugetrlimit              sys_getrlimit                   compat_sys_getrlimit
 192    i386    mmap2                   sys_mmap_pgoff
-193    i386    truncate64              sys_truncate64                  compat_sys_ia32_truncate64
-194    i386    ftruncate64             sys_ftruncate64                 compat_sys_ia32_ftruncate64
+193    i386    truncate64              sys_ia32_truncate64
+194    i386    ftruncate64             sys_ia32_ftruncate64
 195    i386    stat64                  sys_stat64                      compat_sys_ia32_stat64
 196    i386    lstat64                 sys_lstat64                     compat_sys_ia32_lstat64
 197    i386    fstat64                 sys_fstat64                     compat_sys_ia32_fstat64
 # 222 is unused
 # 223 is unused
 224    i386    gettid                  sys_gettid
-225    i386    readahead               sys_readahead                   compat_sys_ia32_readahead
+225    i386    readahead               sys_ia32_readahead
 226    i386    setxattr                sys_setxattr
 227    i386    lsetxattr               sys_lsetxattr
 228    i386    fsetxattr               sys_fsetxattr
 247    i386    io_getevents            sys_io_getevents_time32
 248    i386    io_submit               sys_io_submit                   compat_sys_io_submit
 249    i386    io_cancel               sys_io_cancel
-250    i386    fadvise64               sys_fadvise64                   compat_sys_ia32_fadvise64
+250    i386    fadvise64               sys_ia32_fadvise64
 # 251 is available for reuse (was briefly sys_set_zone_reclaim)
 252    i386    exit_group              sys_exit_group
 253    i386    lookup_dcookie          sys_lookup_dcookie              compat_sys_lookup_dcookie
 269    i386    fstatfs64               sys_fstatfs64                   compat_sys_fstatfs64
 270    i386    tgkill                  sys_tgkill
 271    i386    utimes                  sys_utimes_time32
-272    i386    fadvise64_64            sys_fadvise64_64                compat_sys_ia32_fadvise64_64
+272    i386    fadvise64_64            sys_ia32_fadvise64_64
 273    i386    vserver
 274    i386    mbind                   sys_mbind
 275    i386    get_mempolicy           sys_get_mempolicy               compat_sys_get_mempolicy
 311    i386    set_robust_list         sys_set_robust_list             compat_sys_set_robust_list
 312    i386    get_robust_list         sys_get_robust_list             compat_sys_get_robust_list
 313    i386    splice                  sys_splice
-314    i386    sync_file_range         sys_sync_file_range             compat_sys_ia32_sync_file_range
+314    i386    sync_file_range         sys_ia32_sync_file_range
 315    i386    tee                     sys_tee
 316    i386    vmsplice                sys_vmsplice                    compat_sys_vmsplice
 317    i386    move_pages              sys_move_pages                  compat_sys_move_pages
 321    i386    signalfd                sys_signalfd                    compat_sys_signalfd
 322    i386    timerfd_create          sys_timerfd_create
 323    i386    eventfd                 sys_eventfd
-324    i386    fallocate               sys_fallocate                   compat_sys_ia32_fallocate
+324    i386    fallocate               sys_ia32_fallocate
 325    i386    timerfd_settime         sys_timerfd_settime32
 326    i386    timerfd_gettime         sys_timerfd_gettime32
 327    i386    signalfd4               sys_signalfd4                   compat_sys_signalfd4
index d13b352b2aa7178168e788055c0cb62126e69ecb..8e4d0391ff6c9bafa9bcb7dde33478bd6f569d09 100644 (file)
@@ -3,7 +3,7 @@
 # Makefile for the ia32 kernel emulation subsystem.
 #
 
-obj-$(CONFIG_IA32_EMULATION) := sys_ia32.o ia32_signal.o
+obj-$(CONFIG_IA32_EMULATION) := ia32_signal.o
 
 obj-$(CONFIG_IA32_AOUT) += ia32_aout.o
 
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
deleted file mode 100644 (file)
index a189dc6..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on
- *             sys_sparc32
- *
- * Copyright (C) 2000          VA Linux Co
- * Copyright (C) 2000          Don Dugger <n0ano@valinux.com>
- * Copyright (C) 1999          Arun Sharma <arun.sharma@intel.com>
- * Copyright (C) 1997,1998     Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1997          David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 2000          Hewlett-Packard Co.
- * Copyright (C) 2000          David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2000,2001,2002        Andi Kleen, SuSE Labs (x86-64 port)
- *
- * These routines maintain argument size conversion between 32bit and 64bit
- * environment. In 2.5 most of this should be moved to a generic directory.
- *
- * This file assumes that there is a hole at the end of user address space.
- *
- * Some of the functions are LE specific currently. These are
- * hopefully all marked.  This should be fixed.
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/signal.h>
-#include <linux/syscalls.h>
-#include <linux/times.h>
-#include <linux/utsname.h>
-#include <linux/mm.h>
-#include <linux/uio.h>
-#include <linux/poll.h>
-#include <linux/personality.h>
-#include <linux/stat.h>
-#include <linux/rwsem.h>
-#include <linux/compat.h>
-#include <linux/vfs.h>
-#include <linux/ptrace.h>
-#include <linux/highuid.h>
-#include <linux/sysctl.h>
-#include <linux/slab.h>
-#include <linux/sched/task.h>
-#include <asm/mman.h>
-#include <asm/types.h>
-#include <linux/uaccess.h>
-#include <linux/atomic.h>
-#include <asm/vgtod.h>
-#include <asm/ia32.h>
-
-#define AA(__x)                ((unsigned long)(__x))
-
-
-COMPAT_SYSCALL_DEFINE3(ia32_truncate64, const char __user *, filename,
-                      unsigned long, offset_low, unsigned long, offset_high)
-{
-       return ksys_truncate(filename,
-                           ((loff_t) offset_high << 32) | offset_low);
-}
-
-COMPAT_SYSCALL_DEFINE3(ia32_ftruncate64, unsigned int, fd,
-                      unsigned long, offset_low, unsigned long, offset_high)
-{
-       return ksys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low);
-}
-
-/*
- * Another set for IA32/LFS -- x86_64 struct stat is different due to
- * support for 64bit inode numbers.
- */
-static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat)
-{
-       typeof(ubuf->st_uid) uid = 0;
-       typeof(ubuf->st_gid) gid = 0;
-       SET_UID(uid, from_kuid_munged(current_user_ns(), stat->uid));
-       SET_GID(gid, from_kgid_munged(current_user_ns(), stat->gid));
-       if (!access_ok(ubuf, sizeof(struct stat64)) ||
-           __put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) ||
-           __put_user(stat->ino, &ubuf->__st_ino) ||
-           __put_user(stat->ino, &ubuf->st_ino) ||
-           __put_user(stat->mode, &ubuf->st_mode) ||
-           __put_user(stat->nlink, &ubuf->st_nlink) ||
-           __put_user(uid, &ubuf->st_uid) ||
-           __put_user(gid, &ubuf->st_gid) ||
-           __put_user(huge_encode_dev(stat->rdev), &ubuf->st_rdev) ||
-           __put_user(stat->size, &ubuf->st_size) ||
-           __put_user(stat->atime.tv_sec, &ubuf->st_atime) ||
-           __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec) ||
-           __put_user(stat->mtime.tv_sec, &ubuf->st_mtime) ||
-           __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec) ||
-           __put_user(stat->ctime.tv_sec, &ubuf->st_ctime) ||
-           __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec) ||
-           __put_user(stat->blksize, &ubuf->st_blksize) ||
-           __put_user(stat->blocks, &ubuf->st_blocks))
-               return -EFAULT;
-       return 0;
-}
-
-COMPAT_SYSCALL_DEFINE2(ia32_stat64, const char __user *, filename,
-                      struct stat64 __user *, statbuf)
-{
-       struct kstat stat;
-       int ret = vfs_stat(filename, &stat);
-
-       if (!ret)
-               ret = cp_stat64(statbuf, &stat);
-       return ret;
-}
-
-COMPAT_SYSCALL_DEFINE2(ia32_lstat64, const char __user *, filename,
-                      struct stat64 __user *, statbuf)
-{
-       struct kstat stat;
-       int ret = vfs_lstat(filename, &stat);
-       if (!ret)
-               ret = cp_stat64(statbuf, &stat);
-       return ret;
-}
-
-COMPAT_SYSCALL_DEFINE2(ia32_fstat64, unsigned int, fd,
-                      struct stat64 __user *, statbuf)
-{
-       struct kstat stat;
-       int ret = vfs_fstat(fd, &stat);
-       if (!ret)
-               ret = cp_stat64(statbuf, &stat);
-       return ret;
-}
-
-COMPAT_SYSCALL_DEFINE4(ia32_fstatat64, unsigned int, dfd,
-                      const char __user *, filename,
-                      struct stat64 __user *, statbuf, int, flag)
-{
-       struct kstat stat;
-       int error;
-
-       error = vfs_fstatat(dfd, filename, &stat, flag);
-       if (error)
-               return error;
-       return cp_stat64(statbuf, &stat);
-}
-
-/*
- * Linux/i386 didn't use to be able to handle more than
- * 4 system call parameters, so these system calls used a memory
- * block for parameter passing..
- */
-
-struct mmap_arg_struct32 {
-       unsigned int addr;
-       unsigned int len;
-       unsigned int prot;
-       unsigned int flags;
-       unsigned int fd;
-       unsigned int offset;
-};
-
-COMPAT_SYSCALL_DEFINE1(ia32_mmap, struct mmap_arg_struct32 __user *, arg)
-{
-       struct mmap_arg_struct32 a;
-
-       if (copy_from_user(&a, arg, sizeof(a)))
-               return -EFAULT;
-
-       if (a.offset & ~PAGE_MASK)
-               return -EINVAL;
-
-       return ksys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
-                              a.offset>>PAGE_SHIFT);
-}
-
-/* warning: next two assume little endian */
-COMPAT_SYSCALL_DEFINE5(ia32_pread64, unsigned int, fd, char __user *, ubuf,
-                      u32, count, u32, poslo, u32, poshi)
-{
-       return ksys_pread64(fd, ubuf, count,
-                           ((loff_t)AA(poshi) << 32) | AA(poslo));
-}
-
-COMPAT_SYSCALL_DEFINE5(ia32_pwrite64, unsigned int, fd, const char __user *, ubuf,
-                      u32, count, u32, poslo, u32, poshi)
-{
-       return ksys_pwrite64(fd, ubuf, count,
-                            ((loff_t)AA(poshi) << 32) | AA(poslo));
-}
-
-
-/*
- * Some system calls that need sign extended arguments. This could be
- * done by a generic wrapper.
- */
-COMPAT_SYSCALL_DEFINE6(ia32_fadvise64_64, int, fd, __u32, offset_low,
-                      __u32, offset_high, __u32, len_low, __u32, len_high,
-                      int, advice)
-{
-       return ksys_fadvise64_64(fd,
-                                (((u64)offset_high)<<32) | offset_low,
-                                (((u64)len_high)<<32) | len_low,
-                                advice);
-}
-
-COMPAT_SYSCALL_DEFINE4(ia32_readahead, int, fd, unsigned int, off_lo,
-                      unsigned int, off_hi, size_t, count)
-{
-       return ksys_readahead(fd, ((u64)off_hi << 32) | off_lo, count);
-}
-
-COMPAT_SYSCALL_DEFINE6(ia32_sync_file_range, int, fd, unsigned int, off_low,
-                      unsigned int, off_hi, unsigned int, n_low,
-                      unsigned int, n_hi, int, flags)
-{
-       return ksys_sync_file_range(fd,
-                                   ((u64)off_hi << 32) | off_low,
-                                   ((u64)n_hi << 32) | n_low, flags);
-}
-
-COMPAT_SYSCALL_DEFINE5(ia32_fadvise64, int, fd, unsigned int, offset_lo,
-                      unsigned int, offset_hi, size_t, len, int, advice)
-{
-       return ksys_fadvise64_64(fd, ((u64)offset_hi << 32) | offset_lo,
-                                len, advice);
-}
-
-COMPAT_SYSCALL_DEFINE6(ia32_fallocate, int, fd, int, mode,
-                      unsigned int, offset_lo, unsigned int, offset_hi,
-                      unsigned int, len_lo, unsigned int, len_hi)
-{
-       return ksys_fallocate(fd, mode, ((u64)offset_hi << 32) | offset_lo,
-                             ((u64)len_hi << 32) | len_lo);
-}
-
-/*
- * The 32-bit clone ABI is CONFIG_CLONE_BACKWARDS
- */
-COMPAT_SYSCALL_DEFINE5(ia32_clone, unsigned long, clone_flags,
-                      unsigned long, newsp, int __user *, parent_tidptr,
-                      unsigned long, tls_val, int __user *, child_tidptr)
-{
-       struct kernel_clone_args args = {
-               .flags          = (clone_flags & ~CSIGNAL),
-               .pidfd          = parent_tidptr,
-               .child_tid      = child_tidptr,
-               .parent_tid     = parent_tidptr,
-               .exit_signal    = (clone_flags & CSIGNAL),
-               .stack          = newsp,
-               .tls            = tls_val,
-       };
-
-       if (!legacy_clone_args_valid(&args))
-               return -EINVAL;
-
-       return _do_fork(&args);
-}
index 9b294c13809ae476f8ee707ed6304273251753f9..b8f89f78b8cdd91f959ad21fe457812342374b96 100644 (file)
@@ -53,6 +53,8 @@ obj-y                 += setup.o x86_init.o i8259.o irqinit.o
 obj-$(CONFIG_JUMP_LABEL)       += jump_label.o
 obj-$(CONFIG_IRQ_WORK)  += irq_work.o
 obj-y                  += probe_roms.o
+obj-$(CONFIG_X86_32)   += sys_ia32.o
+obj-$(CONFIG_IA32_EMULATION)   += sys_ia32.o
 obj-$(CONFIG_X86_64)   += sys_x86_64.o
 obj-$(CONFIG_X86_ESPFIX64)     += espfix_64.o
 obj-$(CONFIG_SYSFS)    += ksysfs.o
diff --git a/arch/x86/kernel/sys_ia32.c b/arch/x86/kernel/sys_ia32.c
new file mode 100644 (file)
index 0000000..ab03fed
--- /dev/null
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on
+ *             sys_sparc32
+ *
+ * Copyright (C) 2000          VA Linux Co
+ * Copyright (C) 2000          Don Dugger <n0ano@valinux.com>
+ * Copyright (C) 1999          Arun Sharma <arun.sharma@intel.com>
+ * Copyright (C) 1997,1998     Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997          David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 2000          Hewlett-Packard Co.
+ * Copyright (C) 2000          David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2000,2001,2002        Andi Kleen, SuSE Labs (x86-64 port)
+ *
+ * These routines maintain argument size conversion between 32bit and 64bit
+ * environment. In 2.5 most of this should be moved to a generic directory.
+ *
+ * This file assumes that there is a hole at the end of user address space.
+ *
+ * Some of the functions are LE specific currently. These are
+ * hopefully all marked.  This should be fixed.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/times.h>
+#include <linux/utsname.h>
+#include <linux/mm.h>
+#include <linux/uio.h>
+#include <linux/poll.h>
+#include <linux/personality.h>
+#include <linux/stat.h>
+#include <linux/rwsem.h>
+#include <linux/compat.h>
+#include <linux/vfs.h>
+#include <linux/ptrace.h>
+#include <linux/highuid.h>
+#include <linux/sysctl.h>
+#include <linux/slab.h>
+#include <linux/sched/task.h>
+#include <asm/mman.h>
+#include <asm/types.h>
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
+#include <asm/vgtod.h>
+#include <asm/ia32.h>
+
+#define AA(__x)                ((unsigned long)(__x))
+
+SYSCALL_DEFINE3(ia32_truncate64, const char __user *, filename,
+               unsigned long, offset_low, unsigned long, offset_high)
+{
+       return ksys_truncate(filename,
+                           ((loff_t) offset_high << 32) | offset_low);
+}
+
+SYSCALL_DEFINE3(ia32_ftruncate64, unsigned int, fd,
+               unsigned long, offset_low, unsigned long, offset_high)
+{
+       return ksys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low);
+}
+
+/* warning: next two assume little endian */
+SYSCALL_DEFINE5(ia32_pread64, unsigned int, fd, char __user *, ubuf,
+               u32, count, u32, poslo, u32, poshi)
+{
+       return ksys_pread64(fd, ubuf, count,
+                           ((loff_t)AA(poshi) << 32) | AA(poslo));
+}
+
+SYSCALL_DEFINE5(ia32_pwrite64, unsigned int, fd, const char __user *, ubuf,
+               u32, count, u32, poslo, u32, poshi)
+{
+       return ksys_pwrite64(fd, ubuf, count,
+                            ((loff_t)AA(poshi) << 32) | AA(poslo));
+}
+
+
+/*
+ * Some system calls that need sign extended arguments. This could be
+ * done by a generic wrapper.
+ */
+SYSCALL_DEFINE6(ia32_fadvise64_64, int, fd, __u32, offset_low,
+               __u32, offset_high, __u32, len_low, __u32, len_high,
+               int, advice)
+{
+       return ksys_fadvise64_64(fd,
+                                (((u64)offset_high)<<32) | offset_low,
+                                (((u64)len_high)<<32) | len_low,
+                                advice);
+}
+
+SYSCALL_DEFINE4(ia32_readahead, int, fd, unsigned int, off_lo,
+               unsigned int, off_hi, size_t, count)
+{
+       return ksys_readahead(fd, ((u64)off_hi << 32) | off_lo, count);
+}
+
+SYSCALL_DEFINE6(ia32_sync_file_range, int, fd, unsigned int, off_low,
+               unsigned int, off_hi, unsigned int, n_low,
+               unsigned int, n_hi, int, flags)
+{
+       return ksys_sync_file_range(fd,
+                                   ((u64)off_hi << 32) | off_low,
+                                   ((u64)n_hi << 32) | n_low, flags);
+}
+
+SYSCALL_DEFINE5(ia32_fadvise64, int, fd, unsigned int, offset_lo,
+               unsigned int, offset_hi, size_t, len, int, advice)
+{
+       return ksys_fadvise64_64(fd, ((u64)offset_hi << 32) | offset_lo,
+                                len, advice);
+}
+
+SYSCALL_DEFINE6(ia32_fallocate, int, fd, int, mode,
+               unsigned int, offset_lo, unsigned int, offset_hi,
+               unsigned int, len_lo, unsigned int, len_hi)
+{
+       return ksys_fallocate(fd, mode, ((u64)offset_hi << 32) | offset_lo,
+                             ((u64)len_hi << 32) | len_lo);
+}
+
+#ifdef CONFIG_IA32_EMULATION
+/*
+ * Another set for IA32/LFS -- x86_64 struct stat is different due to
+ * support for 64bit inode numbers.
+ */
+static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat)
+{
+       typeof(ubuf->st_uid) uid = 0;
+       typeof(ubuf->st_gid) gid = 0;
+       SET_UID(uid, from_kuid_munged(current_user_ns(), stat->uid));
+       SET_GID(gid, from_kgid_munged(current_user_ns(), stat->gid));
+       if (!access_ok(ubuf, sizeof(struct stat64)) ||
+           __put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) ||
+           __put_user(stat->ino, &ubuf->__st_ino) ||
+           __put_user(stat->ino, &ubuf->st_ino) ||
+           __put_user(stat->mode, &ubuf->st_mode) ||
+           __put_user(stat->nlink, &ubuf->st_nlink) ||
+           __put_user(uid, &ubuf->st_uid) ||
+           __put_user(gid, &ubuf->st_gid) ||
+           __put_user(huge_encode_dev(stat->rdev), &ubuf->st_rdev) ||
+           __put_user(stat->size, &ubuf->st_size) ||
+           __put_user(stat->atime.tv_sec, &ubuf->st_atime) ||
+           __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec) ||
+           __put_user(stat->mtime.tv_sec, &ubuf->st_mtime) ||
+           __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec) ||
+           __put_user(stat->ctime.tv_sec, &ubuf->st_ctime) ||
+           __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec) ||
+           __put_user(stat->blksize, &ubuf->st_blksize) ||
+           __put_user(stat->blocks, &ubuf->st_blocks))
+               return -EFAULT;
+       return 0;
+}
+
+COMPAT_SYSCALL_DEFINE2(ia32_stat64, const char __user *, filename,
+                      struct stat64 __user *, statbuf)
+{
+       struct kstat stat;
+       int ret = vfs_stat(filename, &stat);
+
+       if (!ret)
+               ret = cp_stat64(statbuf, &stat);
+       return ret;
+}
+
+COMPAT_SYSCALL_DEFINE2(ia32_lstat64, const char __user *, filename,
+                      struct stat64 __user *, statbuf)
+{
+       struct kstat stat;
+       int ret = vfs_lstat(filename, &stat);
+       if (!ret)
+               ret = cp_stat64(statbuf, &stat);
+       return ret;
+}
+
+COMPAT_SYSCALL_DEFINE2(ia32_fstat64, unsigned int, fd,
+                      struct stat64 __user *, statbuf)
+{
+       struct kstat stat;
+       int ret = vfs_fstat(fd, &stat);
+       if (!ret)
+               ret = cp_stat64(statbuf, &stat);
+       return ret;
+}
+
+COMPAT_SYSCALL_DEFINE4(ia32_fstatat64, unsigned int, dfd,
+                      const char __user *, filename,
+                      struct stat64 __user *, statbuf, int, flag)
+{
+       struct kstat stat;
+       int error;
+
+       error = vfs_fstatat(dfd, filename, &stat, flag);
+       if (error)
+               return error;
+       return cp_stat64(statbuf, &stat);
+}
+
+/*
+ * Linux/i386 didn't use to be able to handle more than
+ * 4 system call parameters, so these system calls used a memory
+ * block for parameter passing..
+ */
+
+struct mmap_arg_struct32 {
+       unsigned int addr;
+       unsigned int len;
+       unsigned int prot;
+       unsigned int flags;
+       unsigned int fd;
+       unsigned int offset;
+};
+
+COMPAT_SYSCALL_DEFINE1(ia32_mmap, struct mmap_arg_struct32 __user *, arg)
+{
+       struct mmap_arg_struct32 a;
+
+       if (copy_from_user(&a, arg, sizeof(a)))
+               return -EFAULT;
+
+       if (a.offset & ~PAGE_MASK)
+               return -EINVAL;
+
+       return ksys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
+                              a.offset>>PAGE_SHIFT);
+}
+
+/*
+ * The 32-bit clone ABI is CONFIG_CLONE_BACKWARDS
+ */
+COMPAT_SYSCALL_DEFINE5(ia32_clone, unsigned long, clone_flags,
+                      unsigned long, newsp, int __user *, parent_tidptr,
+                      unsigned long, tls_val, int __user *, child_tidptr)
+{
+       struct kernel_clone_args args = {
+               .flags          = (clone_flags & ~CSIGNAL),
+               .pidfd          = parent_tidptr,
+               .child_tid      = child_tidptr,
+               .parent_tid     = parent_tidptr,
+               .exit_signal    = (clone_flags & CSIGNAL),
+               .stack          = newsp,
+               .tls            = tls_val,
+       };
+
+       if (!legacy_clone_args_valid(&args))
+               return -EINVAL;
+
+       return _do_fork(&args);
+}
+#endif /* CONFIG_IA32_EMULATION */
index 33c51c064c77e83242e6dc62e3254af438b626d4..77f70b969d1439a71c8b4f44c42083de46a40b0f 100644 (file)
@@ -21,6 +21,7 @@ obj-y += checksum_32.o syscalls_32.o
 obj-$(CONFIG_ELF_CORE) += elfcore.o
 
 subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o
+subarch-y += ../kernel/sys_ia32.o
 
 else