From patchwork Wed Mar 19 14:03:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 26585 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f70.google.com (mail-oa0-f70.google.com [209.85.219.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id CAFFE20534 for ; Wed, 19 Mar 2014 14:06:12 +0000 (UTC) Received: by mail-oa0-f70.google.com with SMTP id n16sf33497478oag.1 for ; Wed, 19 Mar 2014 07:06:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:date :message-id:in-reply-to:references:cc:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=FYmirDAUSti/p6Czf6X4HWP4OM4tLJYJi2XvUl2tFWs=; b=J/VeyU5FLfyb/7hIB9JbKTSw47ltOjHHAd0XjrBEFIWLCYnsPe6mXjF17Cn0g7R1t2 9Rp9kL50ugorqGqzpujQEvydeOy0aFv2gqrZQeJY6cemWwzaB0PQIdWDqw+vbJkUsrSP U3d3oIurDMRcmyjiy9YtcU5Rcr+PUDf0TewpRjjncRzsX38YnNfIdraDZaX6TJX/kxSH 8fas/LYL4klY2oPBHwf7r2EnVAErjyn6xHxyu4K0OHhjm5wRQrai4CtmNRBWDHlBimol gpldSsw7eX2vTVTf6ceckCK6B0E42Kp8fIOTgkHKIGGAIOvZh6D/86YIG0ZCA2aQtBIh P+IQ== X-Gm-Message-State: ALoCoQmqYH/sT14NiLLKU9pdY0WdHQ1j75Ta6DaYe5axqDClr3FvQP4YKZBDnwJ7no/zEZ6Ivs2Z X-Received: by 10.182.126.137 with SMTP id my9mr1070732obb.13.1395237972336; Wed, 19 Mar 2014 07:06:12 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.86.233 with SMTP id p96ls2342146qgd.33.gmail; Wed, 19 Mar 2014 07:06:12 -0700 (PDT) X-Received: by 10.221.74.65 with SMTP id yv1mr589554vcb.31.1395237972063; Wed, 19 Mar 2014 07:06:12 -0700 (PDT) Received: from mail-ve0-f180.google.com (mail-ve0-f180.google.com [209.85.128.180]) by mx.google.com with ESMTPS id mp4si176288vcb.4.2014.03.19.07.06.12 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 19 Mar 2014 07:06:12 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.180 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.180; Received: by mail-ve0-f180.google.com with SMTP id jz11so8671040veb.25 for ; Wed, 19 Mar 2014 07:06:12 -0700 (PDT) X-Received: by 10.52.242.167 with SMTP id wr7mr1304578vdc.32.1395237971965; Wed, 19 Mar 2014 07:06:11 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.78.9 with SMTP id i9csp302428vck; Wed, 19 Mar 2014 07:06:11 -0700 (PDT) X-Received: by 10.180.89.102 with SMTP id bn6mr19903875wib.28.1395237970608; Wed, 19 Mar 2014 07:06:10 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id wi6si14769128wjb.168.2014.03.19.07.06.09 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 19 Mar 2014 07:06:10 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:41573 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WQH8C-00030x-KP for patch@linaro.org; Wed, 19 Mar 2014 10:06:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54631) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WQH5M-0007ln-OH for qemu-devel@nongnu.org; Wed, 19 Mar 2014 10:03:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WQH5H-000624-5o for qemu-devel@nongnu.org; Wed, 19 Mar 2014 10:03:12 -0400 Received: from afflict.kos.to ([92.243.29.197]:54523) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WQH5G-0005ze-O6 for qemu-devel@nongnu.org; Wed, 19 Mar 2014 10:03:07 -0400 Received: from localhost.localdomain (afflict [92.243.29.197]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by afflict.kos.to (Postfix) with ESMTPSA id 55EA426568; Wed, 19 Mar 2014 15:03:04 +0100 (CET) From: riku.voipio@linaro.org To: qemu-devel@nongnu.org Date: Wed, 19 Mar 2014 16:03:00 +0200 Message-Id: <1c275925bfbbc2de84a8f0e09d1dd70bbefb6da3.1395237255.git.riku.voipio@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 92.243.29.197 Cc: Peter Maydell , Alex Barcelo , Anthony Liguori Subject: [Qemu-devel] [PULL for-2.0 5/7] signal: added a wrapper for sigprocmask function X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: riku.voipio@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.180 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 From: Alex Barcelo Create a wrapper for signal mask changes initiated by the guest; (this includes syscalls and also the sigreturns from signal.c) this will give us a place to put code which prevents the guest from changing the handling of signals used by QEMU itself internally. The wrapper is called from all the guest-initiated sigprocmask, but is not called from internal qemu sigprocmask calls. Signed-off-by: Alex Barcelo [PMM: Added calls to wrapper for sigprocmask uses in signal.c when setting the signal mask on entry and exit from signal handlers, since these also are guest-provided signal masks.] Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/qemu.h | 1 + linux-user/signal.c | 58 ++++++++++++++++++++++++++++++---------------------- linux-user/syscall.c | 14 ++++++------- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index c2f74f3..4d24e74 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -235,6 +235,7 @@ int host_to_target_signal(int sig); long do_sigreturn(CPUArchState *env); long do_rt_sigreturn(CPUArchState *env); abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp); +int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset); #ifdef TARGET_I386 /* vm86.c */ diff --git a/linux-user/signal.c b/linux-user/signal.c index 209855e..9e6a495 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -197,6 +197,16 @@ void target_to_host_old_sigset(sigset_t *sigset, target_to_host_sigset(sigset, &d); } +/* Wrapper for sigprocmask function + * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset + * are host signal set, not guest ones. This wraps the sigprocmask host calls + * that should be protected (calls originated from guest) + */ +int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) +{ + return sigprocmask(how, set, oldset); +} + /* siginfo conversion */ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, @@ -1056,7 +1066,7 @@ long do_sigreturn(CPUX86State *env) } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); /* restore registers */ if (restore_sigcontext(env, &frame->sc, &eax)) @@ -1081,7 +1091,7 @@ long do_rt_sigreturn(CPUX86State *env) if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) goto badframe; target_to_host_sigset(&set, &frame->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) goto badframe; @@ -1220,7 +1230,7 @@ static int target_restore_sigframe(CPUARMState *env, uint64_t pstate; target_to_host_sigset(&set, &sf->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); for (i = 0; i < 31; i++) { __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]); @@ -1861,7 +1871,7 @@ static long do_sigreturn_v1(CPUARMState *env) } target_to_host_sigset_internal(&host_set, &set); - sigprocmask(SIG_SETMASK, &host_set, NULL); + do_sigprocmask(SIG_SETMASK, &host_set, NULL); if (restore_sigcontext(env, &frame->sc)) goto badframe; @@ -1942,7 +1952,7 @@ static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr, abi_ulong *regspace; target_to_host_sigset(&host_set, &uc->tuc_sigmask); - sigprocmask(SIG_SETMASK, &host_set, NULL); + do_sigprocmask(SIG_SETMASK, &host_set, NULL); if (restore_sigcontext(env, &uc->tuc_mcontext)) return 1; @@ -2033,7 +2043,7 @@ static long do_rt_sigreturn_v1(CPUARMState *env) goto badframe; target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &host_set, NULL); + do_sigprocmask(SIG_SETMASK, &host_set, NULL); if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) goto badframe; @@ -2444,7 +2454,7 @@ long do_sigreturn(CPUSPARCState *env) } target_to_host_sigset_internal(&host_set, &set); - sigprocmask(SIG_SETMASK, &host_set, NULL); + do_sigprocmask(SIG_SETMASK, &host_set, NULL); if (err) goto segv_and_exit; @@ -2567,7 +2577,7 @@ void sparc64_set_context(CPUSPARCState *env) goto do_sigsegv; } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); } env->pc = pc; env->npc = npc; @@ -2656,7 +2666,7 @@ void sparc64_get_context(CPUSPARCState *env) err = 0; - sigprocmask(0, NULL, &set); + do_sigprocmask(0, NULL, &set); host_to_target_sigset_internal(&target_set, &set); if (TARGET_NSIG_WORDS == 1) { err |= __put_user(target_set.sig[0], @@ -2991,7 +3001,7 @@ long do_sigreturn(CPUMIPSState *regs) } target_to_host_sigset_internal(&blocked, &target_set); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (restore_sigcontext(regs, &frame->sf_sc)) goto badframe; @@ -3095,7 +3105,7 @@ long do_rt_sigreturn(CPUMIPSState *env) goto badframe; target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (restore_sigcontext(env, &frame->rs_uc.tuc_mcontext)) goto badframe; @@ -3385,7 +3395,7 @@ long do_sigreturn(CPUSH4State *regs) goto badframe; target_to_host_sigset_internal(&blocked, &target_set); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (restore_sigcontext(regs, &frame->sc, &r0)) goto badframe; @@ -3414,7 +3424,7 @@ long do_rt_sigreturn(CPUSH4State *regs) goto badframe; target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0)) goto badframe; @@ -3644,7 +3654,7 @@ long do_sigreturn(CPUMBState *env) goto badframe; } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); restore_sigcontext(&frame->uc.tuc_mcontext, env); /* We got here through a sigreturn syscall, our path back is via an @@ -3819,7 +3829,7 @@ long do_sigreturn(CPUCRISState *env) goto badframe; } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); restore_sigcontext(&frame->sc, env); unlock_user_struct(frame, frame_addr, 0); @@ -4350,7 +4360,7 @@ long do_sigreturn(CPUS390XState *env) } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ + do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ if (restore_sigregs(env, &frame->sregs)) { goto badframe; @@ -4378,7 +4388,7 @@ long do_rt_sigreturn(CPUS390XState *env) } target_to_host_sigset(&set, &frame->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ + do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ if (restore_sigregs(env, &frame->uc.tuc_mcontext)) { goto badframe; @@ -4906,7 +4916,7 @@ long do_sigreturn(CPUPPCState *env) goto sigsegv; #endif target_to_host_sigset_internal(&blocked, &set); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (__get_user(sr_addr, &sc->regs)) goto sigsegv; @@ -4950,7 +4960,7 @@ static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig) return 1; target_to_host_sigset_internal(&blocked, &set); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (restore_user_regs(env, mcp, sig)) goto sigsegv; @@ -5324,7 +5334,7 @@ long do_sigreturn(CPUM68KState *env) } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); /* restore registers */ @@ -5352,7 +5362,7 @@ long do_rt_sigreturn(CPUM68KState *env) goto badframe; target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); /* restore registers */ @@ -5599,7 +5609,7 @@ long do_sigreturn(CPUAlphaState *env) } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); if (restore_sigcontext(env, sc)) { goto badframe; @@ -5622,7 +5632,7 @@ long do_rt_sigreturn(CPUAlphaState *env) goto badframe; } target_to_host_sigset(&set, &frame->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) { goto badframe; @@ -5739,7 +5749,7 @@ void process_pending_signals(CPUArchState *cpu_env) sigaddset(&set, target_to_host_signal(sig)); /* block signals in the handler using Linux */ - sigprocmask(SIG_BLOCK, &set, &old_set); + do_sigprocmask(SIG_BLOCK, &set, &old_set); /* save the previous blocked signal state to restore it at the end of the signal execution (see do_sigreturn) */ host_to_target_sigset_internal(&target_old_set, &old_set); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b8086b8..e404a32 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6029,7 +6029,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { sigset_t cur_set; abi_ulong target_set; - sigprocmask(0, NULL, &cur_set); + do_sigprocmask(0, NULL, &cur_set); host_to_target_old_sigset(&target_set, &cur_set); ret = target_set; } @@ -6040,10 +6040,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { sigset_t set, oset, cur_set; abi_ulong target_set = arg1; - sigprocmask(0, NULL, &cur_set); + do_sigprocmask(0, NULL, &cur_set); target_to_host_old_sigset(&set, &target_set); sigorset(&set, &set, &cur_set); - sigprocmask(SIG_SETMASK, &set, &oset); + do_sigprocmask(SIG_SETMASK, &set, &oset); host_to_target_old_sigset(&target_set, &oset); ret = target_set; } @@ -6074,7 +6074,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, mask = arg2; target_to_host_old_sigset(&set, &mask); - ret = get_errno(sigprocmask(how, &set, &oldset)); + ret = get_errno(do_sigprocmask(how, &set, &oldset)); if (!is_error(ret)) { host_to_target_old_sigset(&mask, &oldset); ret = mask; @@ -6108,7 +6108,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, how = 0; set_ptr = NULL; } - ret = get_errno(sigprocmask(how, set_ptr, &oldset)); + ret = get_errno(do_sigprocmask(how, set_ptr, &oldset)); if (!is_error(ret) && arg3) { if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0))) goto efault; @@ -6148,7 +6148,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, how = 0; set_ptr = NULL; } - ret = get_errno(sigprocmask(how, set_ptr, &oldset)); + ret = get_errno(do_sigprocmask(how, set_ptr, &oldset)); if (!is_error(ret) && arg3) { if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0))) goto efault; @@ -8161,7 +8161,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } mask = arg2; target_to_host_old_sigset(&set, &mask); - sigprocmask(how, &set, &oldset); + do_sigprocmask(how, &set, &oldset); host_to_target_old_sigset(&mask, &oldset); ret = mask; }