Skip to content

Commit

Permalink
Merge branch 'compat' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/s390/linux

Pull s390 compat wrapper rework from Heiko Carstens:
 "S390 compat system call wrapper simplification work.

  The intention of this work is to get rid of all hand written assembly
  compat system call wrappers on s390, which perform proper sign or zero
  extension, or pointer conversion of compat system call parameters.
  Instead all of this should be done with C code eg by using Al's
  COMPAT_SYSCALL_DEFINEx() macro.

  Therefore all common code and s390 specific compat system calls have
  been converted to the COMPAT_SYSCALL_DEFINEx() macro.

  In order to generate correct code all compat system calls may only
  have eg compat_ulong_t parameters, but no unsigned long parameters.
  Those patches which change parameter types from unsigned long to
  compat_ulong_t parameters are separate in this series, but shouldn't
  cause any harm.

  The only compat system calls which intentionally have 64 bit
  parameters (preadv64 and pwritev64) in support of the x86/32 ABI
  haven't been changed, but are now only available if an architecture
  defines __ARCH_WANT_COMPAT_SYS_PREADV64/PWRITEV64.

  System calls which do not have a compat variant but still need proper
  zero extension on s390, like eg "long sys_brk(unsigned long brk)" will
  get a proper wrapper function with the new s390 specific
  COMPAT_SYSCALL_WRAPx() macro:

     COMPAT_SYSCALL_WRAP1(brk, unsigned long, brk);

  which generates the following code (simplified):

     asmlinkage long sys_brk(unsigned long brk);
     asmlinkage long compat_sys_brk(long brk)
     {
         return sys_brk((u32)brk);
     }

  Given that the C file which contains all the COMPAT_SYSCALL_WRAP lines
  includes both linux/syscall.h and linux/compat.h, it will generate
  build errors, if the declaration of sys_brk() doesn't match, or if
  there exists a non-matching compat_sys_brk() declaration.

  In addition this will intentionally result in a link error if
  somewhere else a compat_sys_brk() function exists, which probably
  should have been used instead.  Two more BUILD_BUG_ONs make sure the
  size and type of each compat syscall parameter can be handled
  correctly with the s390 specific macros.

  I converted the compat system calls step by step to verify the
  generated code is correct and matches the previous code.  In fact it
  did not always match, however that was always a bug in the hand
  written asm code.

  In result we get less code, less bugs, and much more sanity checking"

* 'compat' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (44 commits)
  s390/compat: add copyright statement
  compat: include linux/unistd.h within linux/compat.h
  s390/compat: get rid of compat wrapper assembly code
  s390/compat: build error for large compat syscall args
  mm/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types
  kexec/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types
  net/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types
  ipc/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types
  fs/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types
  ipc/compat: convert to COMPAT_SYSCALL_DEFINE
  fs/compat: convert to COMPAT_SYSCALL_DEFINE
  security/compat: convert to COMPAT_SYSCALL_DEFINE
  mm/compat: convert to COMPAT_SYSCALL_DEFINE
  net/compat: convert to COMPAT_SYSCALL_DEFINE
  kernel/compat: convert to COMPAT_SYSCALL_DEFINE
  fs/compat: optional preadv64/pwrite64 compat system calls
  ipc/compat_sys_msgrcv: change msgtyp type from long to compat_long_t
  s390/compat: partial parameter conversion within syscall wrappers
  s390/compat: automatic zero, sign and pointer conversion of syscalls
  s390/compat: add sync_file_range and fallocate compat syscalls
  ...
  • Loading branch information
torvalds committed Mar 31, 2014
2 parents 176ab02 + 1e4ec62 commit 190f918
Show file tree
Hide file tree
Showing 28 changed files with 835 additions and 2,004 deletions.
1 change: 1 addition & 0 deletions arch/arm64/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef CONFIG_COMPAT
#define __ARCH_WANT_COMPAT_SYS_GETDENTS64
#define __ARCH_WANT_COMPAT_STAT64
#define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_PAUSE
Expand Down
1 change: 0 additions & 1 deletion arch/mips/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

#ifndef __ASSEMBLY__

