From patchwork Wed Mar 19 14:03:01 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 26586 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pa0-f71.google.com (mail-pa0-f71.google.com [209.85.220.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 2B76220534 for ; Wed, 19 Mar 2014 14:07:31 +0000 (UTC) Received: by mail-pa0-f71.google.com with SMTP id kq14sf22578721pab.6 for ; Wed, 19 Mar 2014 07:07:30 -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=Gm25xNnO2NsRG6DH1pq2FXoauoL0vYYkeJrjb827Ezg=; b=ImcG4sziuTe6QCURCj4oy9M6/8ywLuOixbmp0dxsfkZJmRhCw7Eh4Q1Hnfi4HxX4uk aHFiKyaCMSqQc4paqO33A7yHzSZY8+XadNbkLoPqbLm82Hsk2Ybp/mIT0ApD27k1fzeQ ki8uTCaq/cqwo+ggR7urnbsjoV5EAwP5gmPtaMwfKPPsrMz8PtlyEyWNJr40L/XyndvF r0vZgLaT6fDOtw5+7Mt40Y9ySAwFS5BBhqT+8lXVggVsiCsqGKrdR9+oenyS1IBOVtOU tsLAC4QLyySEe4LqYUTFKKd+Py8Bx20TXAjTXFiYg6HTQPB2dpk66U0CzTMUoz6OLXi7 RSWA== X-Gm-Message-State: ALoCoQk033k/kejgLOq220TAtf/s9OxV7MWohKGedrDCbt4DyDU3Wn4uyxWUge8iwTuLbUar2DTR X-Received: by 10.66.140.8 with SMTP id rc8mr14731051pab.41.1395238050434; Wed, 19 Mar 2014 07:07:30 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.32.181 with SMTP id h50ls2450768qgh.15.gmail; Wed, 19 Mar 2014 07:07:30 -0700 (PDT) X-Received: by 10.58.185.145 with SMTP id fc17mr31094443vec.14.1395238050226; Wed, 19 Mar 2014 07:07:30 -0700 (PDT) Received: from mail-ve0-f182.google.com (mail-ve0-f182.google.com [209.85.128.182]) by mx.google.com with ESMTPS id rx10si3467298vdc.60.2014.03.19.07.07.30 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 19 Mar 2014 07:07:30 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.182 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.182; Received: by mail-ve0-f182.google.com with SMTP id jw12so9064951veb.27 for ; Wed, 19 Mar 2014 07:07:30 -0700 (PDT) X-Received: by 10.52.108.164 with SMTP id hl4mr3258411vdb.25.1395238050111; Wed, 19 Mar 2014 07:07:30 -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 i9csp302546vck; Wed, 19 Mar 2014 07:07:29 -0700 (PDT) X-Received: by 10.180.106.167 with SMTP id gv7mr20215790wib.40.1395238048496; Wed, 19 Mar 2014 07:07:28 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [208.118.235.17]) by mx.google.com with ESMTPS id ks9si14802468wjc.57.2014.03.19.07.07.27 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 19 Mar 2014 07:07:28 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; Received: from localhost ([::1]:41585 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WQH9T-0005N3-5U for patch@linaro.org; Wed, 19 Mar 2014 10:07:27 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54647) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WQH5O-0007nq-Ma for qemu-devel@nongnu.org; Wed, 19 Mar 2014 10:03:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WQH5H-00062B-6P for qemu-devel@nongnu.org; Wed, 19 Mar 2014 10:03:14 -0400 Received: from afflict.kos.to ([92.243.29.197]:54524) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WQH5G-0005za-MN 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 6206D26569; 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:01 +0200 Message-Id: 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 , Anthony Liguori Subject: [Qemu-devel] [PULL for-2.0 6/7] linux-user: Don't allow guest to block SIGSEGV 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.182 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: Peter Maydell 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 Signed-off-by: Riku Voipio --- 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 9e6a495..e5fb933 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) {