Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp770345ybl; Thu, 23 Jan 2020 07:26:42 -0800 (PST) X-Google-Smtp-Source: APXvYqwyZtLHC+LkTsfF46aJ+9YeO5XTaKWFjvo9zJtAIzdIfhM337yVVm5ApF7cqFHol3nQu1bq X-Received: by 2002:aca:c08b:: with SMTP id q133mr10408702oif.46.1579793202095; Thu, 23 Jan 2020 07:26:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1579793202; cv=none; d=google.com; s=arc-20160816; b=v47eM9qsu9UMy1aNyeFuVRthLDyN1f5zKGdMSY84oHYtQjsHx/Z8WszMhJ4J0rP/FB eOfAvRrqFiMglNrTtPqcxBD7sh8mz3Tjq48bQWk68LYExIUAmH8Smx77MXmTkJ7EJhxv qYKlqizxEh5xzRDheZEmHLxDEJb20n8rK3JYBbgeMLU1yc2VR6Xi9MNY51WmO5Velx77 emBKL1NdOlweSut8lNc6naKeR4GwhQ8ObpqH4xeMqw2hzU4f/Q1VWAguYTeAOGLEKlsh Zw3BFDV9Y0Oyu8MCyB8ajTZoFL9ocYACQrT9FJLdzeFXaxZ7Ap/sAuPWTEcnNrOhSppb SeJw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=kEB1oX080wywjgXCBoRyFYkLoSte5dO4/3ZyhaJZ/DE=; b=N1qb2HW2D9OHc3UuVU/3BxMJMbcG54XWkcFe2a4X/Z3ofNlAE/Equ2t0hpEo8f9HYL 0rJ5kAsHIxik+UWiEM3N3kCKmi897qFuxA3NoBl8VWl9a/pvW6DRRvpU2zTMFjPFvWvf 7D4Ce/3ptmBxJPhLMFRMtrJXgWO94kUtUSXwlmcUVUv/QtXuWBhsrp5Ls/gAVbiaHJyX OQiYsZxoSQY7zbtk4ELIs2hiShTkJNRjS4e4z++9EH8SfFI8gnBjiugelkXgu41Gv9r/ J4NUAMo2Qhnl7Y5rg5WFsykWaokN9wguxGoU9vy2hYg0BGrAuE4wwyXDMrFcPEoh/YZi IXDA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=nlavn8Nd; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x20si1247969otq.222.2020.01.23.07.26.30; Thu, 23 Jan 2020 07:26:42 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=nlavn8Nd; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729095AbgAWPZS (ORCPT + 99 others); Thu, 23 Jan 2020 10:25:18 -0500 Received: from mail-pg1-f195.google.com ([209.85.215.195]:35709 "EHLO mail-pg1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729187AbgAWPZQ (ORCPT ); Thu, 23 Jan 2020 10:25:16 -0500 Received: by mail-pg1-f195.google.com with SMTP id l24so1553340pgk.2 for ; Thu, 23 Jan 2020 07:25:16 -0800 (PST) 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 :mime-version:content-transfer-encoding; bh=kEB1oX080wywjgXCBoRyFYkLoSte5dO4/3ZyhaJZ/DE=; b=nlavn8NdsmMI/q2XsA201oha0BXlUuH8RnGkC1BIvxU403LFzrSYkpBdqmL3QP/HTg hmYPDD25eHCCrhylXhKl4AqllKqkhGr+kydyTUxzm/YTbpiH3v7h6pnMKkmEUPOfn8WR wovnuUevfvCtC4wl20Qh1U6dB5Tp5kdO+y0s8= 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:mime-version:content-transfer-encoding; bh=kEB1oX080wywjgXCBoRyFYkLoSte5dO4/3ZyhaJZ/DE=; b=YCTEgFUH0M947aijecDsdEOjJSNybFhDyWBjC59SU0QQ+7IPI7DSWKvsmkmeA55ZD0 jYAbZzQ6Lsdqvrhgnep3ZaJTZKnReAzzLYdAB7+fw8BP6yOkyEkbhYusf959rIpU1pU5 zHmQHqP+HTpucBFoO3829HR/LSF2zIT3DnPKDfyIi4iIOoMblrCsBjWNJ6gBrw5YU9aE vk+Heed+l16l+0yupJRrRlpKQa0hmgni0LCTxoIPj5eOFyl7YDfz2fgnWE+t1VIBrTPX WFlkVEoYPyKVRBZhJyXbwtf7gmr5VY/k87ez/H90aY2fxTNjKDphNeqHOmFjpV2ArefY QFew== X-Gm-Message-State: APjAAAWeo8aOEuT8t+46lSSGs8J21A3d+stibqGIXzVzD3y9PxtybMZy qAl2McwS1hUztPCz9hpvDAuKV6+qowsPvQ== X-Received: by 2002:aa7:82d5:: with SMTP id f21mr8045338pfn.245.1579793115460; Thu, 23 Jan 2020 07:25:15 -0800 (PST) Received: from kpsingh-kernel.localdomain ([2a00:79e1:abc:122:bd8d:3f7b:87f7:16d1]) by smtp.gmail.com with ESMTPSA id v5sm3108118pfn.122.2020.01.23.07.25.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jan 2020 07:25:14 -0800 (PST) From: KP Singh To: linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-security-module@vger.kernel.org Cc: Brendan Jackman , Florent Revest , Thomas Garnier , Alexei Starovoitov , Daniel Borkmann , James Morris , Kees Cook , Thomas Garnier , Michael Halcrow , Paul Turner , Brendan Gregg , Jann Horn , Matthew Garrett , Christian Brauner , =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= , Florent Revest , Brendan Jackman , Martin KaFai Lau , Song Liu , Yonghong Song , "Serge E. Hallyn" , Mauro Carvalho Chehab , "David S. Miller" , Greg Kroah-Hartman , Nicolas Ferre , Stanislav Fomichev , Quentin Monnet , Andrey Ignatov , Joe Stringer Subject: [PATCH bpf-next v3 04/10] bpf: lsm: Add mutable hooks list for the BPF LSM Date: Thu, 23 Jan 2020 07:24:34 -0800 Message-Id: <20200123152440.28956-5-kpsingh@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200123152440.28956-1-kpsingh@chromium.org> References: <20200123152440.28956-1-kpsingh@chromium.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: KP Singh - The list of hooks registered by an LSM is currently immutable as they are declared with __lsm_ro_after_init and they are attached to a security_hook_heads struct. - For the BPF LSM we need to de/register the hooks at runtime. Making the existing security_hook_heads mutable broadens an attack vector, so a separate security_hook_heads is added for only those that ~must~ be mutable. - These mutable hooks are run only after all the static hooks have successfully executed. This is based on the ideas discussed in: https://lore.kernel.org/lkml/20180408065916.GA2832@ircssh-2.c.rugged-nimbus-611.internal Reviewed-by: Brendan Jackman Reviewed-by: Florent Revest Reviewed-by: Thomas Garnier Signed-off-by: KP Singh --- MAINTAINERS | 1 + include/linux/bpf_lsm.h | 72 +++++++++++++++++++++++++++++++++++++++++ security/bpf/Kconfig | 1 + security/bpf/Makefile | 2 +- security/bpf/hooks.c | 20 ++++++++++++ security/bpf/lsm.c | 7 ++++ security/security.c | 25 +++++++------- 7 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 include/linux/bpf_lsm.h create mode 100644 security/bpf/hooks.c diff --git a/MAINTAINERS b/MAINTAINERS index e2b7f76a1a70..c606b3d89992 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3209,6 +3209,7 @@ L: linux-security-module@vger.kernel.org L: bpf@vger.kernel.org S: Maintained F: security/bpf/ +F: include/linux/bpf_lsm.h BROADCOM B44 10/100 ETHERNET DRIVER M: Michael Chan diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h new file mode 100644 index 000000000000..57c20b2cd2f4 --- /dev/null +++ b/include/linux/bpf_lsm.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Copyright 2019 Google LLC. + */ + +#ifndef _LINUX_BPF_LSM_H +#define _LINUX_BPF_LSM_H + +#include +#include + +#ifdef CONFIG_SECURITY_BPF + +/* Mutable hooks defined at runtime and executed after all the statically + * defined LSM hooks. + */ +extern struct security_hook_heads bpf_lsm_hook_heads; + +int bpf_lsm_srcu_read_lock(void); +void bpf_lsm_srcu_read_unlock(int idx); + +#define CALL_BPF_LSM_VOID_HOOKS(FUNC, ...) \ + do { \ + struct security_hook_list *P; \ + int _idx; \ + \ + if (hlist_empty(&bpf_lsm_hook_heads.FUNC)) \ + break; \ + \ + _idx = bpf_lsm_srcu_read_lock(); \ + hlist_for_each_entry(P, &bpf_lsm_hook_heads.FUNC, list) \ + P->hook.FUNC(__VA_ARGS__); \ + bpf_lsm_srcu_read_unlock(_idx); \ + } while (0) + +#define CALL_BPF_LSM_INT_HOOKS(FUNC, ...) ({ \ + int _ret = 0; \ + do { \ + struct security_hook_list *P; \ + int _idx; \ + \ + if (hlist_empty(&bpf_lsm_hook_heads.FUNC)) \ + break; \ + \ + _idx = bpf_lsm_srcu_read_lock(); \ + \ + hlist_for_each_entry(P, \ + &bpf_lsm_hook_heads.FUNC, list) { \ + _ret = P->hook.FUNC(__VA_ARGS__); \ + if (_ret && IS_ENABLED(CONFIG_SECURITY_BPF_ENFORCE)) \ + break; \ + } \ + bpf_lsm_srcu_read_unlock(_idx); \ + } while (0); \ + IS_ENABLED(CONFIG_SECURITY_BPF_ENFORCE) ? _ret : 0; \ +}) + +#else /* !CONFIG_SECURITY_BPF */ + +#define CALL_BPF_LSM_INT_HOOKS(FUNC, ...) (0) +#define CALL_BPF_LSM_VOID_HOOKS(...) + +static inline int bpf_lsm_srcu_read_lock(void) +{ + return 0; +} +static inline void bpf_lsm_srcu_read_unlock(int idx) {} + +#endif /* CONFIG_SECURITY_BPF */ + +#endif /* _LINUX_BPF_LSM_H */ diff --git a/security/bpf/Kconfig b/security/bpf/Kconfig index a5f6c67ae526..595e4ad597ae 100644 --- a/security/bpf/Kconfig +++ b/security/bpf/Kconfig @@ -6,6 +6,7 @@ config SECURITY_BPF bool "BPF-based MAC and audit policy" depends on SECURITY depends on BPF_SYSCALL + depends on SRCU help This enables instrumentation of the security hooks with eBPF programs. diff --git a/security/bpf/Makefile b/security/bpf/Makefile index c78a8a056e7e..c526927c337d 100644 --- a/security/bpf/Makefile +++ b/security/bpf/Makefile @@ -2,4 +2,4 @@ # # Copyright 2019 Google LLC. -obj-$(CONFIG_SECURITY_BPF) := lsm.o ops.o +obj-$(CONFIG_SECURITY_BPF) := lsm.o ops.o hooks.o diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c new file mode 100644 index 000000000000..b123d9cb4cd4 --- /dev/null +++ b/security/bpf/hooks.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright 2019 Google LLC. + */ + +#include +#include + +DEFINE_STATIC_SRCU(security_hook_srcu); + +int bpf_lsm_srcu_read_lock(void) +{ + return srcu_read_lock(&security_hook_srcu); +} + +void bpf_lsm_srcu_read_unlock(int idx) +{ + return srcu_read_unlock(&security_hook_srcu, idx); +} diff --git a/security/bpf/lsm.c b/security/bpf/lsm.c index dc9ac03c7aa0..a25a068e1781 100644 --- a/security/bpf/lsm.c +++ b/security/bpf/lsm.c @@ -4,6 +4,7 @@ * Copyright 2019 Google LLC. */ +#include #include /* This is only for internal hooks, always statically shipped as part of the @@ -12,6 +13,12 @@ */ static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = {}; +/* Security hooks registered dynamically by the BPF LSM and must be accessed + * by holding bpf_lsm_srcu_read_lock and bpf_lsm_srcu_read_unlock. The mutable + * hooks dynamically allocated by the BPF LSM are appeneded here. + */ +struct security_hook_heads bpf_lsm_hook_heads; + static int __init bpf_lsm_init(void) { security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks), "bpf"); diff --git a/security/security.c b/security/security.c index 30a8aa700557..95a46ca25dcd 100644 --- a/security/security.c +++ b/security/security.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #define MAX_LSM_EVM_XATTR 2 @@ -657,20 +658,22 @@ static void __init lsm_early_task(struct task_struct *task) \ hlist_for_each_entry(P, &security_hook_heads.FUNC, list) \ P->hook.FUNC(__VA_ARGS__); \ + CALL_BPF_LSM_VOID_HOOKS(FUNC, __VA_ARGS__); \ } while (0) -#define call_int_hook(FUNC, IRC, ...) ({ \ - int RC = IRC; \ - do { \ - struct security_hook_list *P; \ - \ +#define call_int_hook(FUNC, IRC, ...) ({ \ + int RC = IRC; \ + do { \ + struct security_hook_list *P; \ hlist_for_each_entry(P, &security_hook_heads.FUNC, list) { \ - RC = P->hook.FUNC(__VA_ARGS__); \ - if (RC != 0) \ - break; \ - } \ - } while (0); \ - RC; \ + RC = P->hook.FUNC(__VA_ARGS__); \ + if (RC != 0) \ + break; \ + } \ + if (RC == 0) \ + RC = CALL_BPF_LSM_INT_HOOKS(FUNC, __VA_ARGS__); \ + } while (0); \ + RC; \ }) /* Security operations */ -- 2.20.1