#define __ARCH_OMIT_COMPAT_SYS_GETDENTS64
#define __ARCH_WANT_OLD_READDIR
#define __ARCH_WANT_SYS_ALARM
#define __ARCH_WANT_SYS_GETHOSTNAME
Expand Down
6 changes: 5 additions & 1 deletion arch/s390/include/asm/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
#include <linux/thread_info.h>

#define __TYPE_IS_PTR(t) (!__builtin_types_compatible_p(typeof(0?(t)0:0ULL), u64))
#define __SC_DELOUSE(t,v) (t)(__TYPE_IS_PTR(t) ? ((v) & 0x7fffffff) : (v))

#define __SC_DELOUSE(t,v) ({ \
BUILD_BUG_ON(sizeof(t) > 4 && !__TYPE_IS_PTR(t)); \
(t)(__TYPE_IS_PTR(t) ? ((v) & 0x7fffffff) : (v)); \
})

#define PSW32_MASK_PER 0x40000000UL
#define PSW32_MASK_DAT 0x04000000UL
Expand Down
116 changes: 63 additions & 53 deletions arch/s390/kernel/compat_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,48 +86,51 @@
#define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
#define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)

asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group)
COMPAT_SYSCALL_DEFINE3(s390_chown16, const char __user *, filename,
u16, user, u16, group)
{
return sys_chown(filename, low2highuid(user), low2highgid(group));
}

asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group)
COMPAT_SYSCALL_DEFINE3(s390_lchown16, const char __user *,
filename, u16, user, u16, group)
{
return sys_lchown(filename, low2highuid(user), low2highgid(group));
}

asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
COMPAT_SYSCALL_DEFINE3(s390_fchown16, unsigned int, fd, u16, user, u16, group)
{
return sys_fchown(fd, low2highuid(user), low2highgid(group));
}

asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
COMPAT_SYSCALL_DEFINE2(s390_setregid16, u16, rgid, u16, egid)
{
return sys_setregid(low2highgid(rgid), low2highgid(egid));
}

asmlinkage long sys32_setgid16(u16 gid)
COMPAT_SYSCALL_DEFINE1(s390_setgid16, u16, gid)
{
return sys_setgid((gid_t)gid);
}

asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
COMPAT_SYSCALL_DEFINE2(s390_setreuid16, u16, ruid, u16, euid)
{
return sys_setreuid(low2highuid(ruid), low2highuid(euid));
}

asmlinkage long sys32_setuid16(u16 uid)
COMPAT_SYSCALL_DEFINE1(s390_setuid16, u16, uid)
{
return sys_setuid((uid_t)uid);
}

asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
COMPAT_SYSCALL_DEFINE3(s390_setresuid16, u16, ruid, u16, euid, u16, suid)
{
return sys_setresuid(low2highuid(ruid), low2highuid(euid),
low2highuid(suid));
low2highuid(suid));
}

asmlinkage long sys32_getresuid16(u16 __user *ruidp, u16 __user *euidp, u16 __user *suidp)
COMPAT_SYSCALL_DEFINE3(s390_getresuid16, u16 __user *, ruidp,
u16 __user *, euidp, u16 __user *, suidp)
{
const struct cred *cred = current_cred();
int retval;
Expand All @@ -144,13 +147,14 @@ asmlinkage long sys32_getresuid16(u16 __user *ruidp, u16 __user *euidp, u16 __us
return retval;
}

asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
COMPAT_SYSCALL_DEFINE3(s390_setresgid16, u16, rgid, u16, egid, u16, sgid)
{
return sys_setresgid(low2highgid(rgid), low2highgid(egid),
low2highgid(sgid));
low2highgid(sgid));
}

