From b6e2c9353a5bd8649ee71a52c35344ce3fb1c7d2 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 8 Jan 2015 12:19:43 +0000 Subject: [PATCH 01/11] linux-user/signal.c: Remove current_exec_domain_sig() Remove the function current_exec_domain_sig(), which always returns its argument. This was intended as a stub for supporting the kernel's exec_domain handling, but: * we don't have any of the other code for execution domains * in the kernel this handling is architecture-specific, not generic * we only call this function in the x86, ppc and sh4 signal code paths, and the PPC one is wrong anyway because the PPC kernel doesn't have this signal-remapping code So it's best to simply delete the function; any future attempt to implement exec domains will be better served by adding the correct code from scratch based on the kernel sources at that time. This change also fixes some clang warnings about the function being defined but not used for some target architectures. Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/signal.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index e11b20887e..fa955efed1 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -738,12 +738,6 @@ static inline void copy_siginfo_to_user(target_siginfo_t *tinfo, tswap_siginfo(tinfo, info); } -static inline int current_exec_domain_sig(int sig) -{ - return /* current->exec_domain && current->exec_domain->signal_invmap - && sig < 32 ? current->exec_domain->signal_invmap[sig] : */ sig; -} - #if defined(TARGET_I386) && TARGET_ABI_BITS == 32 /* from the Linux kernel */ @@ -926,8 +920,7 @@ static void setup_frame(int sig, struct target_sigaction *ka, if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) goto give_sigsegv; - __put_user(current_exec_domain_sig(sig), - &frame->sig); + __put_user(sig, &frame->sig); setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0], frame_addr + offsetof(struct sigframe, fpstate)); @@ -988,7 +981,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) goto give_sigsegv; - __put_user(current_exec_domain_sig(sig), &frame->sig); + __put_user(sig, &frame->sig); addr = frame_addr + offsetof(struct rt_sigframe, info); __put_user(addr, &frame->pinfo); addr = frame_addr + offsetof(struct rt_sigframe, uc); @@ -3228,14 +3221,11 @@ static void setup_frame(int sig, struct target_sigaction *ka, abi_ulong frame_addr; int i; int err = 0; - int signal; frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame)); if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) goto give_sigsegv; - signal = current_exec_domain_sig(sig); - setup_sigcontext(&frame->sc, regs, set->sig[0]); for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) { @@ -3259,7 +3249,7 @@ static void setup_frame(int sig, struct target_sigaction *ka, /* Set up registers for signal handler */ regs->gregs[15] = frame_addr; - regs->gregs[4] = signal; /* Arg for signal handler */ + regs->gregs[4] = sig; /* Arg for signal handler */ regs->gregs[5] = 0; regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc); regs->pc = (unsigned long) ka->_sa_handler; @@ -3280,14 +3270,11 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, abi_ulong frame_addr; int i; int err = 0; - int signal; frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame)); if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) goto give_sigsegv; - signal = current_exec_domain_sig(sig); - copy_siginfo_to_user(&frame->info, info); /* Create the ucontext. */ @@ -3322,7 +3309,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, /* Set up registers for signal handler */ regs->gregs[15] = frame_addr; - regs->gregs[4] = signal; /* Arg for signal handler */ + regs->gregs[4] = sig; /* Arg for signal handler */ regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info); regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc); regs->pc = (unsigned long) ka->_sa_handler; @@ -4680,7 +4667,6 @@ static void setup_frame(int sig, struct target_sigaction *ka, struct target_sigcontext *sc; target_ulong frame_addr, newsp; int err = 0; - int signal; #if defined(TARGET_PPC64) struct image_info *image = ((TaskState *)thread_cpu->opaque)->info; #endif @@ -4690,8 +4676,6 @@ static void setup_frame(int sig, struct target_sigaction *ka, goto sigsegv; sc = &frame->sctx; - signal = current_exec_domain_sig(sig); - __put_user(ka->_sa_handler, &sc->handler); __put_user(set->sig[0], &sc->oldmask); #if TARGET_ABI_BITS == 64 @@ -4724,7 +4708,7 @@ static void setup_frame(int sig, struct target_sigaction *ka, /* Set up registers for signal handler. */ env->gpr[1] = newsp; - env->gpr[3] = signal; + env->gpr[3] = sig; env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx); #if defined(TARGET_PPC64) @@ -4765,7 +4749,6 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, struct target_mcontext *mctx = 0; target_ulong rt_sf_addr, newsp = 0; int i, err = 0; - int signal; #if defined(TARGET_PPC64) struct image_info *image = ((TaskState *)thread_cpu->opaque)->info; #endif @@ -4774,8 +4757,6 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1)) goto sigsegv; - signal = current_exec_domain_sig(sig); - copy_siginfo_to_user(&rt_sf->info, info); __put_user(0, &rt_sf->uc.tuc_flags); @@ -4821,7 +4802,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, /* Set up registers for signal handler. */ env->gpr[1] = newsp; - env->gpr[3] = (target_ulong) signal; + env->gpr[3] = (target_ulong) sig; env->gpr[4] = (target_ulong) h2g(&rt_sf->info); env->gpr[5] = (target_ulong) h2g(&rt_sf->uc); env->gpr[6] = (target_ulong) h2g(rt_sf); From ea2b5fb19d50c1cbdea9a40504e31e54d37b8bab Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 8 Jan 2015 12:19:44 +0000 Subject: [PATCH 02/11] linux-user/alpha: Add define for NR_shmat to enable shmat syscall For historical reasons, the define for the shmat() syscall on Alpha is NR_osf_shmat; however it has the same semantics as this syscall does on all other architectures, so define TARGET_NR_shmat as well so that QEMU's code for the syscall is enabled. This patch brings our behaviour on the LTP shmat tests into line with that for ARM (still not a perfect pass rate but not "this syscall is completely broken" as we had before). (Problem detected via a clang warning that the do_shmat() function was unused on Alpha.) Cc: Richard Henderson Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/alpha/syscall_nr.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux-user/alpha/syscall_nr.h b/linux-user/alpha/syscall_nr.h index 625f301674..dde8d5c6ad 100644 --- a/linux-user/alpha/syscall_nr.h +++ b/linux-user/alpha/syscall_nr.h @@ -185,6 +185,10 @@ #define TARGET_NR_osf_utsname 207 #define TARGET_NR_lchown 208 #define TARGET_NR_osf_shmat 209 +/* this has the usual shmat semantics so give it the name syscall.c expects + * so that our support for it is enabled. + */ +#define TARGET_NR_shmat TARGET_NR_osf_shmat #define TARGET_NR_shmctl 210 #define TARGET_NR_shmdt 211 #define TARGET_NR_shmget 212 From 1af2ee08f9b2f70d31676be14b26026223c9f660 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 8 Jan 2015 12:19:45 +0000 Subject: [PATCH 03/11] linux-user/arm/nwfpe: Delete unused aCC array The aCC array in fpopcode.c is completely unused in QEMU; delete it (silencing a clang warning). Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/arm/nwfpe/fpopcode.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/linux-user/arm/nwfpe/fpopcode.c b/linux-user/arm/nwfpe/fpopcode.c index 0dc5c9cd5d..0ada30c6b9 100644 --- a/linux-user/arm/nwfpe/fpopcode.c +++ b/linux-user/arm/nwfpe/fpopcode.c @@ -88,25 +88,3 @@ unsigned int getDestinationSize(const unsigned int opcode) return(nRc); } - -/* condition code lookup table - index into the table is test code: EQ, NE, ... LT, GT, AL, NV - bit position in short is condition code: NZCV */ -static const unsigned short aCC[16] = { - 0xF0F0, // EQ == Z set - 0x0F0F, // NE - 0xCCCC, // CS == C set - 0x3333, // CC - 0xFF00, // MI == N set - 0x00FF, // PL - 0xAAAA, // VS == V set - 0x5555, // VC - 0x0C0C, // HI == C set && Z clear - 0xF3F3, // LS == C clear || Z set - 0xAA55, // GE == (N==V) - 0x55AA, // LT == (N!=V) - 0x0A05, // GT == (!Z && (N==V)) - 0xF5FA, // LE == (Z || (N!=V)) - 0xFFFF, // AL always - 0 // NV -}; From b040bc9c0360106fab57bb1abe2d242bd17c4c32 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 8 Jan 2015 12:19:46 +0000 Subject: [PATCH 04/11] linux-user/main.c: Call cpu_exec_start/end on all target archs The start_exclusive() infrastructure is used on all target architectures, even if only to do the "stop all CPUs before dumping core" in force_sig(), so be consistent and call cpu_exec_start/end in the main loop of every target. Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/main.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/linux-user/main.c b/linux-user/main.c index 8c70be4c1b..95e8a519ce 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -283,7 +283,9 @@ void cpu_loop(CPUX86State *env) target_siginfo_t info; for(;;) { + cpu_exec_start(cs); trapnr = cpu_x86_exec(env); + cpu_exec_end(cs); switch(trapnr) { case 0x80: /* linux syscall from int $0x80 */ @@ -1288,7 +1290,9 @@ void cpu_loop (CPUSPARCState *env) target_siginfo_t info; while (1) { + cpu_exec_start(cs); trapnr = cpu_sparc_exec (env); + cpu_exec_end(cs); /* Compute PSR before exposing state. */ if (env->cc_op != CC_OP_FLAGS) { @@ -2656,7 +2660,9 @@ void cpu_loop(CPUOpenRISCState *env) int trapnr, gdbsig; for (;;) { + cpu_exec_start(cs); trapnr = cpu_exec(env); + cpu_exec_end(cs); gdbsig = 0; switch (trapnr) { @@ -2744,7 +2750,9 @@ void cpu_loop(CPUSH4State *env) target_siginfo_t info; while (1) { + cpu_exec_start(cs); trapnr = cpu_sh4_exec (env); + cpu_exec_end(cs); switch (trapnr) { case 0x160: @@ -2804,7 +2812,9 @@ void cpu_loop(CPUCRISState *env) target_siginfo_t info; while (1) { + cpu_exec_start(cs); trapnr = cpu_cris_exec (env); + cpu_exec_end(cs); switch (trapnr) { case 0xaa: { @@ -2863,7 +2873,9 @@ void cpu_loop(CPUMBState *env) target_siginfo_t info; while (1) { + cpu_exec_start(cs); trapnr = cpu_mb_exec (env); + cpu_exec_end(cs); switch (trapnr) { case 0xaa: { @@ -2966,7 +2978,9 @@ void cpu_loop(CPUM68KState *env) TaskState *ts = cs->opaque; for(;;) { + cpu_exec_start(cs); trapnr = cpu_m68k_exec(env); + cpu_exec_end(cs); switch(trapnr) { case EXCP_ILLEGAL: { @@ -3103,7 +3117,9 @@ void cpu_loop(CPUAlphaState *env) abi_long sysret; while (1) { + cpu_exec_start(cs); trapnr = cpu_alpha_exec (env); + cpu_exec_end(cs); /* All of the traps imply a transition through PALcode, which implies an REI instruction has been executed. Which means @@ -3289,7 +3305,9 @@ void cpu_loop(CPUS390XState *env) target_ulong addr; while (1) { + cpu_exec_start(cs); trapnr = cpu_s390x_exec(env); + cpu_exec_end(cs); switch (trapnr) { case EXCP_INTERRUPT: /* Just indicate that signals should be handled asap. */ From f7e61b222b2796ee43c976ec44c61a15d55ff662 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 8 Jan 2015 12:19:47 +0000 Subject: [PATCH 05/11] linux-user/main.c: Mark end_exclusive() as possibly unused The function end_exclusive() isn't used on all targets; mark it as such to avoid a clang warning. Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/main.c b/linux-user/main.c index 95e8a519ce..cfa7d07b7a 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -169,7 +169,7 @@ static inline void start_exclusive(void) } /* Finish an exclusive operation. */ -static inline void end_exclusive(void) +static inline void __attribute__((unused)) end_exclusive(void) { pending_cpus = 0; pthread_cond_broadcast(&exclusive_resume); From f6c7a05b8985df7eaf9942ca78e19890204eee4a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 8 Jan 2015 12:19:48 +0000 Subject: [PATCH 06/11] linux-user/signal.c: Remove unnecessary wrapper copy_siginfo_to_user The function copy_siginfo_to_user() just calls tswap_siginfo(), so call the latter function directly and delete the wrapper function. The wrapper is actually misleading since it implies that the semantics are like the kernel function with the same name which copies the data to a guest user-space address. In fact tswap_siginfo() just does data-structure conversion between two structures whose addresses are host addresses (the copy to userspace is handled in QEMU by the lock_user/unlock_user calls). This also fixes clang complaints about the wrapper being unused in some configs. Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/signal.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index fa955efed1..806571041b 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -732,12 +732,6 @@ int do_sigaction(int sig, const struct target_sigaction *act, return ret; } -static inline void copy_siginfo_to_user(target_siginfo_t *tinfo, - const target_siginfo_t *info) -{ - tswap_siginfo(tinfo, info); -} - #if defined(TARGET_I386) && TARGET_ABI_BITS == 32 /* from the Linux kernel */ @@ -986,7 +980,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, __put_user(addr, &frame->pinfo); addr = frame_addr + offsetof(struct rt_sigframe, uc); __put_user(addr, &frame->puc); - copy_siginfo_to_user(&frame->info, info); + tswap_siginfo(&frame->info, info); /* Create the ucontext. */ __put_user(0, &frame->uc.tuc_flags); @@ -1353,7 +1347,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka, env->pc = ka->_sa_handler; env->xregs[30] = return_addr; if (info) { - copy_siginfo_to_user(&frame->info, info); + tswap_siginfo(&frame->info, info); env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info); env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc); } @@ -1770,7 +1764,7 @@ static void setup_rt_frame_v1(int usig, struct target_sigaction *ka, __put_user(info_addr, &frame->pinfo); uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc); __put_user(uc_addr, &frame->puc); - copy_siginfo_to_user(&frame->info, info); + tswap_siginfo(&frame->info, info); /* Clear all the bits of the ucontext we don't use. */ memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext)); @@ -1808,7 +1802,7 @@ static void setup_rt_frame_v2(int usig, struct target_sigaction *ka, info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info); uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc); - copy_siginfo_to_user(&frame->info, info); + tswap_siginfo(&frame->info, info); setup_sigframe_v2(&frame->uc, set, env); @@ -3010,7 +3004,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn); - copy_siginfo_to_user(&frame->rs_info, info); + tswap_siginfo(&frame->rs_info, info); __put_user(0, &frame->rs_uc.tuc_flags); __put_user(0, &frame->rs_uc.tuc_link); @@ -3275,7 +3269,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) goto give_sigsegv; - copy_siginfo_to_user(&frame->info, info); + tswap_siginfo(&frame->info, info); /* Create the ucontext. */ __put_user(0, &frame->uc.tuc_flags); @@ -3934,7 +3928,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, __put_user(uc_addr, &frame->puc); if (ka->sa_flags & SA_SIGINFO) { - copy_siginfo_to_user(&frame->info, info); + tswap_siginfo(&frame->info, info); } /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/ @@ -4182,7 +4176,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, } qemu_log("%s: 1\n", __FUNCTION__); - copy_siginfo_to_user(&frame->info, info); + tswap_siginfo(&frame->info, info); /* Create the ucontext. */ __put_user(0, &frame->uc.tuc_flags); @@ -4757,7 +4751,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1)) goto sigsegv; - copy_siginfo_to_user(&rt_sf->info, info); + tswap_siginfo(&rt_sf->info, info); __put_user(0, &rt_sf->uc.tuc_flags); __put_user(0, &rt_sf->uc.tuc_link); @@ -5177,7 +5171,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc); __put_user(uc_addr, &frame->puc); - copy_siginfo_to_user(&frame->info, info); + tswap_siginfo(&frame->info, info); /* Create the ucontext */ @@ -5454,7 +5448,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, goto give_sigsegv; } - copy_siginfo_to_user(&frame->info, info); + tswap_siginfo(&frame->info, info); __put_user(0, &frame->uc.tuc_flags); __put_user(0, &frame->uc.tuc_link); From 95018018caeea209f58695645fd1d50a9d0ba6df Mon Sep 17 00:00:00 2001 From: Felix Janda Date: Tue, 2 Dec 2014 22:11:17 +0100 Subject: [PATCH 07/11] linux-user: translate resource also for prlimit64 The resource argument is translated from host to target for [gs]etprlimit but not for prlimit64. Fix this. Signed-off-by: Felix Janda Signed-off-by: Riku Voipio --- linux-user/syscall.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index aaac6a25ce..5658b66499 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -9529,6 +9529,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */ struct target_rlimit64 *target_rnew, *target_rold; struct host_rlimit64 rnew, rold, *rnewp = 0; + int resource = target_to_host_resource(arg2); if (arg3) { if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) { goto efault; @@ -9539,7 +9540,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, rnewp = &rnew; } - ret = get_errno(sys_prlimit64(arg1, arg2, rnewp, arg4 ? &rold : 0)); + ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0)); if (!is_error(ret) && arg4) { if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) { goto efault; From 9c6bf9c7d71d7da18a024182b69569969449d6f9 Mon Sep 17 00:00:00 2001 From: Ed Swierk Date: Tue, 16 Dec 2014 12:55:31 -0800 Subject: [PATCH 08/11] linux-user: Fix ioctl cmd type mismatch on 64-bit targets linux-user passes the cmd argument of the ioctl syscall as a signed long, but compares it to an unsigned int when iterating through the ioctl_entries list. When the cmd is a large value like 0x80047476 (TARGET_TIOCSWINSZ on mips64) it gets sign-extended to 0xffffffff80047476, causing the comparison to fail and resulting in lots of spurious "Unsupported ioctl" errors. Changing the target_cmd field in the ioctl_entries list to a signed int causes those values to be sign-extended as well during the comparison. Signed-off-by: Ed Swierk Signed-off-by: Riku Voipio --- linux-user/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5658b66499..683f8ccef5 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3278,7 +3278,7 @@ typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp, int fd, abi_long cmd, abi_long arg); struct IOCTLEntry { - unsigned int target_cmd; + int target_cmd; unsigned int host_cmd; const char *name; int access; From ec355f15476fe91b95c4326836d3fe572d8075e1 Mon Sep 17 00:00:00 2001 From: Ed Swierk Date: Tue, 16 Dec 2014 12:55:18 -0800 Subject: [PATCH 09/11] mips64-linux-user: Fix definition of struct sigaltstack Without this fix, qemu segfaults when emulating the sigaltstack syscall, because it incorrectly treats the ss_flags field as 64 bits rather than 32 bits. Signed-off-by: Ed Swierk Signed-off-by: Riku Voipio --- linux-user/mips64/target_signal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/mips64/target_signal.h b/linux-user/mips64/target_signal.h index 6e1dc8b6e6..5fb6a2ccfc 100644 --- a/linux-user/mips64/target_signal.h +++ b/linux-user/mips64/target_signal.h @@ -8,7 +8,7 @@ typedef struct target_sigaltstack { abi_long ss_sp; abi_ulong ss_size; - abi_long ss_flags; + abi_int ss_flags; } target_stack_t; From 1669add752d9f29283f8ebf6a863d7b1e2d0f146 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Dec 2014 17:47:00 +0000 Subject: [PATCH 10/11] linux-user: Fix broken m68k signal handling on 64 bit hosts The m68k signal frame setup code which writes the signal return trampoline code to the stack was assuming that a 'long' was 32 bits; on 64 bit systems this meant we would end up writing the 32 bit (2 insn) trampoline sequence to retaddr+4,retaddr+6 instead of the intended retaddr+0,retaddr+2, resulting in a guest crash when it tried to execute the invalid zero-bytes at retaddr+0. Fix by using uint32_t instead; also use uint16_t rather than short for consistency. This fixes bug LP:1404690. Reported-by: Michel Boaventura Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/signal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 806571041b..5bb399e16b 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -5066,7 +5066,7 @@ static void setup_frame(int sig, struct target_sigaction *ka, /* moveq #,d0; trap #0 */ __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16), - (long *)(frame->retcode)); + (uint32_t *)(frame->retcode)); /* Set up to return from userspace */ @@ -5200,8 +5200,8 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, /* moveq #,d0; notb d0; trap #0 */ __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16), - (long *)(frame->retcode + 0)); - __put_user(0x4e40, (short *)(frame->retcode + 4)); + (uint32_t *)(frame->retcode + 0)); + __put_user(0x4e40, (uint16_t *)(frame->retcode + 4)); if (err) goto give_sigsegv; From 30b8b68eb574fd68060eebcc4da790fdfe18d668 Mon Sep 17 00:00:00 2001 From: Alex Suykov Date: Tue, 23 Dec 2014 07:52:58 +0200 Subject: [PATCH 11/11] linux-user: support target-to-host SCM_CREDENTIALS When passing ancillary data through a unix socket, handle credentials properly instead of doing a simple copy and issuing a warning. Signed-off-by: Alex Suykov Signed-off-by: Riku Voipio --- linux-user/syscall.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 683f8ccef5..d4398b9c56 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1214,16 +1214,26 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type); cmsg->cmsg_len = CMSG_LEN(len); - if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { - gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); - memcpy(data, target_data, len); - } else { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int *fd = (int *)data; int *target_fd = (int *)target_data; int i, numfds = len / sizeof(int); for (i = 0; i < numfds; i++) fd[i] = tswap32(target_fd[i]); + } else if (cmsg->cmsg_level == SOL_SOCKET + && cmsg->cmsg_type == SCM_CREDENTIALS) { + struct ucred *cred = (struct ucred *)data; + struct target_ucred *target_cred = + (struct target_ucred *)target_data; + + __put_user(target_cred->pid, &cred->pid); + __put_user(target_cred->uid, &cred->uid); + __put_user(target_cred->gid, &cred->gid); + } else { + gemu_log("Unsupported ancillary data: %d/%d\n", + cmsg->cmsg_level, cmsg->cmsg_type); + memcpy(data, target_data, len); } cmsg = CMSG_NXTHDR(msgh, cmsg);