From patchwork Thu Feb 20 17:52:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KP Singh X-Patchwork-Id: 11394819 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7B34E17E0 for ; Thu, 20 Feb 2020 17:53:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 51CC024673 for ; Thu, 20 Feb 2020 17:53:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="P0HVXfLY" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728119AbgBTRxA (ORCPT ); Thu, 20 Feb 2020 12:53:00 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:35915 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728359AbgBTRw6 (ORCPT ); Thu, 20 Feb 2020 12:52:58 -0500 Received: by mail-wm1-f66.google.com with SMTP id p17so3025813wma.1 for ; Thu, 20 Feb 2020 09:52:55 -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=0abA5E0OjgcrSzHbxE94d8IVvZFrSKJHA7cstMQj5qA=; b=P0HVXfLYteXQE5UhSl8LTP0NGCRqCPckfbBRYGOdV+RmW+QOLjeg6HFWkW4sll9KOC 61YuhuiHt3T2kWLTaB2ZjPNqovlBBvo6TAOc8Xcj0ZU52RlutjB2ldpTEqCrgfcC20eJ 7WooBGwQcyT7OsQ0lM9rE5C0DncgsRKxsJ98I= 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=0abA5E0OjgcrSzHbxE94d8IVvZFrSKJHA7cstMQj5qA=; b=Ac8FA4IDABVhQ4Gu8kDmKxmX5y2QoZnKADQfUDeAKRAEswRNFe4Eyl7DGk8t/PysAI Vuewqzw88OsG3dyhntIWw0CfrA8nHs2XlCvbMotU4Prx2Ki75inQ5NjWOslJ/t3fSlKD kNrULrTo6XUfbzEuaHiAiw8RNOwM3W2MZ/axzDvGQdHFca0cR01gyeiGhfX8KABsbyv9 94v6PlP7dgPUrpNM37a12wUv2CohaW3OQLC3VeRkIyy/w2wjTauKCojq0Gvlvvp96Sq8 ZkSusIBPbH+K2nZ/xMbGzUy3UN6FtoH1rB5XHA1Vpk9Y4VSo5pr4CZffZvDFhqEuqG4W +Cag== X-Gm-Message-State: APjAAAVarxeZIpgaehU/KK9RlqFj1/Zf+zAeOaGpCwgcEK3sqFk0cPhP jO+MUHlwdQu1kqYwat64dKEuxg== X-Google-Smtp-Source: APXvYqzF1RB3bMF8HHT53VW6yM9RwTMt/SeAq+H3oPgCjQ85zeXqE9yf4W2eoV0TQfF6xtJkN5fZJQ== X-Received: by 2002:a7b:c750:: with SMTP id w16mr5566673wmk.46.1582221175124; Thu, 20 Feb 2020 09:52:55 -0800 (PST) Received: from kpsingh-kernel.localdomain ([2620:0:105f:fd00:d960:542a:a1d:648a]) by smtp.gmail.com with ESMTPSA id r5sm363059wrt.43.2020.02.20.09.52.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Feb 2020 09:52:54 -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 , Florent Revest , Brendan Jackman , Martin KaFai Lau , Song Liu , Yonghong Song , "Serge E. Hallyn" , "David S. Miller" , Greg Kroah-Hartman , Nicolas Ferre , Stanislav Fomichev , Quentin Monnet , Andrey Ignatov , Joe Stringer Subject: [PATCH bpf-next v4 1/8] bpf: Introduce BPF_PROG_TYPE_LSM Date: Thu, 20 Feb 2020 18:52:43 +0100 Message-Id: <20200220175250.10795-2-kpsingh@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200220175250.10795-1-kpsingh@chromium.org> References: <20200220175250.10795-1-kpsingh@chromium.org> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: KP Singh Introduce types and configs for bpf programs that can be attached to LSM hooks. The programs can be enabled by the config option CONFIG_BPF_LSM. Signed-off-by: KP Singh Reviewed-by: Brendan Jackman Reviewed-by: Florent Revest Reviewed-by: Thomas Garnier --- MAINTAINERS | 1 + include/linux/bpf.h | 3 +++ include/linux/bpf_types.h | 4 ++++ include/uapi/linux/bpf.h | 2 ++ init/Kconfig | 11 +++++++++++ kernel/bpf/Makefile | 1 + kernel/bpf/bpf_lsm.c | 17 +++++++++++++++++ kernel/trace/bpf_trace.c | 12 ++++++------ tools/include/uapi/linux/bpf.h | 2 ++ tools/lib/bpf/libbpf_probes.c | 1 + 10 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 kernel/bpf/bpf_lsm.c diff --git a/MAINTAINERS b/MAINTAINERS index a0d86490c2c6..0f603e8928d5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3147,6 +3147,7 @@ R: Martin KaFai Lau R: Song Liu R: Yonghong Song R: Andrii Nakryiko +R: KP Singh L: netdev@vger.kernel.org L: bpf@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 49b1a70e12c8..c647cef3f4c1 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1429,6 +1429,9 @@ extern const struct bpf_func_proto bpf_strtoul_proto; extern const struct bpf_func_proto bpf_tcp_sock_proto; extern const struct bpf_func_proto bpf_jiffies64_proto; +const struct bpf_func_proto *bpf_tracing_func_proto( + enum bpf_func_id func_id, const struct bpf_prog *prog); + /* Shared helpers among cBPF and eBPF. */ void bpf_user_rnd_init_once(void); u64 bpf_user_rnd_u32(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h index c81d4ece79a4..ba0c2d56f8a3 100644 --- a/include/linux/bpf_types.h +++ b/include/linux/bpf_types.h @@ -70,6 +70,10 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_STRUCT_OPS, bpf_struct_ops, void *, void *) BPF_PROG_TYPE(BPF_PROG_TYPE_EXT, bpf_extension, void *, void *) +#ifdef CONFIG_BPF_LSM +BPF_PROG_TYPE(BPF_PROG_TYPE_LSM, lsm, + void *, void *) +#endif /* CONFIG_BPF_LSM */ #endif BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index f1d74a2bd234..2f1e24a8c4a4 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -181,6 +181,7 @@ enum bpf_prog_type { BPF_PROG_TYPE_TRACING, BPF_PROG_TYPE_STRUCT_OPS, BPF_PROG_TYPE_EXT, + BPF_PROG_TYPE_LSM, }; enum bpf_attach_type { @@ -210,6 +211,7 @@ enum bpf_attach_type { BPF_TRACE_RAW_TP, BPF_TRACE_FENTRY, BPF_TRACE_FEXIT, + BPF_LSM_MAC, __MAX_BPF_ATTACH_TYPE }; diff --git a/init/Kconfig b/init/Kconfig index 452bc1835cd4..7d5db2982875 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1617,6 +1617,17 @@ config KALLSYMS_BASE_RELATIVE # end of the "standard kernel features (expert users)" menu # syscall, maps, verifier + +config BPF_LSM + bool "LSM Instrumentation with BPF" + depends on BPF_SYSCALL + help + This enables instrumentation of the security hooks with eBPF programs. + The programs are executed after all the statically defined LSM hooks + allow the action. + + If you are unsure how to answer this question, answer N. + config BPF_SYSCALL bool "Enable bpf() system call" select BPF diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile index 046ce5d98033..f2d7be596966 100644 --- a/kernel/bpf/Makefile +++ b/kernel/bpf/Makefile @@ -29,4 +29,5 @@ obj-$(CONFIG_DEBUG_INFO_BTF) += sysfs_btf.o endif ifeq ($(CONFIG_BPF_JIT),y) obj-$(CONFIG_BPF_SYSCALL) += bpf_struct_ops.o +obj-${CONFIG_BPF_LSM} += bpf_lsm.o endif diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c new file mode 100644 index 000000000000..affb6941622e --- /dev/null +++ b/kernel/bpf/bpf_lsm.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright 2019 Google LLC. + */ + +#include +#include +#include + +const struct bpf_prog_ops lsm_prog_ops = { +}; + +const struct bpf_verifier_ops lsm_verifier_ops = { + .get_func_proto = bpf_tracing_func_proto, + .is_valid_access = btf_ctx_access, +}; diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 4ddd5ac46094..a69cb8a0042d 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -781,8 +781,8 @@ static const struct bpf_func_proto bpf_send_signal_thread_proto = { .arg1_type = ARG_ANYTHING, }; -static const struct bpf_func_proto * -tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) +const struct bpf_func_proto * +bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) { switch (func_id) { case BPF_FUNC_map_lookup_elem: @@ -865,7 +865,7 @@ kprobe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_override_return_proto; #endif default: - return tracing_func_proto(func_id, prog); + return bpf_tracing_func_proto(func_id, prog); } } @@ -975,7 +975,7 @@ tp_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) case BPF_FUNC_get_stack: return &bpf_get_stack_proto_tp; default: - return tracing_func_proto(func_id, prog); + return bpf_tracing_func_proto(func_id, prog); } } @@ -1041,7 +1041,7 @@ pe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) case BPF_FUNC_perf_prog_read_value: return &bpf_perf_prog_read_value_proto; default: - return tracing_func_proto(func_id, prog); + return bpf_tracing_func_proto(func_id, prog); } } @@ -1168,7 +1168,7 @@ raw_tp_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) case BPF_FUNC_get_stack: return &bpf_get_stack_proto_raw_tp; default: - return tracing_func_proto(func_id, prog); + return bpf_tracing_func_proto(func_id, prog); } } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index f1d74a2bd234..2f1e24a8c4a4 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -181,6 +181,7 @@ enum bpf_prog_type { BPF_PROG_TYPE_TRACING, BPF_PROG_TYPE_STRUCT_OPS, BPF_PROG_TYPE_EXT, + BPF_PROG_TYPE_LSM, }; enum bpf_attach_type { @@ -210,6 +211,7 @@ enum bpf_attach_type { BPF_TRACE_RAW_TP, BPF_TRACE_FENTRY, BPF_TRACE_FEXIT, + BPF_LSM_MAC, __MAX_BPF_ATTACH_TYPE }; diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c index b782ebef6ac9..2c92059c0c90 100644 --- a/tools/lib/bpf/libbpf_probes.c +++ b/tools/lib/bpf/libbpf_probes.c @@ -108,6 +108,7 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, case BPF_PROG_TYPE_TRACING: case BPF_PROG_TYPE_STRUCT_OPS: case BPF_PROG_TYPE_EXT: + case BPF_PROG_TYPE_LSM: default: break; } From patchwork Thu Feb 20 17:52:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KP Singh X-Patchwork-Id: 11394815 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3216A1395 for ; Thu, 20 Feb 2020 17:53:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CC85624673 for ; Thu, 20 Feb 2020 17:53:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="MmR2QjWY" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728806AbgBTRxX (ORCPT ); Thu, 20 Feb 2020 12:53:23 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:35920 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728463AbgBTRxC (ORCPT ); Thu, 20 Feb 2020 12:53:02 -0500 Received: by mail-wm1-f67.google.com with SMTP id p17so3025890wma.1 for ; Thu, 20 Feb 2020 09:52:57 -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=Htacyiu0VGziRBFcmYbu7qhz8olZ2AKY2fV6uBLnqFc=; b=MmR2QjWY8YnAld+aSOkTNdYnJX2mLTyuXnxgZ5mePhfuK9do0OYu/VRZiIbTXw5LoE kKQfu6qxw0AH4zB9Y6cufD5s5rwTABFxfXP/uBuveI1LOiU/HXsvgf/okCHTaL/PZ1ma rwVkqBWOWsXRVh04jgjaxZBMsDdCUNZAeHDTI= 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=Htacyiu0VGziRBFcmYbu7qhz8olZ2AKY2fV6uBLnqFc=; b=uNhAnYEtAg9xVE+Oa3x1mAAVO3j5IdbGHRl0btB8c51vPVTHQU+ZjAxHZ/N4UFfFv1 JinNSsqnGVlUsE/UPiuqep/RNeBNxb4qpo0yUQ8am7/8PjH8v0zWLQvIs3LhWdUBcbIq 0GAHIMTGusD6NQS+iz23bmdwe/Lbpy0deIk2y1ad+Q26JKaGdngLeIbsxsDTZaeePFCz 1uAPZE3QjFRV8foG/nV5iwMM8GmNa/vtKEmEz7axW7w9h5MSm8R1uMDlqMQRvm2kIEz3 w1t7GJq2krY0PLZg9A/4w0Nuoo/Uyybqq4XF/G9M4gG6jMpLjQY5Ux7JQQkQHSTTPcJf 42PA== X-Gm-Message-State: APjAAAWkMcKcK8RjS9G6919MLfvye4+0+hzxBly3GFIvoOoLoeQf6xcd gs0tMx+ZQzWpwgQqv4IuFH7R3g== X-Google-Smtp-Source: APXvYqwTg9PUtZRHMQLapxSoI5MY+bQXQnEfK7QLf7pOwiSQ622tH91Kig0ojBvLQWQUuKotqP3f7Q== X-Received: by 2002:a7b:cb42:: with SMTP id v2mr5870866wmj.170.1582221176267; Thu, 20 Feb 2020 09:52:56 -0800 (PST) Received: from kpsingh-kernel.localdomain ([2620:0:105f:fd00:d960:542a:a1d:648a]) by smtp.gmail.com with ESMTPSA id r5sm363059wrt.43.2020.02.20.09.52.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Feb 2020 09:52:55 -0800 (PST) From: KP Singh To: linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-security-module@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , James Morris , Kees Cook , Thomas Garnier , Michael Halcrow , Paul Turner , Brendan Gregg , Jann Horn , Matthew Garrett , Christian Brauner , Florent Revest , Brendan Jackman , Martin KaFai Lau , Song Liu , Yonghong Song , "Serge E. Hallyn" , "David S. Miller" , Greg Kroah-Hartman , Nicolas Ferre , Stanislav Fomichev , Quentin Monnet , Andrey Ignatov , Joe Stringer Subject: [PATCH bpf-next v4 2/8] security: Refactor declaration of LSM hooks Date: Thu, 20 Feb 2020 18:52:44 +0100 Message-Id: <20200220175250.10795-3-kpsingh@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200220175250.10795-1-kpsingh@chromium.org> References: <20200220175250.10795-1-kpsingh@chromium.org> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: KP Singh The information about the different types of LSM hooks is scattered in two locations i.e. union security_list_options and struct security_hook_heads. Rather than duplicating this information even further for BPF_PROG_TYPE_LSM, define all the hooks with the LSM_HOOK macro in lsm_hook_names.h which is then used to generate all the data structures required by the LSM framework. Signed-off-by: KP Singh --- include/linux/lsm_hook_names.h | 353 +++++++++++++++++++ include/linux/lsm_hooks.h | 622 +-------------------------------- 2 files changed, 359 insertions(+), 616 deletions(-) create mode 100644 include/linux/lsm_hook_names.h diff --git a/include/linux/lsm_hook_names.h b/include/linux/lsm_hook_names.h new file mode 100644 index 000000000000..1137a3e70bf5 --- /dev/null +++ b/include/linux/lsm_hook_names.h @@ -0,0 +1,353 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Linux Security Module Hook declarations. + * + * Copyright (C) 2001 WireX Communications, Inc + * Copyright (C) 2001 Greg Kroah-Hartman + * Copyright (C) 2001 Networks Associates Technology, Inc + * Copyright (C) 2001 James Morris + * Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group) + * Copyright (C) 2015 Intel Corporation. + * Copyright (C) 2015 Casey Schaufler + * Copyright (C) 2016 Mellanox Techonologies + * Copyright 2019 Google LLC. + */ + +/* The macro LSM_HOOK is used to define the data structures required by the + * the LSM framework using the pattern: + * + * struct security_hook_heads { + * #define LSM_HOOK(RET, NAME, ...) struct hlist_head NAME; + * #include + * #undef LSM_HOOK + * }; + */ +LSM_HOOK(int, binder_set_context_mgr, struct task_struct *mgr) +LSM_HOOK(int, binder_transaction, struct task_struct *from, + struct task_struct *to) +LSM_HOOK(int, binder_transfer_binder, struct task_struct *from, + struct task_struct *to) +LSM_HOOK(int, binder_transfer_file, struct task_struct *from, + struct task_struct *to, struct file *file) +LSM_HOOK(int, ptrace_access_check, struct task_struct *child, unsigned int mode) +LSM_HOOK(int, ptrace_traceme, struct task_struct *parent) +LSM_HOOK(int, capget, struct task_struct *target, kernel_cap_t *effective, + kernel_cap_t *inheritable, kernel_cap_t *permitted) +LSM_HOOK(int, capset, struct cred *new, const struct cred *old, + const kernel_cap_t *effective, const kernel_cap_t *inheritable, + const kernel_cap_t *permitted) +LSM_HOOK(int, capable, const struct cred *cred, struct user_namespace *ns, + int cap, unsigned int opts) +LSM_HOOK(int, quotactl, int cmds, int type, int id, struct super_block *sb) +LSM_HOOK(int, quota_on, struct dentry *dentry) +LSM_HOOK(int, syslog, int type) +LSM_HOOK(int, settime, const struct timespec64 *ts, const struct timezone *tz) +LSM_HOOK(int, vm_enough_memory, struct mm_struct *mm, long pages) +LSM_HOOK(int, bprm_set_creds, struct linux_binprm *bprm) +LSM_HOOK(int, bprm_check_security, struct linux_binprm *bprm) +LSM_HOOK(void, bprm_committing_creds, struct linux_binprm *bprm) +LSM_HOOK(void, bprm_committed_creds, struct linux_binprm *bprm) +LSM_HOOK(int, fs_context_dup, struct fs_context *fc, struct fs_context *src_sc) +LSM_HOOK(int, fs_context_parse_param, struct fs_context *fc, + struct fs_parameter *param) +LSM_HOOK(int, sb_alloc_security, struct super_block *sb) +LSM_HOOK(void, sb_free_security, struct super_block *sb) +LSM_HOOK(void, sb_free_mnt_opts, void *mnt_opts) +LSM_HOOK(int, sb_eat_lsm_opts, char *orig, void **mnt_opts) +LSM_HOOK(int, sb_remount, struct super_block *sb, void *mnt_opts) +LSM_HOOK(int, sb_kern_mount, struct super_block *sb) +LSM_HOOK(int, sb_show_options, struct seq_file *m, struct super_block *sb) +LSM_HOOK(int, sb_statfs, struct dentry *dentry) +LSM_HOOK(int, sb_mount, const char *dev_name, const struct path *path, + const char *type, unsigned long flags, void *data) +LSM_HOOK(int, sb_umount, struct vfsmount *mnt, int flags) +LSM_HOOK(int, sb_pivotroot, const struct path *old_path, + const struct path *new_path) +LSM_HOOK(int, sb_set_mnt_opts, struct super_block *sb, void *mnt_opts, + unsigned long kern_flags, unsigned long *set_kern_flags) +LSM_HOOK(int, sb_clone_mnt_opts, const struct super_block *oldsb, + struct super_block *newsb, unsigned long kern_flags, + unsigned long *set_kern_flags) +LSM_HOOK(int, sb_add_mnt_opt, const char *option, const char *val, int len, + void **mnt_opts) +LSM_HOOK(int, move_mount, const struct path *from_path, + const struct path *to_path) +LSM_HOOK(int, dentry_init_security, struct dentry *dentry, int mode, + const struct qstr *name, void **ctx, u32 *ctxlen) +LSM_HOOK(int, dentry_create_files_as, struct dentry *dentry, int mode, + struct qstr *name, const struct cred *old, struct cred *new) +#ifdef CONFIG_SECURITY_PATH +LSM_HOOK(int, path_unlink, const struct path *dir, struct dentry *dentry) +LSM_HOOK(int, path_mkdir, const struct path *dir, struct dentry *dentry, + umode_t mode) +LSM_HOOK(int, path_rmdir, const struct path *dir, struct dentry *dentry) +LSM_HOOK(int, path_mknod, const struct path *dir, struct dentry *dentry, + umode_t mode, unsigned int dev) +LSM_HOOK(int, path_truncate, const struct path *path) +LSM_HOOK(int, path_symlink, const struct path *dir, struct dentry *dentry, + const char *old_name) +LSM_HOOK(int, path_link, struct dentry *old_dentry, const struct path *new_dir, + struct dentry *new_dentry) +LSM_HOOK(int, path_rename, const struct path *old_dir, + struct dentry *old_dentry, const struct path *new_dir, + struct dentry *new_dentry) +LSM_HOOK(int, path_chmod, const struct path *path, umode_t mode) +LSM_HOOK(int, path_chown, const struct path *path, kuid_t uid, kgid_t gid) +LSM_HOOK(int, path_chroot, const struct path *path) +#endif + +/* Needed for inode based security check */ +LSM_HOOK(int, path_notify, const struct path *path, u64 mask, + unsigned int obj_type) +LSM_HOOK(int, inode_alloc_security, struct inode *inode) +LSM_HOOK(void, inode_free_security, struct inode *inode) +LSM_HOOK(int, inode_init_security, struct inode *inode, struct inode *dir, + const struct qstr *qstr, const char **name, void **value, size_t *len) +LSM_HOOK(int, inode_create, struct inode *dir, struct dentry *dentry, + umode_t mode) +LSM_HOOK(int, inode_link, struct dentry *old_dentry, struct inode *dir, + struct dentry *new_dentry) +LSM_HOOK(int, inode_unlink, struct inode *dir, struct dentry *dentry) +LSM_HOOK(int, inode_symlink, struct inode *dir, struct dentry *dentry, + const char *old_name) +LSM_HOOK(int, inode_mkdir, struct inode *dir, struct dentry *dentry, + umode_t mode) +LSM_HOOK(int, inode_rmdir, struct inode *dir, struct dentry *dentry) +LSM_HOOK(int, inode_mknod, struct inode *dir, struct dentry *dentry, + umode_t mode, dev_t dev) +LSM_HOOK(int, inode_rename, struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +LSM_HOOK(int, inode_readlink, struct dentry *dentry) +LSM_HOOK(int, inode_follow_link, struct dentry *dentry, struct inode *inode, + bool rcu) +LSM_HOOK(int, inode_permission, struct inode *inode, int mask) +LSM_HOOK(int, inode_setattr, struct dentry *dentry, struct iattr *attr) +LSM_HOOK(int, inode_getattr, const struct path *path) +LSM_HOOK(int, inode_setxattr, struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) +LSM_HOOK(void, inode_post_setxattr, struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) +LSM_HOOK(int, inode_getxattr, struct dentry *dentry, const char *name) +LSM_HOOK(int, inode_listxattr, struct dentry *dentry) +LSM_HOOK(int, inode_removexattr, struct dentry *dentry, const char *name) +LSM_HOOK(int, inode_need_killpriv, struct dentry *dentry) +LSM_HOOK(int, inode_killpriv, struct dentry *dentry) +LSM_HOOK(int, inode_getsecurity, struct inode *inode, const char *name, + void **buffer, bool alloc) +LSM_HOOK(int, inode_setsecurity, struct inode *inode, const char *name, + const void *value, size_t size, int flags) +LSM_HOOK(int, inode_listsecurity, struct inode *inode, char *buffer, + size_t buffer_size) +LSM_HOOK(void, inode_getsecid, struct inode *inode, u32 *secid) +LSM_HOOK(int, inode_copy_up, struct dentry *src, struct cred **new) +LSM_HOOK(int, inode_copy_up_xattr, const char *name) +LSM_HOOK(int, kernfs_init_security, struct kernfs_node *kn_dir, + struct kernfs_node *kn) +LSM_HOOK(int, file_permission, struct file *file, int mask) +LSM_HOOK(int, file_alloc_security, struct file *file) +LSM_HOOK(void, file_free_security, struct file *file) +LSM_HOOK(int, file_ioctl, struct file *file, unsigned int cmd, + unsigned long arg) +LSM_HOOK(int, mmap_addr, unsigned long addr) +LSM_HOOK(int, mmap_file, struct file *file, unsigned long reqprot, + unsigned long prot, unsigned long flags) +LSM_HOOK(int, file_mprotect, struct vm_area_struct *vma, unsigned long reqprot, + unsigned long prot) +LSM_HOOK(int, file_lock, struct file *file, unsigned int cmd) +LSM_HOOK(int, file_fcntl, struct file *file, unsigned int cmd, + unsigned long arg) +LSM_HOOK(void, file_set_fowner, struct file *file) +LSM_HOOK(int, file_send_sigiotask, struct task_struct *tsk, + struct fown_struct *fown, int sig) +LSM_HOOK(int, file_receive, struct file *file) +LSM_HOOK(int, file_open, struct file *file) +LSM_HOOK(int, task_alloc, struct task_struct *task, unsigned long clone_flags) +LSM_HOOK(void, task_free, struct task_struct *task) +LSM_HOOK(int, cred_alloc_blank, struct cred *cred, gfp_t gfp) +LSM_HOOK(void, cred_free, struct cred *cred) +LSM_HOOK(int, cred_prepare, struct cred *new, const struct cred *old, gfp_t gfp) +LSM_HOOK(void, cred_transfer, struct cred *new, const struct cred *old) +LSM_HOOK(void, cred_getsecid, const struct cred *c, u32 *secid) +LSM_HOOK(int, kernel_act_as, struct cred *new, u32 secid) +LSM_HOOK(int, kernel_create_files_as, struct cred *new, struct inode *inode) +LSM_HOOK(int, kernel_module_request, char *kmod_name) +LSM_HOOK(int, kernel_load_data, enum kernel_load_data_id id) +LSM_HOOK(int, kernel_read_file, struct file *file, enum kernel_read_file_id id) +LSM_HOOK(int, kernel_post_read_file, struct file *file, char *buf, loff_t size, + enum kernel_read_file_id id) +LSM_HOOK(int, task_fix_setuid, struct cred *new, const struct cred *old, + int flags) +LSM_HOOK(int, task_setpgid, struct task_struct *p, pid_t pgid) +LSM_HOOK(int, task_getpgid, struct task_struct *p) +LSM_HOOK(int, task_getsid, struct task_struct *p) +LSM_HOOK(void, task_getsecid, struct task_struct *p, u32 *secid) +LSM_HOOK(int, task_setnice, struct task_struct *p, int nice) +LSM_HOOK(int, task_setioprio, struct task_struct *p, int ioprio) +LSM_HOOK(int, task_getioprio, struct task_struct *p) +LSM_HOOK(int, task_prlimit, const struct cred *cred, const struct cred *tcred, + unsigned int flags) +LSM_HOOK(int, task_setrlimit, struct task_struct *p, unsigned int resource, + struct rlimit *new_rlim) +LSM_HOOK(int, task_setscheduler, struct task_struct *p) +LSM_HOOK(int, task_getscheduler, struct task_struct *p) +LSM_HOOK(int, task_movememory, struct task_struct *p) +LSM_HOOK(int, task_kill, struct task_struct *p, struct kernel_siginfo *info, + int sig, const struct cred *cred) +LSM_HOOK(int, task_prctl, int option, unsigned long arg2, unsigned long arg3, + unsigned long arg4, unsigned long arg5) +LSM_HOOK(void, task_to_inode, struct task_struct *p, struct inode *inode) +LSM_HOOK(int, ipc_permission, struct kern_ipc_perm *ipcp, short flag) +LSM_HOOK(void, ipc_getsecid, struct kern_ipc_perm *ipcp, u32 *secid) +LSM_HOOK(int, msg_msg_alloc_security, struct msg_msg *msg) +LSM_HOOK(void, msg_msg_free_security, struct msg_msg *msg) +LSM_HOOK(int, msg_queue_alloc_security, struct kern_ipc_perm *perm) +LSM_HOOK(void, msg_queue_free_security, struct kern_ipc_perm *perm) +LSM_HOOK(int, msg_queue_associate, struct kern_ipc_perm *perm, int msqflg) +LSM_HOOK(int, msg_queue_msgctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, msg_queue_msgsnd, struct kern_ipc_perm *perm, struct msg_msg *msg, + int msqflg) +LSM_HOOK(int, msg_queue_msgrcv, struct kern_ipc_perm *perm, struct msg_msg *msg, + struct task_struct *target, long type, int mode) +LSM_HOOK(int, shm_alloc_security, struct kern_ipc_perm *perm) +LSM_HOOK(void, shm_free_security, struct kern_ipc_perm *perm) +LSM_HOOK(int, shm_associate, struct kern_ipc_perm *perm, int shmflg) +LSM_HOOK(int, shm_shmctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, shm_shmat, struct kern_ipc_perm *perm, char __user *shmaddr, + int shmflg) +LSM_HOOK(int, sem_alloc_security, struct kern_ipc_perm *perm) +LSM_HOOK(void, sem_free_security, struct kern_ipc_perm *perm) +LSM_HOOK(int, sem_associate, struct kern_ipc_perm *perm, int semflg) +LSM_HOOK(int, sem_semctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, sem_semop, struct kern_ipc_perm *perm, struct sembuf *sops, + unsigned nsops, int alter) +LSM_HOOK(int, netlink_send, struct sock *sk, struct sk_buff *skb) +LSM_HOOK(void, d_instantiate, struct dentry *dentry, struct inode *inode) +LSM_HOOK(int, getprocattr, struct task_struct *p, char *name, char **value) +LSM_HOOK(int, setprocattr, const char *name, void *value, size_t size) +LSM_HOOK(int, ismaclabel, const char *name) +LSM_HOOK(int, secid_to_secctx, u32 secid, char **secdata, u32 *seclen) +LSM_HOOK(int, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid) +LSM_HOOK(void, release_secctx, char *secdata, u32 seclen) +LSM_HOOK(void, inode_invalidate_secctx, struct inode *inode) +LSM_HOOK(int, inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen) +LSM_HOOK(int, inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen) +LSM_HOOK(int, inode_getsecctx, struct inode *inode, void **ctx, u32 *ctxlen) +#ifdef CONFIG_SECURITY_NETWORK +LSM_HOOK(int, unix_stream_connect, struct sock *sock, struct sock *other, + struct sock *newsk) +LSM_HOOK(int, unix_may_send, struct socket *sock, struct socket *other) +LSM_HOOK(int, socket_create, int family, int type, int protocol, int kern) +LSM_HOOK(int, socket_post_create, struct socket *sock, int family, int type, + int protocol, int kern) +LSM_HOOK(int, socket_socketpair, struct socket *socka, struct socket *sockb) +LSM_HOOK(int, socket_bind, struct socket *sock, struct sockaddr *address, + int addrlen) +LSM_HOOK(int, socket_connect, struct socket *sock, struct sockaddr *address, + int addrlen) +LSM_HOOK(int, socket_listen, struct socket *sock, int backlog) +LSM_HOOK(int, socket_accept, struct socket *sock, struct socket *newsock) +LSM_HOOK(int, socket_sendmsg, struct socket *sock, struct msghdr *msg, int size) +LSM_HOOK(int, socket_recvmsg, struct socket *sock, struct msghdr *msg, int size, + int flags) +LSM_HOOK(int, socket_getsockname, struct socket *sock) +LSM_HOOK(int, socket_getpeername, struct socket *sock) +LSM_HOOK(int, socket_getsockopt, struct socket *sock, int level, int optname) +LSM_HOOK(int, socket_setsockopt, struct socket *sock, int level, int optname) +LSM_HOOK(int, socket_shutdown, struct socket *sock, int how) +LSM_HOOK(int, socket_sock_rcv_skb, struct sock *sk, struct sk_buff *skb) +LSM_HOOK(int, socket_getpeersec_stream, struct socket *sock, + char __user *optval, int __user *optlen, unsigned len) +LSM_HOOK(int, socket_getpeersec_dgram, struct socket *sock, struct sk_buff *skb, + u32 *secid) +LSM_HOOK(int, sk_alloc_security, struct sock *sk, int family, gfp_t priority) +LSM_HOOK(void, sk_free_security, struct sock *sk) +LSM_HOOK(void, sk_clone_security, const struct sock *sk, struct sock *newsk) +LSM_HOOK(void, sk_getsecid, struct sock *sk, u32 *secid) +LSM_HOOK(void, sock_graft, struct sock *sk, struct socket *parent) +LSM_HOOK(int, inet_conn_request, struct sock *sk, struct sk_buff *skb, + struct request_sock *req) +LSM_HOOK(void, inet_csk_clone, struct sock *newsk, + const struct request_sock *req) +LSM_HOOK(void, inet_conn_established, struct sock *sk, struct sk_buff *skb) +LSM_HOOK(int, secmark_relabel_packet, u32 secid) +LSM_HOOK(void, secmark_refcount_inc, void) +LSM_HOOK(void, secmark_refcount_dec, void) +LSM_HOOK(void, req_classify_flow, const struct request_sock *req, + struct flowi *fl) +LSM_HOOK(int, tun_dev_alloc_security, void **security) +LSM_HOOK(void, tun_dev_free_security, void *security) +LSM_HOOK(int, tun_dev_create, void) +LSM_HOOK(int, tun_dev_attach_queue, void *security) +LSM_HOOK(int, tun_dev_attach, struct sock *sk, void *security) +LSM_HOOK(int, tun_dev_open, void *security) +LSM_HOOK(int, sctp_assoc_request, struct sctp_endpoint *ep, struct sk_buff *skb) +LSM_HOOK(int, sctp_bind_connect, struct sock *sk, int optname, + struct sockaddr *address, int addrlen) +LSM_HOOK(void, sctp_sk_clone, struct sctp_endpoint *ep, struct sock *sk, + struct sock *newsk) +#endif /* CONFIG_SECURITY_NETWORK */ + +#ifdef CONFIG_SECURITY_INFINIBAND +LSM_HOOK(int, ib_pkey_access, void *sec, u64 subnet_prefix, u16 pkey) +LSM_HOOK(int, ib_endport_manage_subnet, void *sec, const char *dev_name, + u8 port_num) +LSM_HOOK(int, ib_alloc_security, void **sec) +LSM_HOOK(void, ib_free_security, void *sec) +#endif /* CONFIG_SECURITY_INFINIBAND */ + +#ifdef CONFIG_SECURITY_NETWORK_XFRM +LSM_HOOK(int, xfrm_policy_alloc_security, struct xfrm_sec_ctx **ctxp, + struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp) +LSM_HOOK(int, xfrm_policy_clone_security, struct xfrm_sec_ctx *old_ctx, + struct xfrm_sec_ctx **new_ctx) +LSM_HOOK(void, xfrm_policy_free_security, struct xfrm_sec_ctx *ctx) +LSM_HOOK(int, xfrm_policy_delete_security, struct xfrm_sec_ctx *ctx) +LSM_HOOK(int, xfrm_state_alloc, struct xfrm_state *x, + struct xfrm_user_sec_ctx *sec_ctx) +LSM_HOOK(int, xfrm_state_alloc_acquire, struct xfrm_state *x, + struct xfrm_sec_ctx *polsec, u32 secid) +LSM_HOOK(void, xfrm_state_free_security, struct xfrm_state *x) +LSM_HOOK(int, xfrm_state_delete_security, struct xfrm_state *x) +LSM_HOOK(int, xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid, + u8 dir) +LSM_HOOK(int, xfrm_state_pol_flow_match, struct xfrm_state *x, + struct xfrm_policy *xp, const struct flowi *fl) +LSM_HOOK(int, xfrm_decode_session, struct sk_buff *skb, u32 *secid, int ckall) +#endif /* CONFIG_SECURITY_NETWORK_XFRM */ + +/* key management security hooks */ +#ifdef CONFIG_KEYS +LSM_HOOK(int, key_alloc, struct key *key, const struct cred *cred, + unsigned long flags) +LSM_HOOK(void, key_free, struct key *key) +LSM_HOOK(int, key_permission, key_ref_t key_ref, const struct cred *cred, + unsigned perm) +LSM_HOOK(int, key_getsecurity, struct key *key, char **_buffer) +#endif /* CONFIG_KEYS */ + +#ifdef CONFIG_AUDIT +LSM_HOOK(int, audit_rule_init, u32 field, u32 op, char *rulestr, void **lsmrule) +LSM_HOOK(int, audit_rule_known, struct audit_krule *krule) +LSM_HOOK(int, audit_rule_match, u32 secid, u32 field, u32 op, void *lsmrule) +LSM_HOOK(void, audit_rule_free, void *lsmrule) +#endif /* CONFIG_AUDIT */ + +#ifdef CONFIG_BPF_SYSCALL +LSM_HOOK(int, bpf, int cmd, union bpf_attr *attr, unsigned int size) +LSM_HOOK(int, bpf_map, struct bpf_map *map, fmode_t fmode) +LSM_HOOK(int, bpf_prog, struct bpf_prog *prog) +LSM_HOOK(int, bpf_map_alloc_security, struct bpf_map *map) +LSM_HOOK(void, bpf_map_free_security, struct bpf_map *map) +LSM_HOOK(int, bpf_prog_alloc_security, struct bpf_prog_aux *aux) +LSM_HOOK(void, bpf_prog_free_security, struct bpf_prog_aux *aux) +#endif /* CONFIG_BPF_SYSCALL */ + +LSM_HOOK(int, locked_down, enum lockdown_reason what) +#ifdef CONFIG_PERF_EVENTS +LSM_HOOK(int, perf_event_open, struct perf_event_attr *attr, int type) +LSM_HOOK(int, perf_event_alloc, struct perf_event *event) +LSM_HOOK(void, perf_event_free, struct perf_event *event) +LSM_HOOK(int, perf_event_read, struct perf_event *event) +LSM_HOOK(int, perf_event_write, struct perf_event *event) +#endif diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 20d8cf194fb7..905954c650ff 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1456,625 +1456,15 @@ * @what: kernel feature being accessed */ union security_list_options { - int (*binder_set_context_mgr)(struct task_struct *mgr); - int (*binder_transaction)(struct task_struct *from, - struct task_struct *to); - int (*binder_transfer_binder)(struct task_struct *from, - struct task_struct *to); - int (*binder_transfer_file)(struct task_struct *from, - struct task_struct *to, - struct file *file); - - int (*ptrace_access_check)(struct task_struct *child, - unsigned int mode); - int (*ptrace_traceme)(struct task_struct *parent); - int (*capget)(struct task_struct *target, kernel_cap_t *effective, - kernel_cap_t *inheritable, kernel_cap_t *permitted); - int (*capset)(struct cred *new, const struct cred *old, - const kernel_cap_t *effective, - const kernel_cap_t *inheritable, - const kernel_cap_t *permitted); - int (*capable)(const struct cred *cred, - struct user_namespace *ns, - int cap, - unsigned int opts); - int (*quotactl)(int cmds, int type, int id, struct super_block *sb); - int (*quota_on)(struct dentry *dentry); - int (*syslog)(int type); - int (*settime)(const struct timespec64 *ts, const struct timezone *tz); - int (*vm_enough_memory)(struct mm_struct *mm, long pages); - - int (*bprm_set_creds)(struct linux_binprm *bprm); - int (*bprm_check_security)(struct linux_binprm *bprm); - void (*bprm_committing_creds)(struct linux_binprm *bprm); - void (*bprm_committed_creds)(struct linux_binprm *bprm); - - int (*fs_context_dup)(struct fs_context *fc, struct fs_context *src_sc); - int (*fs_context_parse_param)(struct fs_context *fc, struct fs_parameter *param); - - int (*sb_alloc_security)(struct super_block *sb); - void (*sb_free_security)(struct super_block *sb); - void (*sb_free_mnt_opts)(void *mnt_opts); - int (*sb_eat_lsm_opts)(char *orig, void **mnt_opts); - int (*sb_remount)(struct super_block *sb, void *mnt_opts); - int (*sb_kern_mount)(struct super_block *sb); - int (*sb_show_options)(struct seq_file *m, struct super_block *sb); - int (*sb_statfs)(struct dentry *dentry); - int (*sb_mount)(const char *dev_name, const struct path *path, - const char *type, unsigned long flags, void *data); - int (*sb_umount)(struct vfsmount *mnt, int flags); - int (*sb_pivotroot)(const struct path *old_path, const struct path *new_path); - int (*sb_set_mnt_opts)(struct super_block *sb, - void *mnt_opts, - unsigned long kern_flags, - unsigned long *set_kern_flags); - int (*sb_clone_mnt_opts)(const struct super_block *oldsb, - struct super_block *newsb, - unsigned long kern_flags, - unsigned long *set_kern_flags); - int (*sb_add_mnt_opt)(const char *option, const char *val, int len, - void **mnt_opts); - int (*move_mount)(const struct path *from_path, const struct path *to_path); - int (*dentry_init_security)(struct dentry *dentry, int mode, - const struct qstr *name, void **ctx, - u32 *ctxlen); - int (*dentry_create_files_as)(struct dentry *dentry, int mode, - struct qstr *name, - const struct cred *old, - struct cred *new); - - -#ifdef CONFIG_SECURITY_PATH - int (*path_unlink)(const struct path *dir, struct dentry *dentry); - int (*path_mkdir)(const struct path *dir, struct dentry *dentry, - umode_t mode); - int (*path_rmdir)(const struct path *dir, struct dentry *dentry); - int (*path_mknod)(const struct path *dir, struct dentry *dentry, - umode_t mode, unsigned int dev); - int (*path_truncate)(const struct path *path); - int (*path_symlink)(const struct path *dir, struct dentry *dentry, - const char *old_name); - int (*path_link)(struct dentry *old_dentry, const struct path *new_dir, - struct dentry *new_dentry); - int (*path_rename)(const struct path *old_dir, struct dentry *old_dentry, - const struct path *new_dir, - struct dentry *new_dentry); - int (*path_chmod)(const struct path *path, umode_t mode); - int (*path_chown)(const struct path *path, kuid_t uid, kgid_t gid); - int (*path_chroot)(const struct path *path); -#endif - /* Needed for inode based security check */ - int (*path_notify)(const struct path *path, u64 mask, - unsigned int obj_type); - int (*inode_alloc_security)(struct inode *inode); - void (*inode_free_security)(struct inode *inode); - int (*inode_init_security)(struct inode *inode, struct inode *dir, - const struct qstr *qstr, - const char **name, void **value, - size_t *len); - int (*inode_create)(struct inode *dir, struct dentry *dentry, - umode_t mode); - int (*inode_link)(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry); - int (*inode_unlink)(struct inode *dir, struct dentry *dentry); - int (*inode_symlink)(struct inode *dir, struct dentry *dentry, - const char *old_name); - int (*inode_mkdir)(struct inode *dir, struct dentry *dentry, - umode_t mode); - int (*inode_rmdir)(struct inode *dir, struct dentry *dentry); - int (*inode_mknod)(struct inode *dir, struct dentry *dentry, - umode_t mode, dev_t dev); - int (*inode_rename)(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, - struct dentry *new_dentry); - int (*inode_readlink)(struct dentry *dentry); - int (*inode_follow_link)(struct dentry *dentry, struct inode *inode, - bool rcu); - int (*inode_permission)(struct inode *inode, int mask); - int (*inode_setattr)(struct dentry *dentry, struct iattr *attr); - int (*inode_getattr)(const struct path *path); - int (*inode_setxattr)(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); - void (*inode_post_setxattr)(struct dentry *dentry, const char *name, - const void *value, size_t size, - int flags); - int (*inode_getxattr)(struct dentry *dentry, const char *name); - int (*inode_listxattr)(struct dentry *dentry); - int (*inode_removexattr)(struct dentry *dentry, const char *name); - int (*inode_need_killpriv)(struct dentry *dentry); - int (*inode_killpriv)(struct dentry *dentry); - int (*inode_getsecurity)(struct inode *inode, const char *name, - void **buffer, bool alloc); - int (*inode_setsecurity)(struct inode *inode, const char *name, - const void *value, size_t size, - int flags); - int (*inode_listsecurity)(struct inode *inode, char *buffer, - size_t buffer_size); - void (*inode_getsecid)(struct inode *inode, u32 *secid); - int (*inode_copy_up)(struct dentry *src, struct cred **new); - int (*inode_copy_up_xattr)(const char *name); - - int (*kernfs_init_security)(struct kernfs_node *kn_dir, - struct kernfs_node *kn); - - int (*file_permission)(struct file *file, int mask); - int (*file_alloc_security)(struct file *file); - void (*file_free_security)(struct file *file); - int (*file_ioctl)(struct file *file, unsigned int cmd, - unsigned long arg); - int (*mmap_addr)(unsigned long addr); - int (*mmap_file)(struct file *file, unsigned long reqprot, - unsigned long prot, unsigned long flags); - int (*file_mprotect)(struct vm_area_struct *vma, unsigned long reqprot, - unsigned long prot); - int (*file_lock)(struct file *file, unsigned int cmd); - int (*file_fcntl)(struct file *file, unsigned int cmd, - unsigned long arg); - void (*file_set_fowner)(struct file *file); - int (*file_send_sigiotask)(struct task_struct *tsk, - struct fown_struct *fown, int sig); - int (*file_receive)(struct file *file); - int (*file_open)(struct file *file); - - int (*task_alloc)(struct task_struct *task, unsigned long clone_flags); - void (*task_free)(struct task_struct *task); - int (*cred_alloc_blank)(struct cred *cred, gfp_t gfp); - void (*cred_free)(struct cred *cred); - int (*cred_prepare)(struct cred *new, const struct cred *old, - gfp_t gfp); - void (*cred_transfer)(struct cred *new, const struct cred *old); - void (*cred_getsecid)(const struct cred *c, u32 *secid); - int (*kernel_act_as)(struct cred *new, u32 secid); - int (*kernel_create_files_as)(struct cred *new, struct inode *inode); - int (*kernel_module_request)(char *kmod_name); - int (*kernel_load_data)(enum kernel_load_data_id id); - int (*kernel_read_file)(struct file *file, enum kernel_read_file_id id); - int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size, - enum kernel_read_file_id id); - int (*task_fix_setuid)(struct cred *new, const struct cred *old, - int flags); - int (*task_setpgid)(struct task_struct *p, pid_t pgid); - int (*task_getpgid)(struct task_struct *p); - int (*task_getsid)(struct task_struct *p); - void (*task_getsecid)(struct task_struct *p, u32 *secid); - int (*task_setnice)(struct task_struct *p, int nice); - int (*task_setioprio)(struct task_struct *p, int ioprio); - int (*task_getioprio)(struct task_struct *p); - int (*task_prlimit)(const struct cred *cred, const struct cred *tcred, - unsigned int flags); - int (*task_setrlimit)(struct task_struct *p, unsigned int resource, - struct rlimit *new_rlim); - int (*task_setscheduler)(struct task_struct *p); - int (*task_getscheduler)(struct task_struct *p); - int (*task_movememory)(struct task_struct *p); - int (*task_kill)(struct task_struct *p, struct kernel_siginfo *info, - int sig, const struct cred *cred); - int (*task_prctl)(int option, unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5); - void (*task_to_inode)(struct task_struct *p, struct inode *inode); - - int (*ipc_permission)(struct kern_ipc_perm *ipcp, short flag); - void (*ipc_getsecid)(struct kern_ipc_perm *ipcp, u32 *secid); - - int (*msg_msg_alloc_security)(struct msg_msg *msg); - void (*msg_msg_free_security)(struct msg_msg *msg); - - int (*msg_queue_alloc_security)(struct kern_ipc_perm *perm); - void (*msg_queue_free_security)(struct kern_ipc_perm *perm); - int (*msg_queue_associate)(struct kern_ipc_perm *perm, int msqflg); - int (*msg_queue_msgctl)(struct kern_ipc_perm *perm, int cmd); - int (*msg_queue_msgsnd)(struct kern_ipc_perm *perm, struct msg_msg *msg, - int msqflg); - int (*msg_queue_msgrcv)(struct kern_ipc_perm *perm, struct msg_msg *msg, - struct task_struct *target, long type, - int mode); - - int (*shm_alloc_security)(struct kern_ipc_perm *perm); - void (*shm_free_security)(struct kern_ipc_perm *perm); - int (*shm_associate)(struct kern_ipc_perm *perm, int shmflg); - int (*shm_shmctl)(struct kern_ipc_perm *perm, int cmd); - int (*shm_shmat)(struct kern_ipc_perm *perm, char __user *shmaddr, - int shmflg); - - int (*sem_alloc_security)(struct kern_ipc_perm *perm); - void (*sem_free_security)(struct kern_ipc_perm *perm); - int (*sem_associate)(struct kern_ipc_perm *perm, int semflg); - int (*sem_semctl)(struct kern_ipc_perm *perm, int cmd); - int (*sem_semop)(struct kern_ipc_perm *perm, struct sembuf *sops, - unsigned nsops, int alter); - - int (*netlink_send)(struct sock *sk, struct sk_buff *skb); - - void (*d_instantiate)(struct dentry *dentry, struct inode *inode); - - int (*getprocattr)(struct task_struct *p, char *name, char **value); - int (*setprocattr)(const char *name, void *value, size_t size); - int (*ismaclabel)(const char *name); - int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen); - int (*secctx_to_secid)(const char *secdata, u32 seclen, u32 *secid); - void (*release_secctx)(char *secdata, u32 seclen); - - void (*inode_invalidate_secctx)(struct inode *inode); - int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen); - int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen); - int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen); - -#ifdef CONFIG_SECURITY_NETWORK - int (*unix_stream_connect)(struct sock *sock, struct sock *other, - struct sock *newsk); - int (*unix_may_send)(struct socket *sock, struct socket *other); - - int (*socket_create)(int family, int type, int protocol, int kern); - int (*socket_post_create)(struct socket *sock, int family, int type, - int protocol, int kern); - int (*socket_socketpair)(struct socket *socka, struct socket *sockb); - int (*socket_bind)(struct socket *sock, struct sockaddr *address, - int addrlen); - int (*socket_connect)(struct socket *sock, struct sockaddr *address, - int addrlen); - int (*socket_listen)(struct socket *sock, int backlog); - int (*socket_accept)(struct socket *sock, struct socket *newsock); - int (*socket_sendmsg)(struct socket *sock, struct msghdr *msg, - int size); - int (*socket_recvmsg)(struct socket *sock, struct msghdr *msg, - int size, int flags); - int (*socket_getsockname)(struct socket *sock); - int (*socket_getpeername)(struct socket *sock); - int (*socket_getsockopt)(struct socket *sock, int level, int optname); - int (*socket_setsockopt)(struct socket *sock, int level, int optname); - int (*socket_shutdown)(struct socket *sock, int how); - int (*socket_sock_rcv_skb)(struct sock *sk, struct sk_buff *skb); - int (*socket_getpeersec_stream)(struct socket *sock, - char __user *optval, - int __user *optlen, unsigned len); - int (*socket_getpeersec_dgram)(struct socket *sock, - struct sk_buff *skb, u32 *secid); - int (*sk_alloc_security)(struct sock *sk, int family, gfp_t priority); - void (*sk_free_security)(struct sock *sk); - void (*sk_clone_security)(const struct sock *sk, struct sock *newsk); - void (*sk_getsecid)(struct sock *sk, u32 *secid); - void (*sock_graft)(struct sock *sk, struct socket *parent); - int (*inet_conn_request)(struct sock *sk, struct sk_buff *skb, - struct request_sock *req); - void (*inet_csk_clone)(struct sock *newsk, - const struct request_sock *req); - void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb); - int (*secmark_relabel_packet)(u32 secid); - void (*secmark_refcount_inc)(void); - void (*secmark_refcount_dec)(void); - void (*req_classify_flow)(const struct request_sock *req, - struct flowi *fl); - int (*tun_dev_alloc_security)(void **security); - void (*tun_dev_free_security)(void *security); - int (*tun_dev_create)(void); - int (*tun_dev_attach_queue)(void *security); - int (*tun_dev_attach)(struct sock *sk, void *security); - int (*tun_dev_open)(void *security); - int (*sctp_assoc_request)(struct sctp_endpoint *ep, - struct sk_buff *skb); - int (*sctp_bind_connect)(struct sock *sk, int optname, - struct sockaddr *address, int addrlen); - void (*sctp_sk_clone)(struct sctp_endpoint *ep, struct sock *sk, - struct sock *newsk); -#endif /* CONFIG_SECURITY_NETWORK */ - -#ifdef CONFIG_SECURITY_INFINIBAND - int (*ib_pkey_access)(void *sec, u64 subnet_prefix, u16 pkey); - int (*ib_endport_manage_subnet)(void *sec, const char *dev_name, - u8 port_num); - int (*ib_alloc_security)(void **sec); - void (*ib_free_security)(void *sec); -#endif /* CONFIG_SECURITY_INFINIBAND */ - -#ifdef CONFIG_SECURITY_NETWORK_XFRM - int (*xfrm_policy_alloc_security)(struct xfrm_sec_ctx **ctxp, - struct xfrm_user_sec_ctx *sec_ctx, - gfp_t gfp); - int (*xfrm_policy_clone_security)(struct xfrm_sec_ctx *old_ctx, - struct xfrm_sec_ctx **new_ctx); - void (*xfrm_policy_free_security)(struct xfrm_sec_ctx *ctx); - int (*xfrm_policy_delete_security)(struct xfrm_sec_ctx *ctx); - int (*xfrm_state_alloc)(struct xfrm_state *x, - struct xfrm_user_sec_ctx *sec_ctx); - int (*xfrm_state_alloc_acquire)(struct xfrm_state *x, - struct xfrm_sec_ctx *polsec, - u32 secid); - void (*xfrm_state_free_security)(struct xfrm_state *x); - int (*xfrm_state_delete_security)(struct xfrm_state *x); - int (*xfrm_policy_lookup)(struct xfrm_sec_ctx *ctx, u32 fl_secid, - u8 dir); - int (*xfrm_state_pol_flow_match)(struct xfrm_state *x, - struct xfrm_policy *xp, - const struct flowi *fl); - int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall); -#endif /* CONFIG_SECURITY_NETWORK_XFRM */ - - /* key management security hooks */ -#ifdef CONFIG_KEYS - int (*key_alloc)(struct key *key, const struct cred *cred, - unsigned long flags); - void (*key_free)(struct key *key); - int (*key_permission)(key_ref_t key_ref, const struct cred *cred, - unsigned perm); - int (*key_getsecurity)(struct key *key, char **_buffer); -#endif /* CONFIG_KEYS */ - -#ifdef CONFIG_AUDIT - int (*audit_rule_init)(u32 field, u32 op, char *rulestr, - void **lsmrule); - int (*audit_rule_known)(struct audit_krule *krule); - int (*audit_rule_match)(u32 secid, u32 field, u32 op, void *lsmrule); - void (*audit_rule_free)(void *lsmrule); -#endif /* CONFIG_AUDIT */ - -#ifdef CONFIG_BPF_SYSCALL - int (*bpf)(int cmd, union bpf_attr *attr, - unsigned int size); - int (*bpf_map)(struct bpf_map *map, fmode_t fmode); - int (*bpf_prog)(struct bpf_prog *prog); - int (*bpf_map_alloc_security)(struct bpf_map *map); - void (*bpf_map_free_security)(struct bpf_map *map); - int (*bpf_prog_alloc_security)(struct bpf_prog_aux *aux); - void (*bpf_prog_free_security)(struct bpf_prog_aux *aux); -#endif /* CONFIG_BPF_SYSCALL */ - int (*locked_down)(enum lockdown_reason what); -#ifdef CONFIG_PERF_EVENTS - int (*perf_event_open)(struct perf_event_attr *attr, int type); - int (*perf_event_alloc)(struct perf_event *event); - void (*perf_event_free)(struct perf_event *event); - int (*perf_event_read)(struct perf_event *event); - int (*perf_event_write)(struct perf_event *event); - -#endif + #define LSM_HOOK(RET, NAME, ...) RET (*NAME)(__VA_ARGS__); + #include "lsm_hook_names.h" + #undef LSM_HOOK }; struct security_hook_heads { - struct hlist_head binder_set_context_mgr; - struct hlist_head binder_transaction; - struct hlist_head binder_transfer_binder; - struct hlist_head binder_transfer_file; - struct hlist_head ptrace_access_check; - struct hlist_head ptrace_traceme; - struct hlist_head capget; - struct hlist_head capset; - struct hlist_head capable; - struct hlist_head quotactl; - struct hlist_head quota_on; - struct hlist_head syslog; - struct hlist_head settime; - struct hlist_head vm_enough_memory; - struct hlist_head bprm_set_creds; - struct hlist_head bprm_check_security; - struct hlist_head bprm_committing_creds; - struct hlist_head bprm_committed_creds; - struct hlist_head fs_context_dup; - struct hlist_head fs_context_parse_param; - struct hlist_head sb_alloc_security; - struct hlist_head sb_free_security; - struct hlist_head sb_free_mnt_opts; - struct hlist_head sb_eat_lsm_opts; - struct hlist_head sb_remount; - struct hlist_head sb_kern_mount; - struct hlist_head sb_show_options; - struct hlist_head sb_statfs; - struct hlist_head sb_mount; - struct hlist_head sb_umount; - struct hlist_head sb_pivotroot; - struct hlist_head sb_set_mnt_opts; - struct hlist_head sb_clone_mnt_opts; - struct hlist_head sb_add_mnt_opt; - struct hlist_head move_mount; - struct hlist_head dentry_init_security; - struct hlist_head dentry_create_files_as; -#ifdef CONFIG_SECURITY_PATH - struct hlist_head path_unlink; - struct hlist_head path_mkdir; - struct hlist_head path_rmdir; - struct hlist_head path_mknod; - struct hlist_head path_truncate; - struct hlist_head path_symlink; - struct hlist_head path_link; - struct hlist_head path_rename; - struct hlist_head path_chmod; - struct hlist_head path_chown; - struct hlist_head path_chroot; -#endif - /* Needed for inode based modules as well */ - struct hlist_head path_notify; - struct hlist_head inode_alloc_security; - struct hlist_head inode_free_security; - struct hlist_head inode_init_security; - struct hlist_head inode_create; - struct hlist_head inode_link; - struct hlist_head inode_unlink; - struct hlist_head inode_symlink; - struct hlist_head inode_mkdir; - struct hlist_head inode_rmdir; - struct hlist_head inode_mknod; - struct hlist_head inode_rename; - struct hlist_head inode_readlink; - struct hlist_head inode_follow_link; - struct hlist_head inode_permission; - struct hlist_head inode_setattr; - struct hlist_head inode_getattr; - struct hlist_head inode_setxattr; - struct hlist_head inode_post_setxattr; - struct hlist_head inode_getxattr; - struct hlist_head inode_listxattr; - struct hlist_head inode_removexattr; - struct hlist_head inode_need_killpriv; - struct hlist_head inode_killpriv; - struct hlist_head inode_getsecurity; - struct hlist_head inode_setsecurity; - struct hlist_head inode_listsecurity; - struct hlist_head inode_getsecid; - struct hlist_head inode_copy_up; - struct hlist_head inode_copy_up_xattr; - struct hlist_head kernfs_init_security; - struct hlist_head file_permission; - struct hlist_head file_alloc_security; - struct hlist_head file_free_security; - struct hlist_head file_ioctl; - struct hlist_head mmap_addr; - struct hlist_head mmap_file; - struct hlist_head file_mprotect; - struct hlist_head file_lock; - struct hlist_head file_fcntl; - struct hlist_head file_set_fowner; - struct hlist_head file_send_sigiotask; - struct hlist_head file_receive; - struct hlist_head file_open; - struct hlist_head task_alloc; - struct hlist_head task_free; - struct hlist_head cred_alloc_blank; - struct hlist_head cred_free; - struct hlist_head cred_prepare; - struct hlist_head cred_transfer; - struct hlist_head cred_getsecid; - struct hlist_head kernel_act_as; - struct hlist_head kernel_create_files_as; - struct hlist_head kernel_load_data; - struct hlist_head kernel_read_file; - struct hlist_head kernel_post_read_file; - struct hlist_head kernel_module_request; - struct hlist_head task_fix_setuid; - struct hlist_head task_setpgid; - struct hlist_head task_getpgid; - struct hlist_head task_getsid; - struct hlist_head task_getsecid; - struct hlist_head task_setnice; - struct hlist_head task_setioprio; - struct hlist_head task_getioprio; - struct hlist_head task_prlimit; - struct hlist_head task_setrlimit; - struct hlist_head task_setscheduler; - struct hlist_head task_getscheduler; - struct hlist_head task_movememory; - struct hlist_head task_kill; - struct hlist_head task_prctl; - struct hlist_head task_to_inode; - struct hlist_head ipc_permission; - struct hlist_head ipc_getsecid; - struct hlist_head msg_msg_alloc_security; - struct hlist_head msg_msg_free_security; - struct hlist_head msg_queue_alloc_security; - struct hlist_head msg_queue_free_security; - struct hlist_head msg_queue_associate; - struct hlist_head msg_queue_msgctl; - struct hlist_head msg_queue_msgsnd; - struct hlist_head msg_queue_msgrcv; - struct hlist_head shm_alloc_security; - struct hlist_head shm_free_security; - struct hlist_head shm_associate; - struct hlist_head shm_shmctl; - struct hlist_head shm_shmat; - struct hlist_head sem_alloc_security; - struct hlist_head sem_free_security; - struct hlist_head sem_associate; - struct hlist_head sem_semctl; - struct hlist_head sem_semop; - struct hlist_head netlink_send; - struct hlist_head d_instantiate; - struct hlist_head getprocattr; - struct hlist_head setprocattr; - struct hlist_head ismaclabel; - struct hlist_head secid_to_secctx; - struct hlist_head secctx_to_secid; - struct hlist_head release_secctx; - struct hlist_head inode_invalidate_secctx; - struct hlist_head inode_notifysecctx; - struct hlist_head inode_setsecctx; - struct hlist_head inode_getsecctx; -#ifdef CONFIG_SECURITY_NETWORK - struct hlist_head unix_stream_connect; - struct hlist_head unix_may_send; - struct hlist_head socket_create; - struct hlist_head socket_post_create; - struct hlist_head socket_socketpair; - struct hlist_head socket_bind; - struct hlist_head socket_connect; - struct hlist_head socket_listen; - struct hlist_head socket_accept; - struct hlist_head socket_sendmsg; - struct hlist_head socket_recvmsg; - struct hlist_head socket_getsockname; - struct hlist_head socket_getpeername; - struct hlist_head socket_getsockopt; - struct hlist_head socket_setsockopt; - struct hlist_head socket_shutdown; - struct hlist_head socket_sock_rcv_skb; - struct hlist_head socket_getpeersec_stream; - struct hlist_head socket_getpeersec_dgram; - struct hlist_head sk_alloc_security; - struct hlist_head sk_free_security; - struct hlist_head sk_clone_security; - struct hlist_head sk_getsecid; - struct hlist_head sock_graft; - struct hlist_head inet_conn_request; - struct hlist_head inet_csk_clone; - struct hlist_head inet_conn_established; - struct hlist_head secmark_relabel_packet; - struct hlist_head secmark_refcount_inc; - struct hlist_head secmark_refcount_dec; - struct hlist_head req_classify_flow; - struct hlist_head tun_dev_alloc_security; - struct hlist_head tun_dev_free_security; - struct hlist_head tun_dev_create; - struct hlist_head tun_dev_attach_queue; - struct hlist_head tun_dev_attach; - struct hlist_head tun_dev_open; - struct hlist_head sctp_assoc_request; - struct hlist_head sctp_bind_connect; - struct hlist_head sctp_sk_clone; -#endif /* CONFIG_SECURITY_NETWORK */ -#ifdef CONFIG_SECURITY_INFINIBAND - struct hlist_head ib_pkey_access; - struct hlist_head ib_endport_manage_subnet; - struct hlist_head ib_alloc_security; - struct hlist_head ib_free_security; -#endif /* CONFIG_SECURITY_INFINIBAND */ -#ifdef CONFIG_SECURITY_NETWORK_XFRM - struct hlist_head xfrm_policy_alloc_security; - struct hlist_head xfrm_policy_clone_security; - struct hlist_head xfrm_policy_free_security; - struct hlist_head xfrm_policy_delete_security; - struct hlist_head xfrm_state_alloc; - struct hlist_head xfrm_state_alloc_acquire; - struct hlist_head xfrm_state_free_security; - struct hlist_head xfrm_state_delete_security; - struct hlist_head xfrm_policy_lookup; - struct hlist_head xfrm_state_pol_flow_match; - struct hlist_head xfrm_decode_session; -#endif /* CONFIG_SECURITY_NETWORK_XFRM */ -#ifdef CONFIG_KEYS - struct hlist_head key_alloc; - struct hlist_head key_free; - struct hlist_head key_permission; - struct hlist_head key_getsecurity; -#endif /* CONFIG_KEYS */ -#ifdef CONFIG_AUDIT - struct hlist_head audit_rule_init; - struct hlist_head audit_rule_known; - struct hlist_head audit_rule_match; - struct hlist_head audit_rule_free; -#endif /* CONFIG_AUDIT */ -#ifdef CONFIG_BPF_SYSCALL - struct hlist_head bpf; - struct hlist_head bpf_map; - struct hlist_head bpf_prog; - struct hlist_head bpf_map_alloc_security; - struct hlist_head bpf_map_free_security; - struct hlist_head bpf_prog_alloc_security; - struct hlist_head bpf_prog_free_security; -#endif /* CONFIG_BPF_SYSCALL */ - struct hlist_head locked_down; -#ifdef CONFIG_PERF_EVENTS - struct hlist_head perf_event_open; - struct hlist_head perf_event_alloc; - struct hlist_head perf_event_free; - struct hlist_head perf_event_read; - struct hlist_head perf_event_write; -#endif + #define LSM_HOOK(RET, NAME, ...) struct hlist_head NAME; + #include "lsm_hook_names.h" + #undef LSM_HOOK } __randomize_layout; /* From patchwork Thu Feb 20 17:52:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KP Singh X-Patchwork-Id: 11394817 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BECFD17E0 for ; Thu, 20 Feb 2020 17:53:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 94CAC2467D for ; Thu, 20 Feb 2020 17:53:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="HebykKvI" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728585AbgBTRxA (ORCPT ); Thu, 20 Feb 2020 12:53:00 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:54348 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728480AbgBTRxA (ORCPT ); Thu, 20 Feb 2020 12:53:00 -0500 Received: by mail-wm1-f68.google.com with SMTP id n3so2975744wmk.4 for ; Thu, 20 Feb 2020 09:52:58 -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=vQw2DgUHyFsv/uFvbbGRrtN6ETqPZ9VjN5jx2X9sBgU=; b=HebykKvIKM5PZBkfLT5pCg4RIu6HnbBOEdy3+q3FsjO2oWApigJ78PqksZx6/3EZYc 9DjpGuAVVRgNXvKMXKti6vuT6WZrU0JBiCGOA+Oo5lL072xka032SsballAS566SRGgj BdUUee2PA2YgC7U96fabPMYN5WlrgRTHl5k0w= 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=vQw2DgUHyFsv/uFvbbGRrtN6ETqPZ9VjN5jx2X9sBgU=; b=eHO2BqxcLvC/KrEU2TjwkKfztDa4i2UG6V/x+Xyum4SJNZvqDB+bKyDl3lwWM6mKYE 63GpvxRj1DM1Rm9Th0jzU+0YsfSqN+arM8XNfP6fEVaez5PFOxgZwObbtD58NuwPY8cU uN9x7p8C8peTcq6rOtkO/OOGw9R310kd2e+IxFg+LqgH1m/564RLuGHaAzB9hus/p91k 4FTpQF17+C8+MO23tkCEirdDH79atUoNMzeVqDxKJQRGkU0/4PeIYyVguofg47AtOEJo Ie7yhLCQkDCzASSAeCQYwr3boUlBqWa0WX9h1o4extD6Ct4M1xRHz3te4hCB8trlQ1y2 r0ew== X-Gm-Message-State: APjAAAWQLmgAPdlNllRfbJEfTnMsDSTVZWldliNkrSyU/NQGGw7FPw5v NFWlSWGhRch2xCA+X0Aj/cwUFlpOpdE= X-Google-Smtp-Source: APXvYqyrfCxoZ+bs+y1C/Ol8/1xIHHXPZjDT3tv6J1XnPzCayZgQWx/JyE/a4db+w5DAnaRL5jF07g== X-Received: by 2002:a05:600c:34d:: with SMTP id u13mr5840606wmd.77.1582221177369; Thu, 20 Feb 2020 09:52:57 -0800 (PST) Received: from kpsingh-kernel.localdomain ([2620:0:105f:fd00:d960:542a:a1d:648a]) by smtp.gmail.com with ESMTPSA id r5sm363059wrt.43.2020.02.20.09.52.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Feb 2020 09:52:56 -0800 (PST) From: KP Singh To: linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-security-module@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , James Morris , Kees Cook , Thomas Garnier , Michael Halcrow , Paul Turner , Brendan Gregg , Jann Horn , Matthew Garrett , Christian Brauner , Florent Revest , Brendan Jackman , Martin KaFai Lau , Song Liu , Yonghong Song , "Serge E. Hallyn" , "David S. Miller" , Greg Kroah-Hartman , Nicolas Ferre , Stanislav Fomichev , Quentin Monnet , Andrey Ignatov , Joe Stringer Subject: [PATCH bpf-next v4 3/8] bpf: lsm: provide attachment points for BPF LSM programs Date: Thu, 20 Feb 2020 18:52:45 +0100 Message-Id: <20200220175250.10795-4-kpsingh@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200220175250.10795-1-kpsingh@chromium.org> References: <20200220175250.10795-1-kpsingh@chromium.org> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: KP Singh The BPF LSM programs are implemented as fexit trampolines to avoid the overhead of retpolines. These programs cannot be attached to security_* wrappers as there are quite a few security_* functions that do more than just calling the LSM callbacks. This was discussed on the lists in: https://lore.kernel.org/bpf/20200123152440.28956-1-kpsingh@chromium.org/T/#m068becce588a0cdf01913f368a97aea4c62d8266 Adding a NOP callback after all the static LSM callbacks are called has the following benefits: - The BPF programs run at the right stage of the security_* wrappers. - They run after all the static LSM hooks allowed the operation, therefore cannot allow an action that was already denied. There are some hooks which do not call call_int_hooks or call_void_hooks. It's not possible to call the bpf_lsm_* functions without checking if there is BPF LSM program attached to these hooks. This is added further in a subsequent patch. For now, these hooks are marked as NO_BPF (i.e. attachment of BPF programs is not possible). Signed-off-by: KP Singh --- include/linux/bpf_lsm.h | 34 ++++++++++++++++++++++++++++++++++ kernel/bpf/bpf_lsm.c | 16 ++++++++++++++++ security/security.c | 3 +++ 3 files changed, 53 insertions(+) create mode 100644 include/linux/bpf_lsm.h diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h new file mode 100644 index 000000000000..f867f72f6aa9 --- /dev/null +++ b/include/linux/bpf_lsm.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Copyright 2019 Google LLC. + */ + +#ifndef _LINUX_BPF_LSM_H +#define _LINUX_BPF_LSM_H + +#include + +#ifdef CONFIG_BPF_LSM + +#define LSM_HOOK(RET, NAME, ...) RET bpf_lsm_##NAME(__VA_ARGS__); +#include +#undef LSM_HOOK + +#define RUN_BPF_LSM_VOID_PROGS(FUNC, ...) bpf_lsm_##FUNC(__VA_ARGS__) +#define RUN_BPF_LSM_INT_PROGS(RC, FUNC, ...) ({ \ + do { \ + if (RC == 0) \ + RC = bpf_lsm_##FUNC(__VA_ARGS__); \ + } while (0); \ + RC; \ +}) + +#else /* !CONFIG_BPF_LSM */ + +#define RUN_BPF_LSM_INT_PROGS(RC, FUNC, ...) (RC) +#define RUN_BPF_LSM_VOID_PROGS(FUNC, ...) + +#endif /* CONFIG_BPF_LSM */ + +#endif /* _LINUX_BPF_LSM_H */ diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index affb6941622e..abc847c9b9a1 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -7,6 +7,22 @@ #include #include #include +#include + +/* For every LSM hook that allows attachment of BPF programs, declare a NOP + * function where a BPF program can be attached as an fexit trampoline. + */ +#define LSM_HOOK(RET, NAME, ...) LSM_HOOK_##RET(NAME, __VA_ARGS__) +#define LSM_HOOK_int(NAME, ...) noinline int bpf_lsm_##NAME(__VA_ARGS__) \ +{ \ + return 0; \ +} + +#define LSM_HOOK_void(NAME, ...) \ + noinline void bpf_lsm_##NAME(__VA_ARGS__) {} + +#include +#undef LSM_HOOK const struct bpf_prog_ops lsm_prog_ops = { }; diff --git a/security/security.c b/security/security.c index 565bc9b67276..aa111392a700 100644 --- a/security/security.c +++ b/security/security.c @@ -28,6 +28,7 @@ #include #include #include +#include #define MAX_LSM_EVM_XATTR 2 @@ -684,6 +685,7 @@ 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__); \ + RUN_BPF_LSM_VOID_PROGS(FUNC, __VA_ARGS__); \ } while (0) #define call_int_hook(FUNC, IRC, ...) ({ \ @@ -696,6 +698,7 @@ static void __init lsm_early_task(struct task_struct *task) if (RC != 0) \ break; \ } \ + RC = RUN_BPF_LSM_INT_PROGS(RC, FUNC, __VA_ARGS__); \ } while (0); \ RC; \ }) From patchwork Thu Feb 20 17:52:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KP Singh X-Patchwork-Id: 11394813 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7B4F41395 for ; Thu, 20 Feb 2020 17:53:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 52B0524673 for ; Thu, 20 Feb 2020 17:53:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="PJruUuRl" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728483AbgBTRxC (ORCPT ); Thu, 20 Feb 2020 12:53:02 -0500 Received: from mail-wr1-f65.google.com ([209.85.221.65]:34170 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728482AbgBTRxB (ORCPT ); Thu, 20 Feb 2020 12:53:01 -0500 Received: by mail-wr1-f65.google.com with SMTP id n10so5683361wrm.1 for ; Thu, 20 Feb 2020 09:52:59 -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=lKW2MzukcNPCi/25rtTKAKQ42C5bRG1+jarcaz5NtHI=; b=PJruUuRl5SuOo/l2gIEHwBUPO96BpTAQVkJfL0l+k6D0iDONJsn+yPFci1Gdr4yQef jZmY71z4UXmArPerDVdjQANLI6j2n7KbUZgqZ6ywhXtbhbCcB9PR+CPmpzs6C1SiSxMT v8hmjlWBWRsOx5GFHjCdTzEf3JI8r4J/XQquk= 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=lKW2MzukcNPCi/25rtTKAKQ42C5bRG1+jarcaz5NtHI=; b=mThuGDLlhaGOWH1H/1QuyUHJGK2AgxyAc3xP3AQ2kZvs+vNI09DXBXX8HMpmr+M/Lk D2ydaRGut8pRy2v7j0hhHTPYhT+NmGk5w00axUvea3El54iwNzxbh2UaAfDhpkraMXB3 qvdaL4uSFMfwAqGttVMP2qt6YRUxIfFBCXkhZuxWeTghG5YYTUA6Z2YGvar/R8C0Afx4 cpvEyd0a8x+0KH6u/1n6CIKJH992zytCFyrZixCaU4E4Lj+XBeKEimA8jwfiLdB5hLtp lGP2VIHwsmDxCopEoBKrSsvPynnL1/sa48VqtBSDA0csslxBQelJjpOLCLjH2lzADs4/ 205w== X-Gm-Message-State: APjAAAXpAd1EUUdyyB7wWkcVp/KqsN+Q9ibuimwDl1u9tUW+a8TKDNZO s3T+0nbH3PIYOJQykH9HBQtEmQ== X-Google-Smtp-Source: APXvYqxXDn9Z/x/ZI7GWukZw5C1wH7P8LAjuJiwD5kBuqCEirAfZJYEkwTIYpv03n5kIetKLjLNXgg== X-Received: by 2002:adf:dc86:: with SMTP id r6mr43903264wrj.68.1582221178664; Thu, 20 Feb 2020 09:52:58 -0800 (PST) Received: from kpsingh-kernel.localdomain ([2620:0:105f:fd00:d960:542a:a1d:648a]) by smtp.gmail.com with ESMTPSA id r5sm363059wrt.43.2020.02.20.09.52.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Feb 2020 09:52:58 -0800 (PST) From: KP Singh To: linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-security-module@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , James Morris , Kees Cook , Thomas Garnier , Michael Halcrow , Paul Turner , Brendan Gregg , Jann Horn , Matthew Garrett , Christian Brauner , Florent Revest , Brendan Jackman , Martin KaFai Lau , Song Liu , Yonghong Song , "Serge E. Hallyn" , "David S. Miller" , Greg Kroah-Hartman , Nicolas Ferre , Stanislav Fomichev , Quentin Monnet , Andrey Ignatov , Joe Stringer Subject: [PATCH bpf-next v4 4/8] bpf: lsm: Add support for enabling/disabling BPF hooks Date: Thu, 20 Feb 2020 18:52:46 +0100 Message-Id: <20200220175250.10795-5-kpsingh@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200220175250.10795-1-kpsingh@chromium.org> References: <20200220175250.10795-1-kpsingh@chromium.org> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: KP Singh Each LSM hook defines a static key i.e. bpf_lsm_ and a bpf_lsm__set_enabled function to toggle the key which enables/disables the branch which executes the BPF programs attached to the LSM hook. Use of static keys was suggested in upstream discussion: https://lore.kernel.org/bpf/1cd10710-a81b-8f9b-696d-aa40b0a67225@iogearbox.net/ and results in the following assembly: 0x0000000000001e31 <+65>: jmpq 0x1e36 0x0000000000001e36 <+70>: nopl 0x0(%rax,%rax,1) 0x0000000000001e3b <+75>: xor %eax,%eax 0x0000000000001e3d <+77>: jmp 0x1e25 which avoids an indirect branch and results in lower overhead which is especially helpful for LSM hooks in performance hotpaths. Given the ability to toggle the BPF trampolines, some hooks which do not call call__hooks as they have different default return values, also gain support for BPF program attachment. There are some hooks like security_setprocattr and security_getprocattr which are not instrumentable as they do not provide any monitoring or access control decisions. If required, generation of BTF type information for these hooks can be also be blacklisted. Signed-off-by: KP Singh --- include/linux/bpf_lsm.h | 30 +++++++++++++++++++++++++++--- kernel/bpf/bpf_lsm.c | 28 ++++++++++++++++++++++++++++ security/security.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h index f867f72f6aa9..53dcda8ace01 100644 --- a/include/linux/bpf_lsm.h +++ b/include/linux/bpf_lsm.h @@ -8,27 +8,51 @@ #define _LINUX_BPF_LSM_H #include +#include #ifdef CONFIG_BPF_LSM +#define LSM_HOOK(RET, NAME, ...) \ +DECLARE_STATIC_KEY_FALSE(bpf_lsm_key_##NAME); \ +void bpf_lsm_##NAME##_set_enabled(bool value); +#include +#undef LSM_HOOK + #define LSM_HOOK(RET, NAME, ...) RET bpf_lsm_##NAME(__VA_ARGS__); #include #undef LSM_HOOK -#define RUN_BPF_LSM_VOID_PROGS(FUNC, ...) bpf_lsm_##FUNC(__VA_ARGS__) +#define HAS_BPF_LSM_PROG(FUNC) (static_branch_unlikely(&bpf_lsm_key_##FUNC)) + +#define RUN_BPF_LSM_VOID_PROGS(FUNC, ...) \ + do { \ + if (HAS_BPF_LSM_PROG(FUNC)) \ + bpf_lsm_##FUNC(__VA_ARGS__); \ + } while (0) + #define RUN_BPF_LSM_INT_PROGS(RC, FUNC, ...) ({ \ do { \ - if (RC == 0) \ - RC = bpf_lsm_##FUNC(__VA_ARGS__); \ + if (HAS_BPF_LSM_PROG(FUNC)) { \ + if (RC == 0) \ + RC = bpf_lsm_##FUNC(__VA_ARGS__); \ + } \ } while (0); \ RC; \ }) +int bpf_lsm_set_enabled(const char *name, bool value); + #else /* !CONFIG_BPF_LSM */ +#define HAS_BPF_LSM_PROG false #define RUN_BPF_LSM_INT_PROGS(RC, FUNC, ...) (RC) #define RUN_BPF_LSM_VOID_PROGS(FUNC, ...) +static inline int bpf_lsm_set_enabled(const char *name, bool value) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_BPF_LSM */ #endif /* _LINUX_BPF_LSM_H */ diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index abc847c9b9a1..d7c44433c003 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -8,6 +8,20 @@ #include #include #include +#include +#include + +#define LSM_HOOK(RET, NAME, ...) \ + DEFINE_STATIC_KEY_FALSE(bpf_lsm_key_##NAME); \ + void bpf_lsm_##NAME##_set_enabled(bool value) \ + { \ + if (value) \ + static_branch_enable(&bpf_lsm_key_##NAME); \ + else \ + static_branch_disable(&bpf_lsm_key_##NAME); \ + } +#include +#undef LSM_HOOK /* For every LSM hook that allows attachment of BPF programs, declare a NOP * function where a BPF program can be attached as an fexit trampoline. @@ -24,6 +38,20 @@ #include #undef LSM_HOOK +int bpf_lsm_set_enabled(const char *name, bool value) +{ + char toggle_fn_name[KSYM_NAME_LEN]; + void (*toggle_fn)(bool value); + + snprintf(toggle_fn_name, KSYM_NAME_LEN, "%s_set_enabled", name); + toggle_fn = (void *)kallsyms_lookup_name(toggle_fn_name); + if (!toggle_fn) + return -ESRCH; + + toggle_fn(value); + return 0; +} + const struct bpf_prog_ops lsm_prog_ops = { }; diff --git a/security/security.c b/security/security.c index aa111392a700..569cc07d5e34 100644 --- a/security/security.c +++ b/security/security.c @@ -804,6 +804,13 @@ int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) break; } } +#ifdef CONFIG_BPF_LSM + if (HAS_BPF_LSM_PROG(vm_enough_memory)) { + rc = bpf_lsm_vm_enough_memory(mm, pages); + if (rc <= 0) + cap_sys_admin = 0; + } +#endif return __vm_enough_memory(mm, pages, cap_sys_admin); } @@ -1350,6 +1357,13 @@ int security_inode_getsecurity(struct inode *inode, const char *name, void **buf if (rc != -EOPNOTSUPP) return rc; } +#ifdef CONFIG_BPF_LSM + if (HAS_BPF_LSM_PROG(inode_getsecurity)) { + rc = bpf_lsm_inode_getsecurity(inode, name, buffer, alloc); + if (rc != -EOPNOTSUPP) + return rc; + } +#endif return -EOPNOTSUPP; } @@ -1369,6 +1383,14 @@ int security_inode_setsecurity(struct inode *inode, const char *name, const void if (rc != -EOPNOTSUPP) return rc; } +#ifdef CONFIG_BPF_LSM + if (HAS_BPF_LSM_PROG(inode_setsecurity)) { + rc = bpf_lsm_inode_setsecurity(inode, name, value, size, + flags); + if (rc != -EOPNOTSUPP) + return rc; + } +#endif return -EOPNOTSUPP; } @@ -1754,6 +1776,12 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, break; } } +#ifdef CONFIG_BPF_LSM + if (HAS_BPF_LSM_PROG(task_prctl)) { + if (rc == -ENOSYS) + rc = bpf_lsm_task_prctl(option, arg2, arg3, arg4, arg5); + } +#endif return rc; } @@ -2334,6 +2362,10 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x, rc = hp->hook.xfrm_state_pol_flow_match(x, xp, fl); break; } +#ifdef CONFIG_BPF_LSM + if (HAS_BPF_LSM_PROG(xfrm_state_pol_flow_match)) + rc = bpf_lsm_xfrm_state_pol_flow_match(x, xp, fl); +#endif return rc; } From patchwork Thu Feb 20 17:52:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KP Singh X-Patchwork-Id: 11394809 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 86DCD1395 for ; Thu, 20 Feb 2020 17:53:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4B1F020722 for ; Thu, 20 Feb 2020 17:53:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="SCS879P9" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728818AbgBTRxD (ORCPT ); Thu, 20 Feb 2020 12:53:03 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:54349 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728376AbgBTRxC (ORCPT ); Thu, 20 Feb 2020 12:53:02 -0500 Received: by mail-wm1-f65.google.com with SMTP id n3so2975861wmk.4 for ; Thu, 20 Feb 2020 09:53:00 -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=iSMj63gTFkl6QNNUKNg/Zkq8prJATW6HCmVIlhHEtWU=; b=SCS879P9XqLTwgYYr1ehUQ/eEazVWHreNLobsXZXHnNAzrRMWo+sqDmz+RVEqf3a6A hbbD/VTXHadWdD/BZhTMv5nwF1d3nMMb43KiuFCt3mhj5Zgf1+MD4sJmTMrCKSXrezup d1J4bOqnoM0ObzdMyRQ3tZOtYhUevSNqSlS2M= 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=iSMj63gTFkl6QNNUKNg/Zkq8prJATW6HCmVIlhHEtWU=; b=RwwZRz6bp+xeB/WUWXJUMmFJAitgcNgZ6FttHoe9xaRUSZ77F7RH9AX40pk22Xvroi 9A31AFPNND4cueUdVPkop5VL2W/FiM/dg8Ks5V4E5XWHDnbxb2lIpm8cPYCTu3f+2arc 2dRMQBBi/z/o17R5CU7ZjEMP51sDXlVrIf6tNtWBdUt7rmYocldF28tmW0Rm6BM/xC0a 7KNVwelkP9l9WVrBH6AoFQB3tUoss20ROw3x7544rGtNjMNCkbMl+eR6Z/zJoV2Ll7gj wT38tLaGHQB1Z0XewRqmUkUF8NoUNmOtYVevQbBhuTEazTYsqHgGRdkKPStX2hwit2qE FHUg== X-Gm-Message-State: APjAAAVrACGjctUov1yLoHDxOw0unjnubAn4TwdvL5vDiEBEOClIpROG 2IxmSh9CQiiRw/sIu0b3GACE/Q== X-Google-Smtp-Source: APXvYqwYlSbh3EOXeSBEYq7z7yXrer2jfVkbMaDTXKHJFsAUdGLLHCHuPj/2odunhoh5W/PfHu09DQ== X-Received: by 2002:a1c:6588:: with SMTP id z130mr5655980wmb.0.1582221179939; Thu, 20 Feb 2020 09:52:59 -0800 (PST) Received: from kpsingh-kernel.localdomain ([2620:0:105f:fd00:d960:542a:a1d:648a]) by smtp.gmail.com with ESMTPSA id r5sm363059wrt.43.2020.02.20.09.52.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Feb 2020 09:52:59 -0800 (PST) From: KP Singh To: linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-security-module@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , James Morris , Kees Cook , Thomas Garnier , Michael Halcrow , Paul Turner , Brendan Gregg , Jann Horn , Matthew Garrett , Christian Brauner , Florent Revest , Brendan Jackman , Martin KaFai Lau , Song Liu , Yonghong Song , "Serge E. Hallyn" , "David S. Miller" , Greg Kroah-Hartman , Nicolas Ferre , Stanislav Fomichev , Quentin Monnet , Andrey Ignatov , Joe Stringer Subject: [PATCH bpf-next v4 5/8] bpf: lsm: Implement attach, detach and execution Date: Thu, 20 Feb 2020 18:52:47 +0100 Message-Id: <20200220175250.10795-6-kpsingh@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200220175250.10795-1-kpsingh@chromium.org> References: <20200220175250.10795-1-kpsingh@chromium.org> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: KP Singh JITed BPF programs are dynamically attached to the LSM hooks using fexit trampolines. The trampoline prologue generates code to handle conversion of the signature of the hook to the BPF context and the newly introduced BPF_TRAMP_F_OVERRIDE_RETURN allows the fexit trampoline to override the return value of the function it is attached to. The allocated fexit trampolines are attached to the nop function added at the appropriate places and are executed if all the statically defined LSM hooks allow the action. The BPF_PROG_TYPE_LSM programs must have a GPL compatible license and the following permissions are required to attach a program to a hook: - CAP_SYS_ADMIN to load the program - CAP_MAC_ADMIN to attach it (i.e. to update the security policy) When the program is loaded (BPF_PROG_LOAD): * The verifier validates if the program is trying to attach to a valid security hook and updates the prog->aux->attach_func_proto. * The verifier then further verifies the program for memory accesses by using the BTF information. (It also ensures that no memory is being written to). * An fexit trampoline is initialized (if not present in the lookup table). When an attachment (BPF_PROG_ATTACH) is requested: * The fexit trampoline is updated to use the program being attached. * The static key of the LSM hook is toggled if this is the first program being attached to this hook. (and not a replacement). The attached programs can override the return value of the fexit trampoline to indicate a MAC Policy decision. When multiple programs aree attached to the hook, each program receives the return value from the previous program on the stack and the last program provides the return value to the LSM hook. Signed-off-by: KP Singh --- arch/x86/net/bpf_jit_comp.c | 21 +++++++++++++---- include/linux/bpf.h | 4 ++++ include/linux/bpf_lsm.h | 8 +++++++ kernel/bpf/bpf_lsm.c | 27 +++++++++++++++++++++ kernel/bpf/btf.c | 3 ++- kernel/bpf/syscall.c | 47 ++++++++++++++++++++++++++++++------- kernel/bpf/trampoline.c | 24 +++++++++++++++---- kernel/bpf/verifier.c | 19 +++++++++++---- 8 files changed, 131 insertions(+), 22 deletions(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 9ba08e9abc09..b710abfe06c4 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -1362,7 +1362,8 @@ static void restore_regs(const struct btf_func_model *m, u8 **prog, int nr_args, } static int invoke_bpf(const struct btf_func_model *m, u8 **pprog, - struct bpf_prog **progs, int prog_cnt, int stack_size) + struct bpf_prog **progs, int prog_cnt, int stack_size, + bool override_return) { u8 *prog = *pprog; int cnt = 0, i; @@ -1384,6 +1385,14 @@ static int invoke_bpf(const struct btf_func_model *m, u8 **pprog, if (emit_call(&prog, progs[i]->bpf_func, prog)) return -EINVAL; + + /* If BPF_TRAMP_F_OVERRIDE_RETURN is set, fexit trampolines can + * override the return value of the previous trampoline which is + * then passed on the stack to the next BPF program. + */ + if (override_return) + emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -8); + /* arg1: mov rdi, progs[i] */ emit_mov_imm64(&prog, BPF_REG_1, (long) progs[i] >> 32, (u32) (long) progs[i]); @@ -1462,6 +1471,7 @@ int arch_prepare_bpf_trampoline(void *image, void *image_end, struct bpf_prog **fexit_progs, int fexit_cnt, void *orig_call) { + bool override_return = flags & BPF_TRAMP_F_OVERRIDE_RETURN; int cnt = 0, nr_args = m->nr_args; int stack_size = nr_args * 8; u8 *prog; @@ -1493,7 +1503,8 @@ int arch_prepare_bpf_trampoline(void *image, void *image_end, save_regs(m, &prog, nr_args, stack_size); if (fentry_cnt) - if (invoke_bpf(m, &prog, fentry_progs, fentry_cnt, stack_size)) + if (invoke_bpf(m, &prog, fentry_progs, fentry_cnt, stack_size, + false)) return -EINVAL; if (flags & BPF_TRAMP_F_CALL_ORIG) { @@ -1503,18 +1514,20 @@ int arch_prepare_bpf_trampoline(void *image, void *image_end, /* call original function */ if (emit_call(&prog, orig_call, prog)) return -EINVAL; + /* remember return value in a stack for bpf prog to access */ emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -8); } if (fexit_cnt) - if (invoke_bpf(m, &prog, fexit_progs, fexit_cnt, stack_size)) + if (invoke_bpf(m, &prog, fexit_progs, fexit_cnt, stack_size, + override_return)) return -EINVAL; if (flags & BPF_TRAMP_F_RESTORE_REGS) restore_regs(m, &prog, nr_args, stack_size); - if (flags & BPF_TRAMP_F_CALL_ORIG) + if (flags & BPF_TRAMP_F_CALL_ORIG && !override_return) /* restore original return value back into RAX */ emit_ldx(&prog, BPF_DW, BPF_REG_0, BPF_REG_FP, -8); diff --git a/include/linux/bpf.h b/include/linux/bpf.h index c647cef3f4c1..e63caadbaef3 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -432,6 +432,10 @@ struct btf_func_model { * programs only. Should not be used with normal calls and indirect calls. */ #define BPF_TRAMP_F_SKIP_FRAME BIT(2) +/* Override the return value of the original function. This flag only makes + * sense for fexit trampolines. + */ +#define BPF_TRAMP_F_OVERRIDE_RETURN BIT(3) /* Different use cases for BPF trampoline: * 1. replace nop at the function entry (kprobe equivalent) diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h index 53dcda8ace01..8f114affe5c6 100644 --- a/include/linux/bpf_lsm.h +++ b/include/linux/bpf_lsm.h @@ -41,6 +41,8 @@ void bpf_lsm_##NAME##_set_enabled(bool value); }) int bpf_lsm_set_enabled(const char *name, bool value); +int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog, + const struct bpf_prog *prog); #else /* !CONFIG_BPF_LSM */ @@ -53,6 +55,12 @@ static inline int bpf_lsm_set_enabled(const char *name, bool value) return -EOPNOTSUPP; } +static inline int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog, + const struct bpf_prog *prog) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_BPF_LSM */ #endif /* _LINUX_BPF_LSM_H */ diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index d7c44433c003..edeb4ded1d3e 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -10,6 +10,7 @@ #include #include #include +#include #define LSM_HOOK(RET, NAME, ...) \ DEFINE_STATIC_KEY_FALSE(bpf_lsm_key_##NAME); \ @@ -52,6 +53,32 @@ int bpf_lsm_set_enabled(const char *name, bool value) return 0; } +#define BPF_LSM_SYM_PREFX "bpf_lsm_" + +int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog, + const struct bpf_prog *prog) +{ + /* Only CAP_MAC_ADMIN users are allowed to make changes to LSM hooks + */ + if (!capable(CAP_MAC_ADMIN)) + return -EPERM; + + if (!prog->gpl_compatible) { + bpf_log(vlog, + "LSM programs must have a GPL compatible license\n"); + return -EINVAL; + } + + if (strncmp(BPF_LSM_SYM_PREFX, prog->aux->attach_func_name, + strlen(BPF_LSM_SYM_PREFX))) { + bpf_log(vlog, "attach_btf_id %u points to wrong type name %s\n", + prog->aux->attach_btf_id, prog->aux->attach_func_name); + return -EINVAL; + } + + return 0; +} + const struct bpf_prog_ops lsm_prog_ops = { }; diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 805c43b083e9..0e4cad3c810b 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -3710,7 +3710,8 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, nr_args--; } - if (prog->expected_attach_type == BPF_TRACE_FEXIT && + if ((prog->expected_attach_type == BPF_TRACE_FEXIT || + prog->expected_attach_type == BPF_LSM_MAC) && arg == nr_args) { if (!t) /* Default prog with 5 args. 6th arg is retval. */ diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index a91ad518c050..e10e216463ad 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -25,6 +25,7 @@ #include #include #include +#include #define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \ (map)->map_type == BPF_MAP_TYPE_CGROUP_ARRAY || \ @@ -1931,6 +1932,7 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type, switch (prog_type) { case BPF_PROG_TYPE_TRACING: + case BPF_PROG_TYPE_LSM: case BPF_PROG_TYPE_STRUCT_OPS: case BPF_PROG_TYPE_EXT: break; @@ -2169,28 +2171,53 @@ static int bpf_obj_get(const union bpf_attr *attr) attr->file_flags); } -static int bpf_tracing_prog_release(struct inode *inode, struct file *filp) +static int bpf_tramp_prog_release(struct inode *inode, struct file *filp) { struct bpf_prog *prog = filp->private_data; + /* Only CAP_MAC_ADMIN users are allowed to make changes to LSM hooks + */ + if (prog->type == BPF_PROG_TYPE_LSM && !capable(CAP_MAC_ADMIN)) + return -EPERM; + WARN_ON_ONCE(bpf_trampoline_unlink_prog(prog)); bpf_prog_put(prog); return 0; } -static const struct file_operations bpf_tracing_prog_fops = { - .release = bpf_tracing_prog_release, +static const struct file_operations bpf_tramp_prog_fops = { + .release = bpf_tramp_prog_release, .read = bpf_dummy_read, .write = bpf_dummy_write, }; -static int bpf_tracing_prog_attach(struct bpf_prog *prog) +static int bpf_tramp_prog_attach(struct bpf_prog *prog) { int tr_fd, err; - if (prog->expected_attach_type != BPF_TRACE_FENTRY && - prog->expected_attach_type != BPF_TRACE_FEXIT && - prog->type != BPF_PROG_TYPE_EXT) { + switch (prog->type) { + case BPF_PROG_TYPE_TRACING: + if (prog->expected_attach_type != BPF_TRACE_FENTRY && + prog->expected_attach_type != BPF_TRACE_FEXIT && + prog->type != BPF_PROG_TYPE_EXT) { + err = -EINVAL; + goto out_put_prog; + } + break; + case BPF_PROG_TYPE_LSM: + if (prog->expected_attach_type != BPF_LSM_MAC) { + err = -EINVAL; + goto out_put_prog; + } + /* Only CAP_MAC_ADMIN users are allowed to make changes to LSM + * hooks. + */ + if (!capable(CAP_MAC_ADMIN)) { + err = -EPERM; + goto out_put_prog; + } + break; + default: err = -EINVAL; goto out_put_prog; } @@ -2199,7 +2226,7 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog) if (err) goto out_put_prog; - tr_fd = anon_inode_getfd("bpf-tracing-prog", &bpf_tracing_prog_fops, + tr_fd = anon_inode_getfd("bpf-tramp-prog", &bpf_tramp_prog_fops, prog, O_CLOEXEC); if (tr_fd < 0) { WARN_ON_ONCE(bpf_trampoline_unlink_prog(prog)); @@ -2258,12 +2285,14 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr) if (prog->type != BPF_PROG_TYPE_RAW_TRACEPOINT && prog->type != BPF_PROG_TYPE_TRACING && prog->type != BPF_PROG_TYPE_EXT && + prog->type != BPF_PROG_TYPE_LSM && prog->type != BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE) { err = -EINVAL; goto out_put_prog; } if (prog->type == BPF_PROG_TYPE_TRACING || + prog->type == BPF_PROG_TYPE_LSM || prog->type == BPF_PROG_TYPE_EXT) { if (attr->raw_tracepoint.name) { /* The attach point for this category of programs @@ -2275,7 +2304,7 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr) if (prog->expected_attach_type == BPF_TRACE_RAW_TP) tp_name = prog->aux->attach_func_name; else - return bpf_tracing_prog_attach(prog); + return bpf_tramp_prog_attach(prog); } else { if (strncpy_from_user(buf, u64_to_user_ptr(attr->raw_tracepoint.name), diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c index 6b264a92064b..4974c14258a9 100644 --- a/kernel/bpf/trampoline.c +++ b/kernel/bpf/trampoline.c @@ -5,6 +5,7 @@ #include #include #include +#include /* dummy _ops. The verifier will operate on target program's ops. */ const struct bpf_verifier_ops bpf_extension_verifier_ops = { @@ -195,8 +196,9 @@ static int register_fentry(struct bpf_trampoline *tr, void *new_addr) */ #define BPF_MAX_TRAMP_PROGS 40 -static int bpf_trampoline_update(struct bpf_trampoline *tr) +static int bpf_trampoline_update(struct bpf_prog *prog) { + struct bpf_trampoline *tr = prog->aux->trampoline; void *old_image = tr->image + ((tr->selector + 1) & 1) * BPF_IMAGE_SIZE/2; void *new_image = tr->image + (tr->selector & 1) * BPF_IMAGE_SIZE/2; struct bpf_prog *progs_to_run[BPF_MAX_TRAMP_PROGS]; @@ -223,8 +225,11 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr) hlist_for_each_entry(aux, &tr->progs_hlist[BPF_TRAMP_FEXIT], tramp_hlist) *progs++ = aux->prog; - if (fexit_cnt) + if (fexit_cnt) { flags = BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_SKIP_FRAME; + if (prog->type == BPF_PROG_TYPE_LSM) + flags |= BPF_TRAMP_F_OVERRIDE_RETURN; + } /* Though the second half of trampoline page is unused a task could be * preempted in the middle of the first half of trampoline and two @@ -261,6 +266,7 @@ static enum bpf_tramp_prog_type bpf_attach_type_to_tramp(enum bpf_attach_type t) case BPF_TRACE_FENTRY: return BPF_TRAMP_FENTRY; case BPF_TRACE_FEXIT: + case BPF_LSM_MAC: return BPF_TRAMP_FEXIT; default: return BPF_TRAMP_REPLACE; @@ -307,11 +313,17 @@ int bpf_trampoline_link_prog(struct bpf_prog *prog) } hlist_add_head(&prog->aux->tramp_hlist, &tr->progs_hlist[kind]); tr->progs_cnt[kind]++; - err = bpf_trampoline_update(prog->aux->trampoline); + err = bpf_trampoline_update(prog); if (err) { hlist_del(&prog->aux->tramp_hlist); tr->progs_cnt[kind]--; } + + /* This is the first program to be attached to the LSM hook, the hook + * needs to be enabled. + */ + if (prog->type == BPF_PROG_TYPE_LSM && tr->progs_cnt[kind] == 1) + err = bpf_lsm_set_enabled(prog->aux->attach_func_name, true); out: mutex_unlock(&tr->mutex); return err; @@ -336,7 +348,11 @@ int bpf_trampoline_unlink_prog(struct bpf_prog *prog) } hlist_del(&prog->aux->tramp_hlist); tr->progs_cnt[kind]--; - err = bpf_trampoline_update(prog->aux->trampoline); + err = bpf_trampoline_update(prog); + + /* There are no more LSM programs, the hook should be disabled */ + if (prog->type == BPF_PROG_TYPE_LSM && tr->progs_cnt[kind] == 0) + err = bpf_lsm_set_enabled(prog->aux->attach_func_name, false); out: mutex_unlock(&tr->mutex); return err; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 1cc945daa9c8..6be11889678b 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "disasm.h" @@ -6405,8 +6406,9 @@ static int check_return_code(struct bpf_verifier_env *env) struct tnum range = tnum_range(0, 1); int err; - /* The struct_ops func-ptr's return type could be "void" */ - if (env->prog->type == BPF_PROG_TYPE_STRUCT_OPS && + /* LSM and struct_ops func-ptr's return type could be "void" */ + if ((env->prog->type == BPF_PROG_TYPE_STRUCT_OPS || + env->prog->type == BPF_PROG_TYPE_LSM) && !prog->aux->attach_func_proto->type) return 0; @@ -9794,7 +9796,9 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) if (prog->type == BPF_PROG_TYPE_STRUCT_OPS) return check_struct_ops_btf_id(env); - if (prog->type != BPF_PROG_TYPE_TRACING && !prog_extension) + if (prog->type != BPF_PROG_TYPE_TRACING && + prog->type != BPF_PROG_TYPE_LSM && + !prog_extension) return 0; if (!btf_id) { @@ -9924,8 +9928,16 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) if (!prog_extension) return -EINVAL; /* fallthrough */ + case BPF_LSM_MAC: case BPF_TRACE_FENTRY: case BPF_TRACE_FEXIT: + prog->aux->attach_func_name = tname; + if (prog->type == BPF_PROG_TYPE_LSM) { + ret = bpf_lsm_verify_prog(&env->log, prog); + if (ret < 0) + return ret; + } + if (!btf_type_is_func(t)) { verbose(env, "attach_btf_id %u is not a function\n", btf_id); @@ -9940,7 +9952,6 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) tr = bpf_trampoline_lookup(key); if (!tr) return -ENOMEM; - prog->aux->attach_func_name = tname; /* t is either vmlinux type or another program's type */ prog->aux->attach_func_proto = t; mutex_lock(&tr->mutex); From patchwork Thu Feb 20 17:52:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KP Singh X-Patchwork-Id: 11394811 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C59B817F0 for ; Thu, 20 Feb 2020 17:53:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A5E9124673 for ; Thu, 20 Feb 2020 17:53:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Rx0luW6p" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728847AbgBTRxU (ORCPT ); Thu, 20 Feb 2020 12:53:20 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:33839 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728806AbgBTRxD (ORCPT ); Thu, 20 Feb 2020 12:53:03 -0500 Received: by mail-wm1-f68.google.com with SMTP id s144so3339144wme.1 for ; Thu, 20 Feb 2020 09:53:01 -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=Adu6TFrPNSr18eey8+2tPmGfp+2eqe2mYVGsncyEkDQ=; b=Rx0luW6pGwCXCc8qCCqt+RFGihCY4OijwO71VThmmQFmAjf4MrKJzpkU7zKnp05oNH t0j2cMFMgg0MyhDSExfeNTqxIR4wUbTBQ9OehhS1E90aoTtWhZafYOb7ij8LmsDh2z6V 0CW6vl9fuGiR8IMgwDf9no8Oqay/cUVB8QzxQ= 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=Adu6TFrPNSr18eey8+2tPmGfp+2eqe2mYVGsncyEkDQ=; b=KFsDAwHnjzcnw5LOk+bNfswDtvdPyhQHqO6Q61L/oQpsc6CBxeZYoPEpp4zcHQvq2z wtxrTMQ9meTsKxXE5rYxlxmbORxoBGYRr8kHj4qWXZ6WWK4LYXurSPNaY1tZsXIyFrtW B5UGZnqxzKtmdx1btHLIcgkjO+bsTIgcwbZnD2GU/0EbtRI2CgJe0rE7mJDryRMeCsuf /YqzpwfSHXXJH4FW4Kxjh8qcC9zOb9OSBkwtTt8w6JYNq59iHTOl56ZXEAa/7vgk24Pa rkwUYBfwEYiDfTnw2A5+5AkcdLn+IPFQ7xHEWV1HEMxlTrwo0xkWuVna4ntHqDdJefA8 OxLg== X-Gm-Message-State: APjAAAVUXNBdOga/ocpH/EQML1Hhm3JQqDHOwO47zMB7x5cLPVHvSf9l X789q8awUnObqh7drPqtkK6fVw== X-Google-Smtp-Source: APXvYqw0z9ltTQGr1UG7ZjjOTiaFeE6G8AsIvJWW0WnaT+7vTOCJEX+dmrIG6ZG/8efmggTixAtTpA== X-Received: by 2002:a05:600c:34b:: with SMTP id u11mr5626356wmd.69.1582221181234; Thu, 20 Feb 2020 09:53:01 -0800 (PST) Received: from kpsingh-kernel.localdomain ([2620:0:105f:fd00:d960:542a:a1d:648a]) by smtp.gmail.com with ESMTPSA id r5sm363059wrt.43.2020.02.20.09.53.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Feb 2020 09:53:00 -0800 (PST) From: KP Singh To: linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-security-module@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , James Morris , Kees Cook , Thomas Garnier , Michael Halcrow , Paul Turner , Brendan Gregg , Jann Horn , Matthew Garrett , Christian Brauner , Florent Revest , Brendan Jackman , Martin KaFai Lau , Song Liu , Yonghong Song , "Serge E. Hallyn" , "David S. Miller" , Greg Kroah-Hartman , Nicolas Ferre , Stanislav Fomichev , Quentin Monnet , Andrey Ignatov , Joe Stringer Subject: [PATCH bpf-next v4 6/8] tools/libbpf: Add support for BPF_PROG_TYPE_LSM Date: Thu, 20 Feb 2020 18:52:48 +0100 Message-Id: <20200220175250.10795-7-kpsingh@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200220175250.10795-1-kpsingh@chromium.org> References: <20200220175250.10795-1-kpsingh@chromium.org> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: KP Singh Since BPF_PROG_TYPE_LSM uses the same attaching mechanism as BPF_PROG_TYPE_TRACING, the common logic is refactored into a static function bpf_program__attach_btf. A new API call bpf_program__attach_lsm is still added to avoid userspace conflicts if this ever changes in the future. Signed-off-by: KP Singh --- tools/lib/bpf/bpf.c | 3 ++- tools/lib/bpf/libbpf.c | 46 ++++++++++++++++++++++++++++++++-------- tools/lib/bpf/libbpf.h | 4 ++++ tools/lib/bpf/libbpf.map | 3 +++ 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index c6dafe563176..73220176728d 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -235,7 +235,8 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, memset(&attr, 0, sizeof(attr)); attr.prog_type = load_attr->prog_type; attr.expected_attach_type = load_attr->expected_attach_type; - if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS) { + if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS || + attr.prog_type == BPF_PROG_TYPE_LSM) { attr.attach_btf_id = load_attr->attach_btf_id; } else if (attr.prog_type == BPF_PROG_TYPE_TRACING || attr.prog_type == BPF_PROG_TYPE_EXT) { diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 514b1a524abb..d11139d5e76b 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -2351,16 +2351,14 @@ static int bpf_object__finalize_btf(struct bpf_object *obj) static inline bool libbpf_prog_needs_vmlinux_btf(struct bpf_program *prog) { - if (prog->type == BPF_PROG_TYPE_STRUCT_OPS) + if (prog->type == BPF_PROG_TYPE_STRUCT_OPS || + prog->type == BPF_PROG_TYPE_LSM) return true; /* BPF_PROG_TYPE_TRACING programs which do not attach to other programs * also need vmlinux BTF */ - if (prog->type == BPF_PROG_TYPE_TRACING && !prog->attach_prog_fd) - return true; - - return false; + return prog->type == BPF_PROG_TYPE_TRACING && !prog->attach_prog_fd; } static int bpf_object__load_vmlinux_btf(struct bpf_object *obj) @@ -4855,7 +4853,8 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt, load_attr.insns = insns; load_attr.insns_cnt = insns_cnt; load_attr.license = license; - if (prog->type == BPF_PROG_TYPE_STRUCT_OPS) { + if (prog->type == BPF_PROG_TYPE_STRUCT_OPS || + prog->type == BPF_PROG_TYPE_LSM) { load_attr.attach_btf_id = prog->attach_btf_id; } else if (prog->type == BPF_PROG_TYPE_TRACING || prog->type == BPF_PROG_TYPE_EXT) { @@ -4940,6 +4939,7 @@ int bpf_program__load(struct bpf_program *prog, char *license, __u32 kern_ver) int err = 0, fd, i, btf_id; if (prog->type == BPF_PROG_TYPE_TRACING || + prog->type == BPF_PROG_TYPE_LSM || prog->type == BPF_PROG_TYPE_EXT) { btf_id = libbpf_find_attach_btf_id(prog); if (btf_id <= 0) @@ -6179,6 +6179,7 @@ bool bpf_program__is_##NAME(const struct bpf_program *prog) \ } \ BPF_PROG_TYPE_FNS(socket_filter, BPF_PROG_TYPE_SOCKET_FILTER); +BPF_PROG_TYPE_FNS(lsm, BPF_PROG_TYPE_LSM); BPF_PROG_TYPE_FNS(kprobe, BPF_PROG_TYPE_KPROBE); BPF_PROG_TYPE_FNS(sched_cls, BPF_PROG_TYPE_SCHED_CLS); BPF_PROG_TYPE_FNS(sched_act, BPF_PROG_TYPE_SCHED_ACT); @@ -6245,6 +6246,8 @@ static struct bpf_link *attach_raw_tp(const struct bpf_sec_def *sec, struct bpf_program *prog); static struct bpf_link *attach_trace(const struct bpf_sec_def *sec, struct bpf_program *prog); +static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec, + struct bpf_program *prog); struct bpf_sec_def { const char *sec; @@ -6291,6 +6294,10 @@ static const struct bpf_sec_def section_defs[] = { SEC_DEF("freplace/", EXT, .is_attach_btf = true, .attach_fn = attach_trace), + SEC_DEF("lsm/", LSM, + .is_attach_btf = true, + .expected_attach_type = BPF_LSM_MAC, + .attach_fn = attach_lsm), BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP), BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT), BPF_PROG_SEC("lwt_in", BPF_PROG_TYPE_LWT_IN), @@ -6553,6 +6560,7 @@ static int bpf_object__collect_struct_ops_map_reloc(struct bpf_object *obj, } #define BTF_TRACE_PREFIX "btf_trace_" +#define BTF_LSM_PREFIX "bpf_lsm_" #define BTF_MAX_NAME_SIZE 128 static int find_btf_by_prefix_kind(const struct btf *btf, const char *prefix, @@ -6580,6 +6588,9 @@ static inline int __find_vmlinux_btf_id(struct btf *btf, const char *name, if (attach_type == BPF_TRACE_RAW_TP) err = find_btf_by_prefix_kind(btf, BTF_TRACE_PREFIX, name, BTF_KIND_TYPEDEF); + else if (attach_type == BPF_LSM_MAC) + err = find_btf_by_prefix_kind(btf, BTF_LSM_PREFIX, name, + BTF_KIND_FUNC); else err = btf__find_by_name_kind(btf, name, BTF_KIND_FUNC); @@ -7354,7 +7365,8 @@ static struct bpf_link *attach_raw_tp(const struct bpf_sec_def *sec, return bpf_program__attach_raw_tracepoint(prog, tp_name); } -struct bpf_link *bpf_program__attach_trace(struct bpf_program *prog) +/* Common logic for all BPF program types that attach to a btf_id */ +static struct bpf_link *bpf_program__attach_btf(struct bpf_program *prog) { char errmsg[STRERR_BUFSIZE]; struct bpf_link_fd *link; @@ -7376,7 +7388,7 @@ struct bpf_link *bpf_program__attach_trace(struct bpf_program *prog) if (pfd < 0) { pfd = -errno; free(link); - pr_warn("program '%s': failed to attach to trace: %s\n", + pr_warn("program '%s': failed to attach to: %s\n", bpf_program__title(prog, false), libbpf_strerror_r(pfd, errmsg, sizeof(errmsg))); return ERR_PTR(pfd); @@ -7385,10 +7397,26 @@ struct bpf_link *bpf_program__attach_trace(struct bpf_program *prog) return (struct bpf_link *)link; } +struct bpf_link *bpf_program__attach_trace(struct bpf_program *prog) +{ + return bpf_program__attach_btf(prog); +} + +struct bpf_link *bpf_program__attach_lsm(struct bpf_program *prog) +{ + return bpf_program__attach_btf(prog); +} + static struct bpf_link *attach_trace(const struct bpf_sec_def *sec, struct bpf_program *prog) { - return bpf_program__attach_trace(prog); + return bpf_program__attach_btf(prog); +} + +static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec, + struct bpf_program *prog) +{ + return bpf_program__attach_btf(prog); } struct bpf_link *bpf_program__attach(struct bpf_program *prog) diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 3fe12c9d1f92..3f72323f205b 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -243,6 +243,8 @@ bpf_program__attach_raw_tracepoint(struct bpf_program *prog, LIBBPF_API struct bpf_link * bpf_program__attach_trace(struct bpf_program *prog); +LIBBPF_API struct bpf_link * +bpf_program__attach_lsm(struct bpf_program *prog); struct bpf_map; LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map); struct bpf_insn; @@ -316,6 +318,7 @@ LIBBPF_API int bpf_program__set_socket_filter(struct bpf_program *prog); LIBBPF_API int bpf_program__set_tracepoint(struct bpf_program *prog); LIBBPF_API int bpf_program__set_raw_tracepoint(struct bpf_program *prog); LIBBPF_API int bpf_program__set_kprobe(struct bpf_program *prog); +LIBBPF_API int bpf_program__set_lsm(struct bpf_program *prog); LIBBPF_API int bpf_program__set_sched_cls(struct bpf_program *prog); LIBBPF_API int bpf_program__set_sched_act(struct bpf_program *prog); LIBBPF_API int bpf_program__set_xdp(struct bpf_program *prog); @@ -338,6 +341,7 @@ LIBBPF_API bool bpf_program__is_socket_filter(const struct bpf_program *prog); LIBBPF_API bool bpf_program__is_tracepoint(const struct bpf_program *prog); LIBBPF_API bool bpf_program__is_raw_tracepoint(const struct bpf_program *prog); LIBBPF_API bool bpf_program__is_kprobe(const struct bpf_program *prog); +LIBBPF_API bool bpf_program__is_lsm(const struct bpf_program *prog); LIBBPF_API bool bpf_program__is_sched_cls(const struct bpf_program *prog); LIBBPF_API bool bpf_program__is_sched_act(const struct bpf_program *prog); LIBBPF_API bool bpf_program__is_xdp(const struct bpf_program *prog); diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index b035122142bb..8df332a528a0 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -227,10 +227,13 @@ LIBBPF_0.0.7 { bpf_probe_large_insn_limit; bpf_prog_attach_xattr; bpf_program__attach; + bpf_program__attach_lsm; bpf_program__name; bpf_program__is_extension; + bpf_program__is_lsm; bpf_program__is_struct_ops; bpf_program__set_extension; + bpf_program__set_lsm; bpf_program__set_struct_ops; btf__align_of; libbpf_find_kernel_btf; From patchwork Thu Feb 20 17:52:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KP Singh X-Patchwork-Id: 11394807 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1EBCF1395 for ; Thu, 20 Feb 2020 17:53:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E0ADA24673 for ; Thu, 20 Feb 2020 17:53:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="B3piX1VD" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728845AbgBTRxG (ORCPT ); Thu, 20 Feb 2020 12:53:06 -0500 Received: from mail-wr1-f66.google.com ([209.85.221.66]:46381 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728836AbgBTRxG (ORCPT ); Thu, 20 Feb 2020 12:53:06 -0500 Received: by mail-wr1-f66.google.com with SMTP id z7so5573308wrl.13 for ; Thu, 20 Feb 2020 09:53:03 -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=adfWj6krnYMDay+GPoQfqpNZuN5MZlEFMLgjeZEuGG8=; b=B3piX1VDd0y+GiS3xOijNGSIS70I0ytViQp349mNrJ9q866rEPEN8mdD4TzrOQT4WM CwRexqXTw0sefFk71rFC7BkFTTbNbCwH5qtot+ZlZxLAzhoO9BrOS55PvQNOFIlSPuyO ia7M5YF+7sylLkAXIQY8vfxLf3QJ2PkYBVCzQ= 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=adfWj6krnYMDay+GPoQfqpNZuN5MZlEFMLgjeZEuGG8=; b=TWLrHb3jg7FT8mq8xUIPPOr0l8rIvsX/HG92djw9BvoVD/SjqXrJuCMcxi/9TPfk+N ETga7hHxlTOWlIMiWuZiXRvUSO0huD4B19Q7qNUSnlRsAkJV1+WGcesiBRyn94S8KABc F/xf0XxHOpjf4BEpSYXETbd73bTO4ccnC0gym8s8FIJ/Elj7FlvBHz+gKDCfr8fMGoLV tCuz6UPIzE+mDiT1gHHMKqTpLjb1tXmBBQKG7TneheV5ObJVMdjeKdAdpyHTPP/2eEmm 0c8Vfcf27GAvyJtrns1lJFmhVp1u64jE3DqOdzqAyALQxF2j1AeAB55L0xQhw+f9mUkC svTA== X-Gm-Message-State: APjAAAXut3+GTdW+rH72BLA+ptXrz3bCBXbqVmZ1+p6QW1tHxINyMlp8 pPj40MQV1k8KhrOOG9bq9ydrzA== X-Google-Smtp-Source: APXvYqyKZvCNuUcqJozkMRYf/cFD+U0nFmP2+o8GPNyDe0jeSaF09jaWPuXvxncvQlu+uLdva4G56Q== X-Received: by 2002:a5d:4a84:: with SMTP id o4mr43474331wrq.396.1582221183000; Thu, 20 Feb 2020 09:53:03 -0800 (PST) Received: from kpsingh-kernel.localdomain ([2620:0:105f:fd00:d960:542a:a1d:648a]) by smtp.gmail.com with ESMTPSA id r5sm363059wrt.43.2020.02.20.09.53.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Feb 2020 09:53:02 -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 , Florent Revest , Brendan Jackman , Martin KaFai Lau , Song Liu , Yonghong Song , "Serge E. Hallyn" , "David S. Miller" , Greg Kroah-Hartman , Nicolas Ferre , Stanislav Fomichev , Quentin Monnet , Andrey Ignatov , Joe Stringer Subject: [PATCH bpf-next v4 7/8] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM Date: Thu, 20 Feb 2020 18:52:49 +0100 Message-Id: <20200220175250.10795-8-kpsingh@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200220175250.10795-1-kpsingh@chromium.org> References: <20200220175250.10795-1-kpsingh@chromium.org> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: KP Singh * Load a BPF program that hooks to the mprotect calls. * Attach the program to the "file_mprotect" LSM hook. * Do an mprotect on some memory allocated on the heap * Verify if the return value is overridden. * Verify if the audit event was received using the shared global result variable. Signed-off-by: KP Singh Reviewed-by: Brendan Jackman Reviewed-by: Florent Revest Reviewed-by: Thomas Garnier --- tools/testing/selftests/bpf/lsm_helpers.h | 19 ++++ .../selftests/bpf/prog_tests/lsm_mprotect.c | 96 +++++++++++++++++++ .../selftests/bpf/progs/lsm_mprotect_audit.c | 48 ++++++++++ .../selftests/bpf/progs/lsm_mprotect_mac.c | 53 ++++++++++ 4 files changed, 216 insertions(+) create mode 100644 tools/testing/selftests/bpf/lsm_helpers.h create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_mprotect.c create mode 100644 tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c create mode 100644 tools/testing/selftests/bpf/progs/lsm_mprotect_mac.c diff --git a/tools/testing/selftests/bpf/lsm_helpers.h b/tools/testing/selftests/bpf/lsm_helpers.h new file mode 100644 index 000000000000..b973ec1c4a0b --- /dev/null +++ b/tools/testing/selftests/bpf/lsm_helpers.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Copyright 2019 Google LLC. + */ +#ifndef _LSM_HELPERS_H +#define _LSM_HELPERS_H + +struct lsm_mprotect_result { + /* This ensures that the LSM Hook only monitors the PID requested + * by the loader + */ + __u32 monitored_pid; + /* The number of mprotect calls for the monitored PID. + */ + __u32 mprotect_count; +}; + +#endif /* _LSM_HELPERS_H */ diff --git a/tools/testing/selftests/bpf/prog_tests/lsm_mprotect.c b/tools/testing/selftests/bpf/prog_tests/lsm_mprotect.c new file mode 100644 index 000000000000..93c3b5fb2ef0 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/lsm_mprotect.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright 2019 Google LLC. + */ + +#include +#include +#include +#include +#include "lsm_helpers.h" +#include "lsm_mprotect_audit.skel.h" +#include "lsm_mprotect_mac.skel.h" + +int heap_mprotect(void) +{ + void *buf; + long sz; + + sz = sysconf(_SC_PAGESIZE); + if (sz < 0) + return sz; + + buf = memalign(sz, 2 * sz); + if (buf == NULL) + return -ENOMEM; + + return mprotect(buf, sz, PROT_READ | PROT_EXEC); +} + +void test_lsm_mprotect_audit(void) +{ + struct lsm_mprotect_result *result; + struct lsm_mprotect_audit *skel = NULL; + int err, duration = 0; + + skel = lsm_mprotect_audit__open_and_load(); + if (CHECK(!skel, "skel_load", "lsm_mprotect_audit skeleton failed\n")) + goto close_prog; + + err = lsm_mprotect_audit__attach(skel); + if (CHECK(err, "attach", "lsm_mprotect_audit attach failed: %d\n", err)) + goto close_prog; + + result = &skel->bss->result; + result->monitored_pid = getpid(); + + err = heap_mprotect(); + if (CHECK(err < 0, "heap_mprotect", "err %d errno %d\n", err, errno)) + goto close_prog; + + /* Make sure mprotect_audit program was triggered + * and detected an mprotect on the heap. + */ + CHECK_FAIL(result->mprotect_count != 1); + +close_prog: + lsm_mprotect_audit__destroy(skel); +} + +void test_lsm_mprotect_mac(void) +{ + struct lsm_mprotect_result *result; + struct lsm_mprotect_mac *skel = NULL; + int err, duration = 0; + + skel = lsm_mprotect_mac__open_and_load(); + if (CHECK(!skel, "skel_load", "lsm_mprotect_mac skeleton failed\n")) + goto close_prog; + + err = lsm_mprotect_mac__attach(skel); + if (CHECK(err, "attach", "lsm_mprotect_mac attach failed: %d\n", err)) + goto close_prog; + + result = &skel->bss->result; + result->monitored_pid = getpid(); + + err = heap_mprotect(); + if (CHECK(errno != EPERM, "heap_mprotect", "want errno=EPERM, got %d\n", + errno)) + goto close_prog; + + /* Make sure mprotect_mac program was triggered + * and detected an mprotect on the heap. + */ + CHECK_FAIL(result->mprotect_count != 1); + +close_prog: + lsm_mprotect_mac__destroy(skel); +} + +void test_lsm_mprotect(void) +{ + test_lsm_mprotect_audit(); + test_lsm_mprotect_mac(); +} diff --git a/tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c b/tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c new file mode 100644 index 000000000000..c68fb02b57fa --- /dev/null +++ b/tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright 2019 Google LLC. + */ + +#include +#include +#include "bpf_trace_helpers.h" +#include +#include "lsm_helpers.h" + +char _license[] SEC("license") = "GPL"; + +struct lsm_mprotect_result result = { + .mprotect_count = 0, + .monitored_pid = 0, +}; + +/* + * Define some of the structs used in the BPF program. + * Only the field names and their sizes need to be the + * same as the kernel type, the order is irrelevant. + */ +struct mm_struct { + unsigned long start_brk, brk; +} __attribute__((preserve_access_index)); + +struct vm_area_struct { + unsigned long vm_start, vm_end; + struct mm_struct *vm_mm; +} __attribute__((preserve_access_index)); + +SEC("lsm/file_mprotect") +int BPF_PROG(mprotect_audit, struct vm_area_struct *vma, + unsigned long reqprot, unsigned long prot) +{ + __u32 pid = bpf_get_current_pid_tgid(); + int is_heap = 0; + + is_heap = (vma->vm_start >= vma->vm_mm->start_brk && + vma->vm_end <= vma->vm_mm->brk); + + if (is_heap && result.monitored_pid == pid) + result.mprotect_count++; + + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/lsm_mprotect_mac.c b/tools/testing/selftests/bpf/progs/lsm_mprotect_mac.c new file mode 100644 index 000000000000..c0ae344593e8 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/lsm_mprotect_mac.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright 2019 Google LLC. + */ + +#include +#include +#include "bpf_trace_helpers.h" +#include +#include "lsm_helpers.h" + +char _license[] SEC("license") = "GPL"; + +struct lsm_mprotect_result result = { + .mprotect_count = 0, + .monitored_pid = 0, +}; + +/* + * Define some of the structs used in the BPF program. + * Only the field names and their sizes need to be the + * same as the kernel type, the order is irrelevant. + */ +struct mm_struct { + unsigned long start_brk, brk; +} __attribute__((preserve_access_index)); + +struct vm_area_struct { + unsigned long vm_start, vm_end; + struct mm_struct *vm_mm; +} __attribute__((preserve_access_index)); + +SEC("lsm/file_mprotect") +int BPF_PROG(mprotect_mac, struct vm_area_struct *vma, + unsigned long reqprot, unsigned long prot, int ret) +{ + if (ret != 0) + return ret; + + __u32 pid = bpf_get_current_pid_tgid(); + int is_heap = 0; + + is_heap = (vma->vm_start >= vma->vm_mm->start_brk && + vma->vm_end <= vma->vm_mm->brk); + + if (is_heap && result.monitored_pid == pid) { + result.mprotect_count++; + ret = -EPERM; + } + + return ret; +} From patchwork Thu Feb 20 17:52:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KP Singh X-Patchwork-Id: 11394805 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 53C6117E0 for ; Thu, 20 Feb 2020 17:53:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2188524673 for ; Thu, 20 Feb 2020 17:53:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="oCXJA4iN" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728517AbgBTRxO (ORCPT ); Thu, 20 Feb 2020 12:53:14 -0500 Received: from mail-wr1-f65.google.com ([209.85.221.65]:38690 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728846AbgBTRxI (ORCPT ); Thu, 20 Feb 2020 12:53:08 -0500 Received: by mail-wr1-f65.google.com with SMTP id e8so5648136wrm.5 for ; Thu, 20 Feb 2020 09:53:05 -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=nkZvckj4wnd1GhrUFR4okZmuZW+gAsxm+Y3ZecxjX+A=; b=oCXJA4iNDMJxI4eWXQms3Gpam17Cx4cXzNmACSL20BsHLoBsuXKXw+elnAC4MaGHcz Ogce6XK20NWPQ4qlBWhz6lRkorjh5ReCH9dqRW7c0sgzLFJFpjwGmUoenu2UvDeeEDjt mPlMQo2YqLlQ+p+AEvTOCkwIpPZ/5MMyldPuo= 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=nkZvckj4wnd1GhrUFR4okZmuZW+gAsxm+Y3ZecxjX+A=; b=Q1vMbpTwIxkap6MXnACPMPxyYyJHNSENtpltwJcfiqB35O9jy+7/DZU82j1xIdhRUQ OlkBFdQ0DSAn4jUhhH9PSRAcTbtR8+lE+LKkadtDLyCZx4oo87fOr8xXkAMWuoqugB9+ eV+TZ6E0fDfIsE3p/K5dxwuyREAKz+wj3gGg3wrSUEFa+SoHPrV4l/3/ts3a3HCwtqf5 BmX2/plogSwQLVoPAiRFLeXlvX20De6/4z38jqsncqE2qblCjHLWN3T55lvnsAhkxqxX 8thjKxlilQi+/e0ioKmvmviZ7hnEzSLmtLnKW1lUhTPScS/hguu6Uk7iz8LKCFNNCt3P Xwmg== X-Gm-Message-State: APjAAAV7irMuTV60CwTp/zDjAGGA7p6TcOcs/BnETy6wSXBnkPOZ+o0b 9ub8hQWkW3mXtnh2Elboux0GyA== X-Google-Smtp-Source: APXvYqyoc0OvbZCWrmRmpqkKnCqwRB6+BRIPlIZP00OzqvEkOYVHJsqch1rLLWmle5n5duAaiaT42g== X-Received: by 2002:adf:f283:: with SMTP id k3mr41832141wro.69.1582221184726; Thu, 20 Feb 2020 09:53:04 -0800 (PST) Received: from kpsingh-kernel.localdomain ([2620:0:105f:fd00:d960:542a:a1d:648a]) by smtp.gmail.com with ESMTPSA id r5sm363059wrt.43.2020.02.20.09.53.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Feb 2020 09:53:04 -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 , Florent Revest , Brendan Jackman , Martin KaFai Lau , Song Liu , Yonghong Song , "Serge E. Hallyn" , "David S. Miller" , Greg Kroah-Hartman , Nicolas Ferre , Stanislav Fomichev , Quentin Monnet , Andrey Ignatov , Joe Stringer Subject: [PATCH bpf-next v4 8/8] bpf: lsm: Add Documentation Date: Thu, 20 Feb 2020 18:52:50 +0100 Message-Id: <20200220175250.10795-9-kpsingh@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200220175250.10795-1-kpsingh@chromium.org> References: <20200220175250.10795-1-kpsingh@chromium.org> MIME-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: From: KP Singh Document how eBPF programs (BPF_PROG_TYPE_LSM) can be loaded and attached (BPF_LSM_MAC) to the LSM hooks. Signed-off-by: KP Singh Reviewed-by: Brendan Jackman Reviewed-by: Florent Revest Reviewed-by: Thomas Garnier --- Documentation/bpf/bpf_lsm.rst | 147 ++++++++++++++++++++++++++++++++++ Documentation/bpf/index.rst | 1 + 2 files changed, 148 insertions(+) create mode 100644 Documentation/bpf/bpf_lsm.rst diff --git a/Documentation/bpf/bpf_lsm.rst b/Documentation/bpf/bpf_lsm.rst new file mode 100644 index 000000000000..9d7ec8cb431d --- /dev/null +++ b/Documentation/bpf/bpf_lsm.rst @@ -0,0 +1,147 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright 2019 Google LLC. + +================ +LSM BPF Programs +================ + +These BPF programs allow runtime instrumentation of the LSM hooks by privileged +users to implement system-wide MAC (Mandatory Access Control) and Audit +policies using eBPF. Since these program end up modifying the MAC policies of +the system, they require both ``CAP_MAC_ADMIN`` and also require +``CAP_SYS_ADMIN`` for the loading of BPF programs. + +Structure +--------- + +The example shows an eBPF program that can be attached to the ``file_mprotect`` +LSM hook: + +.. c:function:: int file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot); + +eBPF programs that use :doc:`/bpf/btf` do not need to include kernel headers +for accessing information from the attached eBPF program's context. They can +simply declare the structures in the eBPF program and only specify the fields +that need to be accessed. + +.. code-block:: c + + struct mm_struct { + unsigned long start_brk, brk, start_stack; + } __attribute__((preserve_access_index)); + + struct vm_area_struct { + unsigned long start_brk, brk, start_stack; + unsigned long vm_start, vm_end; + struct mm_struct *vm_mm; + } __attribute__((preserve_access_index)); + + +.. note:: Only the size and the names of the fields must match the type in the + kernel and the order of the fields is irrelevant. + +This can be further simplified (if one has access to the BTF information at +build time) by generating the ``vmlinux.h`` with: + +.. code-block:: console + + # bpftool dump file format c > vmlinux.h + +.. note:: ``path-to-btf-vmlinux`` can be ``/sys/kernel/btf/vmlinux`` if the + build environment matches the environment the BPF programs are + deployed in. + +The ``vmlinux.h`` can then simply be included in the BPF programs without +requiring the definition of the types. + +The eBPF programs can be declared using the``BPF_PROG`` +macros defined in `tools/testing/selftests/bpf/bpf_trace_helpers.h`_. In this +example: + + * ``"lsm/file_mprotect"`` indicates the LSM hook that the program must + be attached to + * ``mprotect_audit`` is the name of the eBPF program + +.. code-block:: c + + SEC("lsm/file_mprotect") + int BPF_PROG(mprotect_audit, struct vm_area_struct *vma, + unsigned long reqprot, unsigned long prot, int ret) + { + /* Ret is the return value from the previous BPF program + * or 0 if it's the first hook. + */ + if (ret != 0) + return ret; + + int is_heap; + + is_heap = (vma->vm_start >= vma->vm_mm->start_brk && + vma->vm_end <= vma->vm_mm->brk); + + /* Return an -EPERM or write information to the perf events buffer + * for auditing + */ + } + +The ``__attribute__((preserve_access_index))`` is a clang feature that allows +the BPF verifier to update the offsets for the access at runtime using the +:doc:`/bpf/btf` information. Since the BPF verifier is aware of the types, it +also validates all the accesses made to the various types in the eBPF program. + +Loading +------- + +eBPP programs can be loaded with the :manpage:`bpf(2)` syscall's +``BPF_PROG_LOAD`` operation or more simply by using the the libbpf helper +``bpf_prog_load_xattr``: + + +.. code-block:: c + + struct bpf_prog_load_attr attr = { + .file = "./prog.o", + }; + struct bpf_object *prog_obj; + struct bpf_program *prog; + int prog_fd; + + bpf_prog_load_xattr(&attr, &prog_obj, &prog_fd); + +Attachment to LSM Hooks +----------------------- + +The LSM allows attachment of eBPF programs as LSM hooks using :manpage:`bpf(2)` +syscall's ``BPF_PROG_ATTACH`` operation or more simply by +using the libbpf helper ``bpf_program__attach_lsm``. In the code shown below +``prog`` is the eBPF program loaded using ``BPF_PROG_LOAD``: + +.. code-block:: c + + struct bpf_link *link; + + link = bpf_program__attach_lsm(prog); + +The program can be detached from the LSM hook by *destroying* the ``link`` +link returned by ``bpf_program__attach_lsm``: + +.. code-block:: c + + link->destroy(); + +Examples +-------- + +Example eBPF programs can be found in +`tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c`_ and `tools/testing/selftests/bpf/progs/lsm_mprotect_mac.c`_ and the corresponding +userspace code in `tools/testing/selftests/bpf/prog_tests/lsm_mprotect.c`_ + +.. Links +.. _tools/testing/selftests/bpf/bpf_trace_helpers.h: + https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/selftests/bpf/bpf_trace_helpers.h +.. _tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c: + https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c +.. _tools/testing/selftests/bpf/progs/lsm_mprotect_mac.c: + https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm_mprotect_mac.c +.. _tools/testing/selftests/bpf/prog_tests/lsm_mprotect.c: + https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/prog_tests/lsm_mprotect.c diff --git a/Documentation/bpf/index.rst b/Documentation/bpf/index.rst index 4f5410b61441..2c3d3c0cb7bb 100644 --- a/Documentation/bpf/index.rst +++ b/Documentation/bpf/index.rst @@ -45,6 +45,7 @@ Program types prog_cgroup_sockopt prog_cgroup_sysctl prog_flow_dissector + bpf_lsm Testing BPF