asmlinkage long sys32_getresgid16(u16 __user *rgidp, u16 __user *egidp, u16 __user *sgidp)
COMPAT_SYSCALL_DEFINE3(s390_getresgid16, u16 __user *, rgidp,
u16 __user *, egidp, u16 __user *, sgidp)
{
const struct cred *cred = current_cred();
int retval;
Expand All @@ -167,12 +171,12 @@ asmlinkage long sys32_getresgid16(u16 __user *rgidp, u16 __user *egidp, u16 __us
return retval;
}

asmlinkage long sys32_setfsuid16(u16 uid)
COMPAT_SYSCALL_DEFINE1(s390_setfsuid16, u16, uid)
{
return sys_setfsuid((uid_t)uid);
}

asmlinkage long sys32_setfsgid16(u16 gid)
COMPAT_SYSCALL_DEFINE1(s390_setfsgid16, u16, gid)
{
return sys_setfsgid((gid_t)gid);
}
Expand Down Expand Up @@ -215,7 +219,7 @@ static int groups16_from_user(struct group_info *group_info, u16 __user *groupli
return 0;
}

asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
COMPAT_SYSCALL_DEFINE2(s390_getgroups16, int, gidsetsize, u16 __user *, grouplist)
{
const struct cred *cred = current_cred();
int i;
Expand All @@ -240,7 +244,7 @@ asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
return i;
}

asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
COMPAT_SYSCALL_DEFINE2(s390_setgroups16, int, gidsetsize, u16 __user *, grouplist)
{
struct group_info *group_info;
int retval;
Expand All @@ -265,22 +269,22 @@ asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
return retval;
}

asmlinkage long sys32_getuid16(void)
COMPAT_SYSCALL_DEFINE0(s390_getuid16)
{
return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));
}

asmlinkage long sys32_geteuid16(void)
COMPAT_SYSCALL_DEFINE0(s390_geteuid16)
{
return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));
}

asmlinkage long sys32_getgid16(void)
COMPAT_SYSCALL_DEFINE0(s390_getgid16)
{
return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));
}

asmlinkage long sys32_getegid16(void)
COMPAT_SYSCALL_DEFINE0(s390_getegid16)
{
return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));
}
Expand All @@ -295,41 +299,35 @@ COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, compat_ulong_t, second,
}
#endif

asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
COMPAT_SYSCALL_DEFINE3(s390_truncate64, const char __user *, path, u32, high, u32, low)
{
if ((int)high < 0)
return -EINVAL;
else
return sys_truncate(path, (high << 32) | low);
return sys_truncate(path, (unsigned long)high << 32 | low);
}

asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
COMPAT_SYSCALL_DEFINE3(s390_ftruncate64, unsigned int, fd, u32, high, u32, low)
{
if ((int)high < 0)
return -EINVAL;
else
return sys_ftruncate(fd, (high << 32) | low);
return sys_ftruncate(fd, (unsigned long)high << 32 | low);
}

asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
size_t count, u32 poshi, u32 poslo)
COMPAT_SYSCALL_DEFINE5(s390_pread64, unsigned int, fd, char __user *, ubuf,
compat_size_t, count, u32, high, u32, low)
{
if ((compat_ssize_t) count < 0)
return -EINVAL;
return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
return sys_pread64(fd, ubuf, count, (unsigned long)high << 32 | low);
}

asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
size_t count, u32 poshi, u32 poslo)
COMPAT_SYSCALL_DEFINE5(s390_pwrite64, unsigned int, fd, const char __user *, ubuf,
compat_size_t, count, u32, high, u32, low)
{
if ((compat_ssize_t) count < 0)
return -EINVAL;
return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
return sys_pwrite64(fd, ubuf, count, (unsigned long)high << 32 | low);
}

asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
COMPAT_SYSCALL_DEFINE4(s390_readahead, int, fd, u32, high, u32, low, s32, count)
{
return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
return sys_readahead(fd, (unsigned long)high << 32 | low, count);
}

struct stat64_emu31 {
Expand Down Expand Up @@ -381,7 +379,7 @@ static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat)
return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}

