From 541e1690420d293c1b09eeb128fac74e98cbef7a Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 31 Oct 2017 13:53:58 +0100 Subject: linux-user: Handle TARGET_MAP_STACK and TARGET_MAP_HUGETLB Add the missing defines and for TARGET_MAP_STACK and TARGET_MAP_HUGETLB for alpha, mips, ppc, x86, hppa. Fix the mmap_flags translation table to translate MAP_HUGETLB between host and target architecture, and to drop MAP_STACK. Signed-off-by: Helge Deller Message-Id: <20170311183016.GA20514@ls3530.fritz.box> [rth: Drop MAP_STACK instead of translating it, since it is ignored in the kernel anyway. Fix tabs to spaces.] Signed-off-by: Richard Henderson Signed-off-by: Riku Voipio --- linux-user/syscall.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'linux-user/syscall.c') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d4497dec5d..8047bf3aac 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5872,17 +5872,26 @@ static const StructEntry struct_termios_def = { }; static bitmask_transtbl mmap_flags_tbl[] = { - { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED }, - { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE }, - { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED }, - { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS }, - { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN }, - { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE }, - { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE }, - { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED }, - { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE, MAP_NORESERVE, - MAP_NORESERVE }, - { 0, 0, 0, 0 } + { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED }, + { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE }, + { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED }, + { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, + MAP_ANONYMOUS, MAP_ANONYMOUS }, + { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, + MAP_GROWSDOWN, MAP_GROWSDOWN }, + { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, + MAP_DENYWRITE, MAP_DENYWRITE }, + { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, + MAP_EXECUTABLE, MAP_EXECUTABLE }, + { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED }, + { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE, + MAP_NORESERVE, MAP_NORESERVE }, + { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB }, + /* MAP_STACK had been ignored by the kernel for quite some time. + Recognize it for the target insofar as we do not want to pass + it through to the host. */ + { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 }, + { 0, 0, 0, 0 } }; #if defined(TARGET_I386) -- cgit v1.2.3-55-g7522 From 8bf8e9df4a7d82c7a47cc961c9cdee1615595de0 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Fri, 15 Sep 2017 20:33:13 +0100 Subject: linux-user/syscall.c: Handle SH4's exceptional alignment for p{read, write}64 Fixes: https://bugs.launchpad.net/qemu/+bug/1716767 Reviewed-by: Laurent Vivier Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Tested-By: John Paul Adrian Glaubitz Signed-off-by: James Clarke Signed-off-by: Riku Voipio --- linux-user/syscall.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'linux-user/syscall.c') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8047bf3aac..9268c3ef69 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -671,18 +671,32 @@ static inline int next_free_host_timer(void) /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ #ifdef TARGET_ARM -static inline int regpairs_aligned(void *cpu_env) { +static inline int regpairs_aligned(void *cpu_env, int num) +{ return ((((CPUARMState *)cpu_env)->eabi) == 1) ; } #elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32) -static inline int regpairs_aligned(void *cpu_env) { return 1; } +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } #elif defined(TARGET_PPC) && !defined(TARGET_PPC64) /* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs * of registers which translates to the same as ARM/MIPS, because we start with * r3 as arg1 */ -static inline int regpairs_aligned(void *cpu_env) { return 1; } +static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } +#elif defined(TARGET_SH4) +/* SH4 doesn't align register pairs, except for p{read,write}64 */ +static inline int regpairs_aligned(void *cpu_env, int num) +{ + switch (num) { + case TARGET_NR_pread64: + case TARGET_NR_pwrite64: + return 1; + + default: + return 0; + } +} #else -static inline int regpairs_aligned(void *cpu_env) { return 0; } +static inline int regpairs_aligned(void *cpu_env, int num) { return 0; } #endif #define ERRNO_TABLE_SIZE 1200 @@ -6870,7 +6884,7 @@ static inline abi_long target_truncate64(void *cpu_env, const char *arg1, abi_long arg3, abi_long arg4) { - if (regpairs_aligned(cpu_env)) { + if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) { arg2 = arg3; arg3 = arg4; } @@ -6884,7 +6898,7 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1, abi_long arg3, abi_long arg4) { - if (regpairs_aligned(cpu_env)) { + if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) { arg2 = arg3; arg3 = arg4; } @@ -10508,7 +10522,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_pread64 case TARGET_NR_pread64: - if (regpairs_aligned(cpu_env)) { + if (regpairs_aligned(cpu_env, num)) { arg4 = arg5; arg5 = arg6; } @@ -10518,7 +10532,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg2, ret); break; case TARGET_NR_pwrite64: - if (regpairs_aligned(cpu_env)) { + if (regpairs_aligned(cpu_env, num)) { arg4 = arg5; arg5 = arg6; } @@ -11288,7 +11302,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, arg6 = ret; #else /* 6 args: fd, offset (high, low), len (high, low), advice */ - if (regpairs_aligned(cpu_env)) { + if (regpairs_aligned(cpu_env, num)) { /* offset is in (3,4), len in (5,6) and advice in 7 */ arg2 = arg3; arg3 = arg4; @@ -11307,7 +11321,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #ifdef TARGET_NR_fadvise64 case TARGET_NR_fadvise64: /* 5 args: fd, offset (high, low), len, advice */ - if (regpairs_aligned(cpu_env)) { + if (regpairs_aligned(cpu_env, num)) { /* offset is in (3,4), len in 5 and advice in 6 */ arg2 = arg3; arg3 = arg4; @@ -11420,7 +11434,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #ifdef TARGET_NR_readahead case TARGET_NR_readahead: #if TARGET_ABI_BITS == 32 - if (regpairs_aligned(cpu_env)) { + if (regpairs_aligned(cpu_env, num)) { arg2 = arg3; arg3 = arg4; arg4 = arg5; -- cgit v1.2.3-55-g7522 From a4dd3d5172c951e05a7424f14c0f9372522b48f8 Mon Sep 17 00:00:00 2001 From: Emilio G. Cota Date: Wed, 18 Oct 2017 18:01:41 -0400 Subject: linux-user: fix 'finshed' typo in comment Signed-off-by: Emilio G. Cota Signed-off-by: Riku Voipio --- linux-user/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-user/syscall.c') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 9268c3ef69..84e123b67b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6258,7 +6258,7 @@ static void *clone_func(void *arg) pthread_mutex_lock(&info->mutex); pthread_cond_broadcast(&info->cond); pthread_mutex_unlock(&info->mutex); - /* Wait until the parent has finshed initializing the tls state. */ + /* Wait until the parent has finished initializing the tls state. */ pthread_mutex_lock(&clone_lock); pthread_mutex_unlock(&clone_lock); cpu_loop(env); -- cgit v1.2.3-55-g7522 From a8b154a637b586441bad42259a8a9b9619cd117c Mon Sep 17 00:00:00 2001 From: James Cowgill Date: Mon, 6 Nov 2017 18:03:51 +0000 Subject: linux-user: return EINVAL from prctl(PR_*_SECCOMP) If an application tries to install a seccomp filter using prctl(PR_SET_SECCOMP), the filter is likely for the target instead of the host architecture. This will probably cause qemu to be immediately killed when it executes another syscall. Prevent this from happening by returning EINVAL from both seccomp prctl calls. This is the error returned by the kernel when seccomp support is disabled. Fixes: https://bugs.launchpad.net/qemu/+bug/1726394 Reviewed-by: Laurent Vivier Signed-off-by: James Cowgill Signed-off-by: Riku Voipio --- linux-user/syscall.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux-user/syscall.c') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 84e123b67b..f31b853bb7 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -10505,6 +10505,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; } #endif + case PR_GET_SECCOMP: + case PR_SET_SECCOMP: + /* Disable seccomp to prevent the target disabling syscalls we + * need. */ + ret = -TARGET_EINVAL; + break; default: /* Most prctl options have no pointer arguments */ ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5)); -- cgit v1.2.3-55-g7522 From 78bfef72fbf8705f002c5c57cf3f1d3b8e83399e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 6 Nov 2017 18:33:26 +0000 Subject: linux-user: Handle rt_sigaction correctly for SPARC SPARC is like Alpha in its handling of the rt_sigaction syscall: it takes an extra parameter 'restorer' which needs to be copied into the sa_restorer field of the sigaction struct. The order of the arguments differs slightly between SPARC and Alpha but the implementation is otherwise the same. (Compare the rt_sigaction() functions in arch/sparc/kernel/sys_sparc_64.c and arch/alpha/kernel/signal.c.) Note that this change is somewhat moot until SPARC acquires support for actually delivering RT signals. Reviewed-by: Laurent Vivier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/syscall.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'linux-user/syscall.c') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f31b853bb7..11c9116c4a 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8579,8 +8579,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_rt_sigaction: { #if defined(TARGET_ALPHA) - struct target_sigaction act, oact, *pact = 0; + /* For Alpha and SPARC this is a 5 argument syscall, with + * a 'restorer' parameter which must be copied into the + * sa_restorer field of the sigaction struct. + * For Alpha that 'restorer' is arg5; for SPARC it is arg4, + * and arg5 is the sigsetsize. + * Alpha also has a separate rt_sigaction struct that it uses + * here; SPARC uses the usual sigaction struct. + */ struct target_rt_sigaction *rt_act; + struct target_sigaction act, oact, *pact = 0; if (arg4 != sizeof(target_sigset_t)) { ret = -TARGET_EINVAL; @@ -8606,18 +8614,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, unlock_user_struct(rt_act, arg3, 1); } #else +#ifdef TARGET_SPARC + target_ulong restorer = arg4; + target_ulong sigsetsize = arg5; +#else + target_ulong sigsetsize = arg4; +#endif struct target_sigaction *act; struct target_sigaction *oact; - if (arg4 != sizeof(target_sigset_t)) { + if (sigsetsize != sizeof(target_sigset_t)) { ret = -TARGET_EINVAL; break; } if (arg2) { - if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) + if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) { goto efault; - } else + } +#ifdef TARGET_SPARC + act->sa_restorer = restorer; +#endif + } else { act = NULL; + } if (arg3) { if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) { ret = -TARGET_EFAULT; -- cgit v1.2.3-55-g7522