From patchwork Thu Sep 22 12:13:44 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 76769 Delivered-To: patch@linaro.org Received: by 10.140.106.72 with SMTP id d66csp10404qgf; Thu, 22 Sep 2016 05:44:55 -0700 (PDT) X-Received: by 10.200.35.44 with SMTP id a41mr1771305qta.25.1474548295692; Thu, 22 Sep 2016 05:44:55 -0700 (PDT) Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id f65si1025192qkj.9.2016.09.22.05.44.55 for (version=TLS1 cipher=AES128-SHA bits=128/128); Thu, 22 Sep 2016 05:44:55 -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; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:43211 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bn3N1-0002x7-4q for patch@linaro.org; Thu, 22 Sep 2016 08:44:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53367) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bn2uX-0000Kf-00 for qemu-devel@nongnu.org; Thu, 22 Sep 2016 08:15:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bn2uS-0006lq-UW for qemu-devel@nongnu.org; Thu, 22 Sep 2016 08:15:28 -0400 Received: from mail-lf0-f44.google.com ([209.85.215.44]:34360) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bn2uS-0006lb-Ic for qemu-devel@nongnu.org; Thu, 22 Sep 2016 08:15:24 -0400 Received: by mail-lf0-f44.google.com with SMTP id y6so65859091lff.1 for ; Thu, 22 Sep 2016 05:15:24 -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=l4zZQahV3WqNMYvto9MMyqvjqra9AASRtZeKqs67vl8=; b=aEtoZycws8BsqLHaEOr/smC7hSFvzKor0XZxGL4zOr5WnUfhl+WKUwkL+o4GsOzvuP CtgV0lkRUnAUaY0rAfozMKMh8H/iZ0gcDF2dEdiwDlM3en0//03HDnltauzQmenGIhey xBukDQY9QpBQJrAQM6WEwAG+jNtaRP5TSDoZE= 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=l4zZQahV3WqNMYvto9MMyqvjqra9AASRtZeKqs67vl8=; b=aZzv3pv6yNNGICiZEtJHqjwgrDVwLsrj9ZmsTsDoDxiC10NBx1CMFoG/MjFSEXUeym GVfeSkivPWJtcIG+aBlqOPgogaGRzghAZZJmbLhsZyiBzVyThXv6ezgzeZDJG331lRcN 33DN2+8egss0PiqB/eHo008FMS+Q1j7P/r4Nb/rQAWCzGqtOSfixzAmfs9HtJq1AywtI ZvHqBvTuCgfdgNTTw50DXW0YYO9r6hOh31DNSed4dNSLUvJS1lVqK9XoV4fUZZ06ZW23 Kj1v/EZ+8esKLDdN7G2ss/ReZvLuavFEzXYyu5i2P1B/cL7BJVgshY8tBEuJQg34XU4k 4LQQ== X-Gm-Message-State: AE9vXwMgGkxDrlZClMqoIIE+fLKJfFsDRyB4o43wcq8KwHpmaSsbyt3y8ZWdz7kpw1K7pfKg X-Received: by 10.25.23.222 with SMTP id 91mr770539lfx.182.1474546463537; Thu, 22 Sep 2016 05:14:23 -0700 (PDT) Received: from beaming.home (91-157-170-157.elisa-laajakaista.fi. [91.157.170.157]) by smtp.gmail.com with ESMTPSA id u14sm294378lja.11.2016.09.22.05.14.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 22 Sep 2016 05:14:22 -0700 (PDT) From: riku.voipio@linaro.org To: qemu-devel@nongnu.org Date: Thu, 22 Sep 2016 15:13:44 +0300 Message-Id: <5ea2fc84da1bffce749c9d0848f5336def2818bb.1474546244.git.riku.voipio@linaro.org> 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] [fuzzy] X-Received-From: 209.85.215.44 Subject: [Qemu-devel] [PULL 24/26] linux-user: Sanity check clone flags 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+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Peter Maydell We currently make no checks on the flags passed to the clone syscall, which means we will not fail clone attempts which ask for features that we can't implement. Add sanity checking of the flags to clone (which we were already doing in the "this is a fork" path, but not for the "this is a new thread" path), tidy up the checking in the fork path to match it, and check that the fork case isn't trying to specify a custom termination signal. This is helpful in causing some LTP test cases to fail cleanly rather than behaving bizarrely when we let the clone succeed but didn't provide the semantics requested by the flags. Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/syscall.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) -- 2.1.4 diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3b7b51f..d7e4d9f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -112,8 +112,56 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include "qemu.h" -#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \ - CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID) +#ifndef CLONE_IO +#define CLONE_IO 0x80000000 /* Clone io context */ +#endif + +/* We can't directly call the host clone syscall, because this will + * badly confuse libc (breaking mutexes, for example). So we must + * divide clone flags into: + * * flag combinations that look like pthread_create() + * * flag combinations that look like fork() + * * flags we can implement within QEMU itself + * * flags we can't support and will return an error for + */ +/* For thread creation, all these flags must be present; for + * fork, none must be present. + */ +#define CLONE_THREAD_FLAGS \ + (CLONE_VM | CLONE_FS | CLONE_FILES | \ + CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM) + +/* These flags are ignored: + * CLONE_DETACHED is now ignored by the kernel; + * CLONE_IO is just an optimisation hint to the I/O scheduler + */ +#define CLONE_IGNORED_FLAGS \ + (CLONE_DETACHED | CLONE_IO) + +/* Flags for fork which we can implement within QEMU itself */ +#define CLONE_OPTIONAL_FORK_FLAGS \ + (CLONE_SETTLS | CLONE_PARENT_SETTID | \ + CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID) + +/* Flags for thread creation which we can implement within QEMU itself */ +#define CLONE_OPTIONAL_THREAD_FLAGS \ + (CLONE_SETTLS | CLONE_PARENT_SETTID | \ + CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT) + +#define CLONE_INVALID_FORK_FLAGS \ + (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS)) + +#define CLONE_INVALID_THREAD_FLAGS \ + (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \ + CLONE_IGNORED_FLAGS)) + +/* CLONE_VFORK is special cased early in do_fork(). The other flag bits + * have almost all been allocated. We cannot support any of + * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC, + * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED. + * The checks against the invalid thread masks above will catch these. + * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.) + */ //#define DEBUG /* Define DEBUG_ERESTARTSYS to force every syscall to be restarted @@ -6013,6 +6061,8 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, CPUArchState *new_env; sigset_t sigmask; + flags &= ~CLONE_IGNORED_FLAGS; + /* Emulate vfork() with fork() */ if (flags & CLONE_VFORK) flags &= ~(CLONE_VFORK | CLONE_VM); @@ -6022,6 +6072,11 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, new_thread_info info; pthread_attr_t attr; + if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) || + (flags & CLONE_INVALID_THREAD_FLAGS)) { + return -TARGET_EINVAL; + } + ts = g_new0(TaskState, 1); init_task_state(ts); /* we create a new CPU instance. */ @@ -6083,7 +6138,12 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, pthread_mutex_unlock(&clone_lock); } else { /* if no CLONE_VM, we consider it is a fork */ - if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) { + if (flags & CLONE_INVALID_FORK_FLAGS) { + return -TARGET_EINVAL; + } + + /* We can't support custom termination signals */ + if ((flags & CSIGNAL) != TARGET_SIGCHLD) { return -TARGET_EINVAL; }