asmlinkage long sys32_stat64(const char __user * filename, struct stat64_emu31 __user * statbuf)
COMPAT_SYSCALL_DEFINE2(s390_stat64, const char __user *, filename, struct stat64_emu31 __user *, statbuf)
{
struct kstat stat;
int ret = vfs_stat(filename, &stat);
Expand All @@ -390,7 +388,7 @@ asmlinkage long sys32_stat64(const char __user * filename, struct stat64_emu31 _
return ret;
}

asmlinkage long sys32_lstat64(const char __user * filename, struct stat64_emu31 __user * statbuf)
COMPAT_SYSCALL_DEFINE2(s390_lstat64, const char __user *, filename, struct stat64_emu31 __user *, statbuf)
{
struct kstat stat;
int ret = vfs_lstat(filename, &stat);
Expand All @@ -399,7 +397,7 @@ asmlinkage long sys32_lstat64(const char __user * filename, struct stat64_emu31
return ret;
}

asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf)
COMPAT_SYSCALL_DEFINE2(s390_fstat64, unsigned int, fd, struct stat64_emu31 __user *, statbuf)
{
struct kstat stat;
int ret = vfs_fstat(fd, &stat);
Expand All @@ -408,8 +406,8 @@ asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * sta
return ret;
}

asmlinkage long sys32_fstatat64(unsigned int dfd, const char __user *filename,
struct stat64_emu31 __user* statbuf, int flag)
COMPAT_SYSCALL_DEFINE4(s390_fstatat64, unsigned int, dfd, const char __user *, filename,
struct stat64_emu31 __user *, statbuf, int, flag)
{
struct kstat stat;
int error;
Expand All @@ -435,7 +433,7 @@ struct mmap_arg_struct_emu31 {
compat_ulong_t offset;
};

asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
COMPAT_SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct_emu31 __user *, arg)
{
struct mmap_arg_struct_emu31 a;

Expand All @@ -447,7 +445,7 @@ asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
a.offset >> PAGE_SHIFT);
}

asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
COMPAT_SYSCALL_DEFINE1(s390_mmap2, struct mmap_arg_struct_emu31 __user *, arg)
{
struct mmap_arg_struct_emu31 a;

Expand All @@ -456,15 +454,15 @@ asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
}

asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count)
COMPAT_SYSCALL_DEFINE3(s390_read, unsigned int, fd, char __user *, buf, compat_size_t, count)
{
if ((compat_ssize_t) count < 0)
return -EINVAL;

return sys_read(fd, buf, count);
}

asmlinkage long sys32_write(unsigned int fd, const char __user * buf, size_t count)
COMPAT_SYSCALL_DEFINE3(s390_write, unsigned int, fd, const char __user *, buf, compat_size_t, count)
{
if ((compat_ssize_t) count < 0)
return -EINVAL;
Expand All @@ -478,14 +476,13 @@ asmlinkage long sys32_write(unsigned int fd, const char __user * buf, size_t cou
* because the 31 bit values differ from the 64 bit values.
*/

asmlinkage long
sys32_fadvise64(int fd, loff_t offset, size_t len, int advise)
COMPAT_SYSCALL_DEFINE5(s390_fadvise64, int, fd, u32, high, u32, low, compat_size_t, len, int, advise)
{
if (advise == 4)
advise = POSIX_FADV_DONTNEED;
else if (advise == 5)
advise = POSIX_FADV_NOREUSE;
return sys_fadvise64(fd, offset, len, advise);
return sys_fadvise64(fd, (unsigned long)high << 32 | low, len, advise);
}

struct fadvise64_64_args {
Expand All @@ -495,8 +492,7 @@ struct fadvise64_64_args {
int advice;
};

asmlinkage long
sys32_fadvise64_64(struct fadvise64_64_args __user *args)
COMPAT_SYSCALL_DEFINE1(s390_fadvise64_64, struct fadvise64_64_args __user *, args)
{
struct fadvise64_64_args a;

Expand All @@ -508,3 +504,17 @@ sys32_fadvise64_64(struct fadvise64_64_args __user *args)
a.advice = POSIX_FADV_NOREUSE;
return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice);
}

COMPAT_SYSCALL_DEFINE6(s390_sync_file_range, int, fd, u32, offhigh, u32, offlow,
u32, nhigh, u32, nlow, unsigned int, flags)
{
return sys_sync_file_range(fd, ((loff_t)offhigh << 32) + offlow,
((u64)nhigh << 32) + nlow, flags);
}

COMPAT_SYSCALL_DEFINE6(s390_fallocate, int, fd, int, mode, u32, offhigh, u32, offlow,
u32, lenhigh, u32, lenlow)
{
return sys_fallocate(fd, mode, ((loff_t)offhigh << 32) + offlow,
((u64)lenhigh << 32) + lenlow);
}
Loading

0 comments on commit 190f918

Please sign in to comment.