From patchwork Tue Aug 8 01:59:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 9886437 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id CCB7860363 for ; Tue, 8 Aug 2017 01:59:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BD1242874F for ; Tue, 8 Aug 2017 01:59:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B189328750; Tue, 8 Aug 2017 01:59:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B0DDC28759 for ; Tue, 8 Aug 2017 01:59:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751971AbdHHB7i (ORCPT ); Mon, 7 Aug 2017 21:59:38 -0400 Received: from mail-pf0-f182.google.com ([209.85.192.182]:32885 "EHLO mail-pf0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751961AbdHHB7O (ORCPT ); Mon, 7 Aug 2017 21:59:14 -0400 Received: by mail-pf0-f182.google.com with SMTP id h68so8406627pfk.0 for ; Mon, 07 Aug 2017 18:59:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WSaeX4UIZJqsVEo9H7OaV8NThmzkTUzCaLmolinHlWk=; b=UZMSGvu6aqyMSygr4+3GlzX/ognRYvOYB/+dC/nL/WOGuMgpeKTGtQBfRmFeWoI/qq GkGA8GU5EAu0jAYqY003HBPwA/Xb35LJ+9Mc373c7IlSEApPmKsIh9Ya4CU9I2fOhnvv ebB4ybkbXegHSb8fj0Uvq9+/tnK/8EZHdt0kE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WSaeX4UIZJqsVEo9H7OaV8NThmzkTUzCaLmolinHlWk=; b=rn0rBgsRZVtP2MEyoeay/lX9F4pVeHcC2dPpd4LlSVv8/lYNmI+48AJF+A1hpPzwo6 OI1iiFQ3schxm8cymX7jLhiOr7+3iGDWWeuj04Lo2nUotM15opsLSHuUPuxfY9s3a73R dv20y0VSWwAj9KcaRFQHO9zzHCHWwWFvrQhkRSK/9p+VUsldU7pBxFpCdt8dDYxGuzBX +p2UEPm/T30QlEr20JoHrVK8qtT3SId9m6KEmm/RN5f+l4cHUCDNckzjf2m05UiU+g4X I4iI1p7auKZuV5VtAFLXv4m1p77KjJNRLhwwYkgR75yjCoHQlWYAdM7sMDP0umHY9Oph onjg== X-Gm-Message-State: AHYfb5ihfzUZE9t1oOuIIaS7XRYstbVl5d/uDJ//72F/Fy02ywm+VILX Xe5/kqd56TdEtmQY X-Received: by 10.84.253.8 with SMTP id z8mr2834340pll.303.1502157553954; Mon, 07 Aug 2017 18:59:13 -0700 (PDT) Received: from www.outflux.net (173-164-112-133-Oregon.hfc.comcastbusiness.net. [173.164.112.133]) by smtp.gmail.com with ESMTPSA id h29sm180774pfd.145.2017.08.07.18.59.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Aug 2017 18:59:10 -0700 (PDT) From: Kees Cook To: linux-kernel@vger.kernel.org Cc: Kees Cook , Fabricio Voznika , Tyler Hicks , Andy Lutomirski , Will Drewry , Shuah Khan , linux-kselftest@vger.kernel.org, linux-security-module@vger.kernel.org Subject: [PATCH v2 2/4] seccomp: Add SECCOMP_FILTER_FLAG_KILL_PROCESS Date: Mon, 7 Aug 2017 18:59:06 -0700 Message-Id: <1502157548-111843-3-git-send-email-keescook@chromium.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1502157548-111843-1-git-send-email-keescook@chromium.org> References: <1502157548-111843-1-git-send-email-keescook@chromium.org> Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Right now, SECCOMP_RET_KILL kills the current thread. There have been a few requests for RET_KILL to kill the entire process (the thread group), but since seccomp's u32 return values are ABI, and ordered by lowest value, with RET_KILL as 0, there isn't a trivial way to provide an even smaller value that would mean the more restrictive action of killing the thread group. Instead, create a filter flag that indicates that a RET_KILL from this filter must kill the process rather than the thread. This can be set (and not cleared) via the new SECCOMP_FILTER_FLAG_KILL_PROCESS flag. Pros: - the logic for the filter action is contained in the filter. - userspace can detect support for the feature since earlier kernels will reject the new flag. Cons: - depends on adding an assignment to the seccomp_run_filters() loop (previous patch). Alternatives to this approach with pros/cons: - Use a new test during seccomp_run_filters() that treats the RET_DATA mask of a RET_KILL action as special. If a new bit is set in the data, then treat the return value as -1 (lower than 0). Pros: - the logic for the filter action is contained in the filter. Cons: - added complexity to time-sensitive seccomp_run_filters() loop. - there isn't a trivial way for userspace to detect if the kernel supports the feature (earlier kernels will silently ignore the RET_DATA and only kill the thread). - Have SECCOMP_FILTER_FLAG_KILL_PROCESS attach to the seccomp struct rather than the filter. Pros: - no change needed to seccomp_run_filters() loop. Cons: - the change in behavior technically originates external to the filter, which allows for later filters to "enhance" a previously applied filter's RET_KILL to kill the entire process, which may be unexpected. Signed-off-by: Kees Cook Reviewed-by: Tyler Hicks --- include/linux/seccomp.h | 3 ++- include/uapi/linux/seccomp.h | 3 ++- kernel/seccomp.c | 22 +++++++++++++++++++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h index ecc296c137cd..59d001ba655c 100644 --- a/include/linux/seccomp.h +++ b/include/linux/seccomp.h @@ -3,7 +3,8 @@ #include -#define SECCOMP_FILTER_FLAG_MASK (SECCOMP_FILTER_FLAG_TSYNC) +#define SECCOMP_FILTER_FLAG_MASK (SECCOMP_FILTER_FLAG_TSYNC | \ + SECCOMP_FILTER_FLAG_KILL_PROCESS) #ifdef CONFIG_SECCOMP diff --git a/include/uapi/linux/seccomp.h b/include/uapi/linux/seccomp.h index 0f238a43ff1e..4b75d8c297b6 100644 --- a/include/uapi/linux/seccomp.h +++ b/include/uapi/linux/seccomp.h @@ -15,7 +15,8 @@ #define SECCOMP_SET_MODE_FILTER 1 /* Valid flags for SECCOMP_SET_MODE_FILTER */ -#define SECCOMP_FILTER_FLAG_TSYNC 1 +#define SECCOMP_FILTER_FLAG_TSYNC 1 +#define SECCOMP_FILTER_FLAG_KILL_PROCESS 2 /* * All BPF programs must return a 32-bit value. diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 1f3347fc2605..297f8bfc3b72 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -44,6 +44,7 @@ * is only needed for handling filters shared across tasks. * @prev: points to a previously installed, or inherited, filter * @prog: the BPF program to evaluate + * @kill_process: if true, RET_KILL will kill process rather than thread. * * seccomp_filter objects are organized in a tree linked via the @prev * pointer. For any task, it appears to be a singly-linked list starting @@ -57,6 +58,7 @@ */ struct seccomp_filter { refcount_t usage; + bool kill_process; struct seccomp_filter *prev; struct bpf_prog *prog; }; @@ -450,6 +452,10 @@ static long seccomp_attach_filter(unsigned int flags, return ret; } + /* Set process-killing flag, if present. */ + if (flags & SECCOMP_FILTER_FLAG_KILL_PROCESS) + filter->kill_process = true; + /* * If there is an existing filter, make it the prev and don't drop its * task reference. @@ -665,7 +671,21 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd, seccomp_init_siginfo(&info, this_syscall, data); do_coredump(&info); } - do_exit(SIGSYS); + /* + * The only way match can be NULL here is if something + * went very wrong in seccomp_run_filters() (e.g. a NULL + * filter list in struct seccomp) and the return action + * falls back to failing closed. In this case, take the + * strongest possible action. + * + * If we get here with match->kill_process set, we need + * to kill the entire thread group. Otherwise, kill only + * the offending thread. + */ + if (!match || match->kill_process) + do_group_exit(SIGSYS); + else + do_exit(SIGSYS); } unreachable();