From patchwork Tue Jul 19 12:54:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 650174 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rv0Wc5Kp2z9sCy for ; Tue, 19 Jul 2016 23:00:12 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b=EgYv/1pN; dkim-atps=neutral Received: from localhost ([::1]:55706 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bPUd8-0004pq-F8 for incoming@patchwork.ozlabs.org; Tue, 19 Jul 2016 09:00:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42821) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bPUXb-0007Cj-TM for qemu-devel@nongnu.org; Tue, 19 Jul 2016 08:54:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bPUXZ-0003MD-NJ for qemu-devel@nongnu.org; Tue, 19 Jul 2016 08:54:26 -0400 Received: from mail-lf0-x236.google.com ([2a00:1450:4010:c07::236]:33641) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bPUXZ-0003M0-B9 for qemu-devel@nongnu.org; Tue, 19 Jul 2016 08:54:25 -0400 Received: by mail-lf0-x236.google.com with SMTP id b199so13471003lfe.0 for ; Tue, 19 Jul 2016 05:54:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=aRCqq+S9A/tBGO7ilAkus6OE/1+oH53L/mcju7fdT0w=; b=EgYv/1pNZo01uUL6NImNOoklhQesROhU1YYD9coDvUOwDAgOa4Z+72heBbnpcyDJwv HLIp4WI9bpJD5b6VqE3TQGVslo3CXAHPh8y2ZZFei0T/BjLmWGVSkLGEw4Fd2H2r2Llh hFmr+BKzI1hWKJcdCT99HQHhPknm/eIa2Y+hc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=aRCqq+S9A/tBGO7ilAkus6OE/1+oH53L/mcju7fdT0w=; b=CtdRZ4sozQVI+YBs2DQgjooTYYsuRdWQ4EZI2dGl1Agg8WQDx3DeBaxoRnZNgUm8w2 TAH14W64ZUFfJweqqCT7q29quZlGEiAI8/4Kaf8KyN38KI6MKAp3yQgiYDYINEVpHuVI 0H9sBhgUCQkYdhZBKovz74dZCvszeLdwCxFN9j3XMOUOcW/GFTVhsLt6pxxUgAtdpynD 5SDYY/eCnYQPX5kl8B4n+l1v7nsXzdVXFSXrt/5mCMaJ5YNTT5EBsX2u+F+ygsJCpvZq EtEYIav+L6VCLxHZFyCtcklB3iqhSjGq9dZ9npqM2TeGhjgbpS6tvAjJ8AFugst4rlWH UeAw== X-Gm-Message-State: ALyK8tJbvwWOkr+mNWfmBCiZMY1FEmIxAHcePZSij4iyYR/1T2WnE8tRsWpHjIS7uM50SW+u X-Received: by 10.46.0.97 with SMTP id 94mr17210229lja.60.1468932864458; Tue, 19 Jul 2016 05:54:24 -0700 (PDT) Received: from beaming.home (91-157-170-157.elisa-laajakaista.fi. [91.157.170.157]) by smtp.gmail.com with ESMTPSA id g3sm2248898lfe.14.2016.07.19.05.54.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 19 Jul 2016 05:54:23 -0700 (PDT) From: riku.voipio@linaro.org To: qemu-devel@nongnu.org Date: Tue, 19 Jul 2016 15:54:04 +0300 Message-Id: X-Mailer: git-send-email 2.1.4 In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:4010:c07::236 Subject: [Qemu-devel] [PULL 06/16] linux-user: Check sigsetsize argument to syscalls X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Peter Maydell Many syscalls which take a sigset_t argument also take an argument giving the size of the sigset_t. The kernel insists that this matches its idea of the type size and fails EINVAL if it is not. Implement this logic in QEMU. (This mostly just means some LTP test cases which check error cases now pass.) Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio Reviewed-by: Laurent Vivier --- linux-user/syscall.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 761d8fb..0a99af8 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7978,7 +7978,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_ALPHA) struct target_sigaction act, oact, *pact = 0; struct target_rt_sigaction *rt_act; - /* ??? arg4 == sizeof(sigset_t). */ + + if (arg4 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } if (arg2) { if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1)) goto efault; @@ -8002,6 +8006,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, struct target_sigaction *act; struct target_sigaction *oact; + if (arg4 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } if (arg2) { if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) goto efault; @@ -8133,6 +8141,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, int how = arg1; sigset_t set, oldset, *set_ptr; + if (arg4 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } + if (arg2) { switch(how) { case TARGET_SIG_BLOCK: @@ -8183,6 +8196,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_rt_sigpending: { sigset_t set; + + /* Yes, this check is >, not != like most. We follow the kernel's + * logic and it does it like this because it implements + * NR_sigpending through the same code path, and in that case + * the old_sigset_t is smaller in size. + */ + if (arg2 > sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } + ret = get_errno(sigpending(&set)); if (!is_error(ret)) { if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0))) @@ -8216,6 +8240,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_rt_sigsuspend: { TaskState *ts = cpu->opaque; + + if (arg2 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) goto efault; target_to_host_sigset(&ts->sigsuspend_mask, p); @@ -8233,6 +8262,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, struct timespec uts, *puts; siginfo_t uinfo; + if (arg4 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } + if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) goto efault; target_to_host_sigset(&set, p); @@ -9484,6 +9518,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } if (arg4) { + if (arg5 != sizeof(target_sigset_t)) { + unlock_user(target_pfd, arg1, 0); + ret = -TARGET_EINVAL; + break; + } + target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1); if (!target_set) { unlock_user(target_pfd, arg1, 0); @@ -11303,6 +11343,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, sigset_t _set, *set = &_set; if (arg5) { + if (arg6 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } + target_set = lock_user(VERIFY_READ, arg5, sizeof(target_sigset_t), 1); if (!target_set) {