From patchwork Fri Mar 14 14:36:56 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 26257 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ve0-f198.google.com (mail-ve0-f198.google.com [209.85.128.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 2D5BC202DD for ; Fri, 14 Mar 2014 14:37:02 +0000 (UTC) Received: by mail-ve0-f198.google.com with SMTP id oz11sf6017922veb.5 for ; Fri, 14 Mar 2014 07:37:01 -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:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=Lbx2mfE0b3cIWzoy4/DHlPf/XA/AWB8hznm0LbJSUjU=; b=HyQ+oK6k7ShOQiVabZ5sba407UWExkEpvuvQEmWtaPtubdE0/HiWScdwlrtJF20q8e phPYEl8oM13Kwg7Ok2pa5O9x13H/lPKc/1XtnbC+qegMibz7Xs7XGhsvXRu3bhnuKySG MUj51EvcBwW1zrYxi+W/VMtY4EN5ygX4GEoGrxXwD1OlwxpWtYDSdtMXcrLT019OS+/7 +yVw7+sfltSDPKEz+48K6Khpm8BCbcgC10frXo5nvknyaI4wckTUUPlviu5BuLLbu3bg KY9ajwj4/MZhCJmMo3Aj4nTod7K+hJlqKPiMVIKOVZojTAxCR1atDRvZu1C8nC15Hw4J bGEQ== X-Gm-Message-State: ALoCoQn701Kyr9IA1kwPyHXblS49/r4W35SKWqC8Fln79fIoNdPah/8xjUVHK32xKf8ifFOTpPFt X-Received: by 10.58.22.166 with SMTP id e6mr3469312vef.6.1394807821850; Fri, 14 Mar 2014 07:37:01 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.84.103 with SMTP id k94ls698998qgd.39.gmail; Fri, 14 Mar 2014 07:37:01 -0700 (PDT) X-Received: by 10.52.230.105 with SMTP id sx9mr5643153vdc.10.1394807821708; Fri, 14 Mar 2014 07:37:01 -0700 (PDT) Received: from mail-vc0-f176.google.com (mail-vc0-f176.google.com [209.85.220.176]) by mx.google.com with ESMTPS id pd4si614841veb.159.2014.03.14.07.37.01 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 14 Mar 2014 07:37:01 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.176 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.176; Received: by mail-vc0-f176.google.com with SMTP id lc6so2768805vcb.21 for ; Fri, 14 Mar 2014 07:37:01 -0700 (PDT) X-Received: by 10.58.188.78 with SMTP id fy14mr1362572vec.23.1394807821603; Fri, 14 Mar 2014 07:37:01 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.78.9 with SMTP id i9csp22991vck; Fri, 14 Mar 2014 07:37:01 -0700 (PDT) X-Received: by 10.14.4.6 with SMTP id 6mr8496694eei.47.1394807819921; Fri, 14 Mar 2014 07:36:59 -0700 (PDT) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id s46si3537474eeg.135.2014.03.14.07.36.58 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 14 Mar 2014 07:36:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::1 as permitted sender) client-ip=2001:8b0:1d0::1; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1WOTEG-0003ml-TB; Fri, 14 Mar 2014 14:36:56 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Riku Voipio , Dann Frazier , Alexander Graf , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Michael Matz Subject: [PATCH 2/2] linux-user: Don't allow guest to block SIGSEGV Date: Fri, 14 Mar 2014 14:36:56 +0000 Message-Id: <1394807816-14514-4-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1394807816-14514-1-git-send-email-peter.maydell@linaro.org> References: <1394807816-14514-1-git-send-email-peter.maydell@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.176 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 Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Don't allow the linux-user guest to block SIGSEGV -- QEMU needs this signal to detect accesses to pages which it has marked read-only because it has cached translated code from them. We implement this by making the do_sigprocmask() wrapper suppress SIGSEGV when doing the host process signal mask manipulation; instead we store the current state of SIGSEGV in the TaskState struct. If we get a SIGSEGV for the guest when the guest has blocked the signal, we treat it as if the default SEGV handler was in place, as the kernel does for forced SIGSEGV delivery. This patch is based on an idea by Alex Barcelo, but rather than simply lying to the guest about the SIGSEGV state we track it. Signed-off-by: Peter Maydell Reported-by: Alex Barcelo --- linux-user/qemu.h | 1 + linux-user/signal.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 4d24e74..36d4a73 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -126,6 +126,7 @@ typedef struct TaskState { #endif uint32_t stack_base; int used; /* non zero if used */ + bool sigsegv_blocked; /* SIGSEGV blocked by guest */ struct image_info *info; struct linux_binprm *bprm; diff --git a/linux-user/signal.c b/linux-user/signal.c index c8df584..f18f3d3 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -204,7 +204,46 @@ void target_to_host_old_sigset(sigset_t *sigset, */ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) { - return sigprocmask(how, set, oldset); + int ret; + sigset_t val; + sigset_t *temp = NULL; + CPUState *cpu = thread_cpu; + TaskState *ts = (TaskState *)cpu->opaque; + bool segv_was_blocked = ts->sigsegv_blocked; + + if (set) { + bool has_sigsegv = sigismember(set, SIGSEGV); + val = *set; + temp = &val; + + sigdelset(temp, SIGSEGV); + + switch (how) { + case SIG_BLOCK: + if (has_sigsegv) { + ts->sigsegv_blocked = true; + } + break; + case SIG_UNBLOCK: + if (has_sigsegv) { + ts->sigsegv_blocked = false; + } + break; + case SIG_SETMASK: + ts->sigsegv_blocked = has_sigsegv; + break; + default: + g_assert_not_reached(); + } + } + + ret = sigprocmask(how, temp, oldset); + + if (oldset && segv_was_blocked) { + sigaddset(oldset, SIGSEGV); + } + + return ret; } /* siginfo conversion */ @@ -468,6 +507,19 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info) k = &ts->sigtab[sig - 1]; queue = gdb_queuesig (); handler = sigact_table[sig - 1]._sa_handler; + + if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) { + /* Guest has blocked SIGSEGV but we got one anyway. Assume this + * is a forced SIGSEGV (ie one the kernel handles via force_sig_info + * because it got a real MMU fault). A blocked SIGSEGV in that + * situation is treated as if using the default handler. This is + * not correct if some other process has randomly sent us a SIGSEGV + * via kill(), but that is not easy to distinguish at this point, + * so we assume it doesn't happen. + */ + handler = TARGET_SIG_DFL; + } + if (!queue && handler == TARGET_SIG_DFL) { if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) { kill(getpid(),SIGSTOP); @@ -5726,6 +5778,14 @@ void process_pending_signals(CPUArchState *cpu_env) handler = sa->_sa_handler; } + if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) { + /* Guest has blocked SIGSEGV but we got one anyway. Assume this + * is a forced SIGSEGV (ie one the kernel handles via force_sig_info + * because it got a real MMU fault), and treat as if default handler. + */ + handler = TARGET_SIG_DFL; + } + if (handler == TARGET_SIG_DFL) { /* default handler : ignore some signal. The other are job control or fatal */ if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {