Linux-Security-Module Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH bpf-next v7 0/8] MAC and Audit policy using eBPF (KRSI)
@ 2020-03-26 14:28 KP Singh
  2020-03-26 14:28 ` [PATCH bpf-next v7 1/8] bpf: Introduce BPF_PROG_TYPE_LSM KP Singh
                   ` (7 more replies)
  0 siblings, 8 replies; 33+ messages in thread
From: KP Singh @ 2020-03-26 14:28 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Paul Turner, Jann Horn, Florent Revest, Brendan Jackman,
	Greg Kroah-Hartman

From: KP Singh <kpsingh@google.com>

# v6 -> v7

  https://lore.kernel.org/bpf/20200325152629.6904-1-kpsingh@chromium.org/

* Removed __weak from the LSM attachment nops per Kees' suggestion.
  Will send a separate patch (if needed) to update the noinline
  definition in include/linux/compiler_attributes.h.
* waitpid to wait specifically for the forked child in selftests.
* Comment format fixes in security/... as suggested by Casey.
* Added Acks from Kees and Andrii and Casey's Reviewed-by: tags to
  the respective patches.
* Rebase

# v5 -> v6

  https://lore.kernel.org/bpf/20200323164415.12943-1-kpsingh@chromium.org/

* Updated LSM_HOOK macro to define a default value and cleaned up the
  BPF LSM hook declarations.
* Added Yonghong's Acks and Kees' Reviewed-by tags.
* Simplification of the selftest code.
* Rebase and fixes suggested by Andrii and Yonghong and some other minor
  fixes noticed in internal review.

# v4 -> v5

  https://lore.kernel.org/bpf/20200220175250.10795-1-kpsingh@chromium.org/

* Removed static keys and special casing of BPF calls from the LSM
  framework.
* Initialized the BPF callbacks (nops) as proper LSM hooks.
* Updated to using the newly introduced BPF_TRAMP_MODIFY_RETURN
  trampolines in https://lkml.org/lkml/2020/3/4/877
* Addressed Andrii's feedback and rebased.

# v3 -> v4

* Moved away from allocating a separate security_hook_heads and adding a
  new special case for arch_prepare_bpf_trampoline to using BPF fexit
  trampolines called from the right place in the LSM hook and toggled by
  static keys based on the discussion in:

  https://lore.kernel.org/bpf/CAG48ez25mW+_oCxgCtbiGMX07g_ph79UOJa07h=o_6B6+Q-u5g@mail.gmail.com/

* Since the code does not deal with security_hook_heads anymore, it goes
  from "being a BPF LSM" to "BPF program attachment to LSM hooks".
* Added a new test case which ensures that the BPF programs' return value
  is reflected by the LSM hook.

# v2 -> v3 does not change the overall design and has some minor fixes:

* LSM_ORDER_LAST is introduced to represent the behaviour of the BPF LSM
* Fixed the inadvertent clobbering of the LSM Hook error codes
* Added GPL license requirement to the commit log
* The lsm_hook_idx is now the more conventional 0-based index
* Some changes were split into a separate patch ("Load btf_vmlinux only
  once per object")

  https://lore.kernel.org/bpf/20200117212825.11755-1-kpsingh@chromium.org/

* Addressed Andrii's feedback on the BTF implementation
* Documentation update for using generated vmlinux.h to simplify
  programs
* Rebase

# Changes since v1

  https://lore.kernel.org/bpf/20191220154208.15895-1-kpsingh@chromium.org

* Eliminate the requirement to maintain LSM hooks separately in
  security/bpf/hooks.h Use BPF trampolines to dynamically allocate
  security hooks
* Drop the use of securityfs as bpftool provides the required
  introspection capabilities.  Update the tests to use the bpf_skeleton
  and global variables
* Use O_CLOEXEC anonymous fds to represent BPF attachment in line with
  the other BPF programs with the possibility to use bpf program pinning
  in the future to provide "permanent attachment".
* Drop the logic based on prog names for handling re-attachment.
* Drop bpf_lsm_event_output from this series and send it as a separate
  patch.

# Motivation

Google does analysis of rich runtime security data to detect and thwart
threats in real-time. Currently, this is done in custom kernel modules
but we would like to replace this with something that's upstream and
useful to others.

The current kernel infrastructure for providing telemetry (Audit, Perf
etc.) is disjoint from access enforcement (i.e. LSMs).  Augmenting the
information provided by audit requires kernel changes to audit, its
policy language and user-space components. Furthermore, building a MAC
policy based on the newly added telemetry data requires changes to
various LSMs and their respective policy languages.

This patchset allows BPF programs to be attached to LSM hooks This
facilitates a unified and dynamic (not requiring re-compilation of the
kernel) audit and MAC policy.

# Why an LSM?

Linux Security Modules target security behaviours rather than the
kernel's API. For example, it's easy to miss out a newly added system
call for executing processes (eg. execve, execveat etc.) but the LSM
framework ensures that all process executions trigger the relevant hooks
irrespective of how the process was executed.

Allowing users to implement LSM hooks at runtime also benefits the LSM
eco-system by enabling a quick feedback loop from the security community
about the kind of behaviours that the LSM Framework should be targeting.

# How does it work?

The patchset introduces a new eBPF (https://docs.cilium.io/en/v1.6/bpf/)
program type BPF_PROG_TYPE_LSM which can only be attached to LSM hooks.
Loading and attachment of BPF programs requires CAP_SYS_ADMIN.

The new LSM registers nop functions (bpf_lsm_<hook_name>) as LSM hook
callbacks. Their purpose is to provide a definite point where BPF
programs can be attached as BPF_TRAMP_MODIFY_RETURN trampoline programs
for hooks that return an int, and BPF_TRAMP_FEXIT trampoline programs
for void LSM hooks.

Audit logs can be written using a format chosen by the eBPF program to
the perf events buffer or to global eBPF variables or maps and can be
further processed in user-space.

# BTF Based Design

The current design uses BTF:

  * https://facebookmicrosites.github.io/bpf/blog/2018/11/14/btf-enhancement.html
  * https://lwn.net/Articles/803258

which allows verifiable read-only structure accesses by field names
rather than fixed offsets. This allows accessing the hook parameters
using a dynamically created context which provides a certain degree of
ABI stability:


// Only declare the structure and fields intended to be used
// in the program
struct vm_area_struct {
  unsigned long vm_start;
} __attribute__((preserve_access_index));

// Declare the eBPF program mprotect_audit which attaches to
// to the file_mprotect LSM hook and accepts three arguments.
SEC("lsm/file_mprotect")
int BPF_PROG(mprotect_audit, struct vm_area_struct *vma,
       unsigned long reqprot, unsigned long prot, int ret)
{
  unsigned long vm_start = vma->vm_start;

  return 0;
}

By relocating field offsets, BTF makes a large portion of kernel data
structures readily accessible across kernel versions without requiring a
large corpus of BPF helper functions and requiring recompilation with
every kernel version. The BTF type information is also used by the BPF
verifier to validate memory accesses within the BPF program and also
prevents arbitrary writes to the kernel memory.

The limitations of BTF compatibility are described in BPF Co-Re
(http://vger.kernel.org/bpfconf2019_talks/bpf-core.pdf, i.e. field
renames, #defines and changes to the signature of LSM hooks).  This
design imposes that the MAC policy (eBPF programs) be updated when the
inspected kernel structures change outside of BTF compatibility
guarantees. In practice, this is only required when a structure field
used by a current policy is removed (or renamed) or when the used LSM
hooks change. We expect the maintenance cost of these changes to be
acceptable as compared to the design presented in the RFC.

(https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/).

# Usage Examples

A simple example and some documentation is included in the patchset.
In order to better illustrate the capabilities of the framework some
more advanced prototype (not-ready for review) code has also been
published separately:

* Logging execution events (including environment variables and
  arguments)
  https://github.com/sinkap/linux-krsi/blob/patch/v1/examples/samples/bpf/lsm_audit_env.c

* Detecting deletion of running executables:
  https://github.com/sinkap/linux-krsi/blob/patch/v1/examples/samples/bpf/lsm_detect_exec_unlink.c

* Detection of writes to /proc/<pid>/mem:
  https://github.com/sinkap/linux-krsi/blob/patch/v1/examples/samples/bpf/lsm_audit_env.c

We have updated Google's internal telemetry infrastructure and have
started deploying this LSM on our Linux Workstations. This gives us more
confidence in the real-world applications of such a system.

KP Singh (8):
  bpf: Introduce BPF_PROG_TYPE_LSM
  security: Refactor declaration of LSM hooks
  bpf: lsm: provide attachment points for BPF LSM programs
  bpf: lsm: Implement attach, detach and execution
  bpf: lsm: Initialize the BPF LSM hooks
  tools/libbpf: Add support for BPF_PROG_TYPE_LSM
  bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
  bpf: lsm: Add Documentation

 Documentation/bpf/bpf_lsm.rst                 | 150 +++++
 Documentation/bpf/index.rst                   |   1 +
 MAINTAINERS                                   |   1 +
 include/linux/bpf.h                           |   3 +
 include/linux/bpf_lsm.h                       |  33 +
 include/linux/bpf_types.h                     |   4 +
 include/linux/lsm_hook_defs.h                 | 381 +++++++++++
 include/linux/lsm_hooks.h                     | 628 +-----------------
 include/uapi/linux/bpf.h                      |   2 +
 init/Kconfig                                  |  12 +
 kernel/bpf/Makefile                           |   1 +
 kernel/bpf/bpf_lsm.c                          |  59 ++
 kernel/bpf/btf.c                              |   9 +-
 kernel/bpf/syscall.c                          |  57 +-
 kernel/bpf/trampoline.c                       |  17 +-
 kernel/bpf/verifier.c                         |  19 +-
 kernel/trace/bpf_trace.c                      |  12 +-
 security/Kconfig                              |  10 +-
 security/Makefile                             |   2 +
 security/bpf/Makefile                         |   5 +
 security/bpf/hooks.c                          |  26 +
 security/security.c                           |  41 +-
 tools/include/uapi/linux/bpf.h                |   2 +
 tools/lib/bpf/bpf.c                           |   3 +-
 tools/lib/bpf/libbpf.c                        |  39 +-
 tools/lib/bpf/libbpf.h                        |   4 +
 tools/lib/bpf/libbpf.map                      |   3 +
 tools/lib/bpf/libbpf_probes.c                 |   1 +
 tools/testing/selftests/bpf/config            |   2 +
 .../selftests/bpf/prog_tests/test_lsm.c       |  86 +++
 tools/testing/selftests/bpf/progs/lsm.c       |  48 ++
 31 files changed, 991 insertions(+), 670 deletions(-)
 create mode 100644 Documentation/bpf/bpf_lsm.rst
 create mode 100644 include/linux/bpf_lsm.h
 create mode 100644 include/linux/lsm_hook_defs.h
 create mode 100644 kernel/bpf/bpf_lsm.c
 create mode 100644 security/bpf/Makefile
 create mode 100644 security/bpf/hooks.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/test_lsm.c
 create mode 100644 tools/testing/selftests/bpf/progs/lsm.c

-- 
2.20.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH bpf-next v7 1/8] bpf: Introduce BPF_PROG_TYPE_LSM
  2020-03-26 14:28 [PATCH bpf-next v7 0/8] MAC and Audit policy using eBPF (KRSI) KP Singh
@ 2020-03-26 14:28 ` KP Singh
  2020-03-27  0:27   ` James Morris
  2020-03-26 14:28 ` [PATCH bpf-next v7 2/8] security: Refactor declaration of LSM hooks KP Singh
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 33+ messages in thread
From: KP Singh @ 2020-03-26 14:28 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Brendan Jackman, Florent Revest, Thomas Garnier, Yonghong Song,
	Andrii Nakryiko, Alexei Starovoitov, Daniel Borkmann,
	James Morris, Kees Cook, Paul Turner, Jann Horn, Florent Revest,
	Brendan Jackman, Greg Kroah-Hartman

From: KP Singh <kpsingh@google.com>

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 <kpsingh@google.com>
Reviewed-by: Brendan Jackman <jackmanb@google.com>
Reviewed-by: Florent Revest <revest@google.com>
Reviewed-by: Thomas Garnier <thgarnie@google.com>
Acked-by: Yonghong Song <yhs@fb.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
---
 MAINTAINERS                    |  1 +
 include/linux/bpf.h            |  3 +++
 include/linux/bpf_types.h      |  4 ++++
 include/uapi/linux/bpf.h       |  2 ++
 init/Kconfig                   | 12 ++++++++++++
 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, 49 insertions(+), 6 deletions(-)
 create mode 100644 kernel/bpf/bpf_lsm.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 5dbee41045bc..3197fe9256b2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3147,6 +3147,7 @@ R:	Martin KaFai Lau <kafai@fb.com>
 R:	Song Liu <songliubraving@fb.com>
 R:	Yonghong Song <yhs@fb.com>
 R:	Andrii Nakryiko <andriin@fb.com>
+R:	KP Singh <kpsingh@chromium.org>
 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 bdb981c204fa..af81ec7b783c 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1513,6 +1513,9 @@ extern const struct bpf_func_proto bpf_tcp_sock_proto;
 extern const struct bpf_func_proto bpf_jiffies64_proto;
 extern const struct bpf_func_proto bpf_get_ns_current_pid_tgid_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 5d01c5c7e598..9f2673c58788 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 {
@@ -211,6 +212,7 @@ enum bpf_attach_type {
 	BPF_TRACE_FENTRY,
 	BPF_TRACE_FEXIT,
 	BPF_MODIFY_RETURN,
+	BPF_LSM_MAC,
 	__MAX_BPF_ATTACH_TYPE
 };
 
diff --git a/init/Kconfig b/init/Kconfig
index 20a6ac33761c..deae572d1927 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1616,6 +1616,18 @@ 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
+	depends on SECURITY
+	depends on BPF_JIT
+	help
+	  Enables instrumentation of the security hooks with eBPF programs for
+	  implementing dynamic MAC and Audit Policies.
+
+	  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..82875039ca90
--- /dev/null
+++ b/kernel/bpf/bpf_lsm.c
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2020 Google LLC.
+ */
+
+#include <linux/filter.h>
+#include <linux/bpf.h>
+#include <linux/btf.h>
+
+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 e619eedb5919..37ffceab608f 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -779,8 +779,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);
 	}
 }
 
@@ -1082,7 +1082,7 @@ pe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 	case BPF_FUNC_read_branch_records:
 		return &bpf_read_branch_records_proto;
 	default:
-		return tracing_func_proto(func_id, prog);
+		return bpf_tracing_func_proto(func_id, prog);
 	}
 }
 
@@ -1210,7 +1210,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 5d01c5c7e598..9f2673c58788 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 {
@@ -211,6 +212,7 @@ enum bpf_attach_type {
 	BPF_TRACE_FENTRY,
 	BPF_TRACE_FEXIT,
 	BPF_MODIFY_RETURN,
+	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;
 	}
-- 
2.20.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH bpf-next v7 2/8] security: Refactor declaration of LSM hooks
  2020-03-26 14:28 [PATCH bpf-next v7 0/8] MAC and Audit policy using eBPF (KRSI) KP Singh
  2020-03-26 14:28 ` [PATCH bpf-next v7 1/8] bpf: Introduce BPF_PROG_TYPE_LSM KP Singh
@ 2020-03-26 14:28 ` KP Singh
  2020-03-27  0:28   ` James Morris
  2020-03-26 14:28 ` [PATCH bpf-next v7 3/8] bpf: lsm: provide attachment points for BPF LSM programs KP Singh
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 33+ messages in thread
From: KP Singh @ 2020-03-26 14:28 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Brendan Jackman, Florent Revest, Kees Cook, Casey Schaufler,
	Alexei Starovoitov, Daniel Borkmann, James Morris, Paul Turner,
	Jann Horn, Florent Revest, Brendan Jackman, Greg Kroah-Hartman

From: KP Singh <kpsingh@google.com>

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_defs.h which is then used to generate all
the data structures required by the LSM framework.

The LSM hooks are defined as:

  LSM_HOOK(<return_type>, <default_value>, <hook_name>, args...)

with <default_value> acccessible in security.c as:

  LSM_RET_DEFAULT(<hook_name>)

Signed-off-by: KP Singh <kpsingh@google.com>
Reviewed-by: Brendan Jackman <jackmanb@google.com>
Reviewed-by: Florent Revest <revest@google.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
---
 include/linux/lsm_hook_defs.h | 381 +++++++++++++++++++++
 include/linux/lsm_hooks.h     | 628 +---------------------------------
 security/security.c           |  41 ++-
 3 files changed, 423 insertions(+), 627 deletions(-)
 create mode 100644 include/linux/lsm_hook_defs.h

diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
new file mode 100644
index 000000000000..9cd4455528e5
--- /dev/null
+++ b/include/linux/lsm_hook_defs.h
@@ -0,0 +1,381 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Linux Security Module Hook declarations.
+ *
+ * Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com>
+ * Copyright (C) 2001 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com>
+ * Copyright (C) 2001 James Morris <jmorris@intercode.com.au>
+ * Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group)
+ * Copyright (C) 2015 Intel Corporation.
+ * Copyright (C) 2015 Casey Schaufler <casey@schaufler-ca.com>
+ * Copyright (C) 2016 Mellanox Techonologies
+ * Copyright (C) 2020 Google LLC.
+ */
+
+/*
+ * The macro LSM_HOOK is used to define the data structures required by the
+ * the LSM framework using the pattern:
+ *
+ *	LSM_HOOK(<return_type>, <default_value>, <hook_name>, args...)
+ *
+ * struct security_hook_heads {
+ *   #define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME;
+ *   #include <linux/lsm_hook_defs.h>
+ *   #undef LSM_HOOK
+ * };
+ */
+LSM_HOOK(int, 0, binder_set_context_mgr, struct task_struct *mgr)
+LSM_HOOK(int, 0, binder_transaction, struct task_struct *from,
+	 struct task_struct *to)
+LSM_HOOK(int, 0, binder_transfer_binder, struct task_struct *from,
+	 struct task_struct *to)
+LSM_HOOK(int, 0, binder_transfer_file, struct task_struct *from,
+	 struct task_struct *to, struct file *file)
+LSM_HOOK(int, 0, ptrace_access_check, struct task_struct *child,
+	 unsigned int mode)
+LSM_HOOK(int, 0, ptrace_traceme, struct task_struct *parent)
+LSM_HOOK(int, 0, capget, struct task_struct *target, kernel_cap_t *effective,
+	 kernel_cap_t *inheritable, kernel_cap_t *permitted)
+LSM_HOOK(int, 0, 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, 0, capable, const struct cred *cred, struct user_namespace *ns,
+	 int cap, unsigned int opts)
+LSM_HOOK(int, 0, quotactl, int cmds, int type, int id, struct super_block *sb)
+LSM_HOOK(int, 0, quota_on, struct dentry *dentry)
+LSM_HOOK(int, 0, syslog, int type)
+LSM_HOOK(int, 0, settime, const struct timespec64 *ts,
+	 const struct timezone *tz)
+LSM_HOOK(int, 0, vm_enough_memory, struct mm_struct *mm, long pages)
+LSM_HOOK(int, 0, bprm_set_creds, struct linux_binprm *bprm)
+LSM_HOOK(int, 0, bprm_check_security, struct linux_binprm *bprm)
+LSM_HOOK(void, LSM_RET_VOID, bprm_committing_creds, struct linux_binprm *bprm)
+LSM_HOOK(void, LSM_RET_VOID, bprm_committed_creds, struct linux_binprm *bprm)
+LSM_HOOK(int, 0, fs_context_dup, struct fs_context *fc,
+	 struct fs_context *src_sc)
+LSM_HOOK(int, 0, fs_context_parse_param, struct fs_context *fc,
+	 struct fs_parameter *param)
+LSM_HOOK(int, 0, sb_alloc_security, struct super_block *sb)
+LSM_HOOK(void, LSM_RET_VOID, sb_free_security, struct super_block *sb)
+LSM_HOOK(void, LSM_RET_VOID, sb_free_mnt_opts, void *mnt_opts)
+LSM_HOOK(int, 0, sb_eat_lsm_opts, char *orig, void **mnt_opts)
+LSM_HOOK(int, 0, sb_remount, struct super_block *sb, void *mnt_opts)
+LSM_HOOK(int, 0, sb_kern_mount, struct super_block *sb)
+LSM_HOOK(int, 0, sb_show_options, struct seq_file *m, struct super_block *sb)
+LSM_HOOK(int, 0, sb_statfs, struct dentry *dentry)
+LSM_HOOK(int, 0, sb_mount, const char *dev_name, const struct path *path,
+	 const char *type, unsigned long flags, void *data)
+LSM_HOOK(int, 0, sb_umount, struct vfsmount *mnt, int flags)
+LSM_HOOK(int, 0, sb_pivotroot, const struct path *old_path,
+	 const struct path *new_path)
+LSM_HOOK(int, 0, sb_set_mnt_opts, struct super_block *sb, void *mnt_opts,
+	 unsigned long kern_flags, unsigned long *set_kern_flags)
+LSM_HOOK(int, 0, 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, 0, sb_add_mnt_opt, const char *option, const char *val,
+	 int len, void **mnt_opts)
+LSM_HOOK(int, 0, move_mount, const struct path *from_path,
+	 const struct path *to_path)
+LSM_HOOK(int, 0, dentry_init_security, struct dentry *dentry,
+	 int mode, const struct qstr *name, void **ctx, u32 *ctxlen)
+LSM_HOOK(int, 0, 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, 0, path_unlink, const struct path *dir, struct dentry *dentry)
+LSM_HOOK(int, 0, path_mkdir, const struct path *dir, struct dentry *dentry,
+	 umode_t mode)
+LSM_HOOK(int, 0, path_rmdir, const struct path *dir, struct dentry *dentry)
+LSM_HOOK(int, 0, path_mknod, const struct path *dir, struct dentry *dentry,
+	 umode_t mode, unsigned int dev)
+LSM_HOOK(int, 0, path_truncate, const struct path *path)
+LSM_HOOK(int, 0, path_symlink, const struct path *dir, struct dentry *dentry,
+	 const char *old_name)
+LSM_HOOK(int, 0, path_link, struct dentry *old_dentry,
+	 const struct path *new_dir, struct dentry *new_dentry)
+LSM_HOOK(int, 0, path_rename, const struct path *old_dir,
+	 struct dentry *old_dentry, const struct path *new_dir,
+	 struct dentry *new_dentry)
+LSM_HOOK(int, 0, path_chmod, const struct path *path, umode_t mode)
+LSM_HOOK(int, 0, path_chown, const struct path *path, kuid_t uid, kgid_t gid)
+LSM_HOOK(int, 0, path_chroot, const struct path *path)
+#endif /* CONFIG_SECURITY_PATH */
+
+/* Needed for inode based security check */
+LSM_HOOK(int, 0, path_notify, const struct path *path, u64 mask,
+	 unsigned int obj_type)
+LSM_HOOK(int, 0, inode_alloc_security, struct inode *inode)
+LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode)
+LSM_HOOK(int, 0, inode_init_security, struct inode *inode,
+	 struct inode *dir, const struct qstr *qstr, const char **name,
+	 void **value, size_t *len)
+LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,
+	 umode_t mode)
+LSM_HOOK(int, 0, inode_link, struct dentry *old_dentry, struct inode *dir,
+	 struct dentry *new_dentry)
+LSM_HOOK(int, 0, inode_unlink, struct inode *dir, struct dentry *dentry)
+LSM_HOOK(int, 0, inode_symlink, struct inode *dir, struct dentry *dentry,
+	 const char *old_name)
+LSM_HOOK(int, 0, inode_mkdir, struct inode *dir, struct dentry *dentry,
+	 umode_t mode)
+LSM_HOOK(int, 0, inode_rmdir, struct inode *dir, struct dentry *dentry)
+LSM_HOOK(int, 0, inode_mknod, struct inode *dir, struct dentry *dentry,
+	 umode_t mode, dev_t dev)
+LSM_HOOK(int, 0, inode_rename, struct inode *old_dir, struct dentry *old_dentry,
+	 struct inode *new_dir, struct dentry *new_dentry)
+LSM_HOOK(int, 0, inode_readlink, struct dentry *dentry)
+LSM_HOOK(int, 0, inode_follow_link, struct dentry *dentry, struct inode *inode,
+	 bool rcu)
+LSM_HOOK(int, 0, inode_permission, struct inode *inode, int mask)
+LSM_HOOK(int, 0, inode_setattr, struct dentry *dentry, struct iattr *attr)
+LSM_HOOK(int, 0, inode_getattr, const struct path *path)
+LSM_HOOK(int, 0, inode_setxattr, struct dentry *dentry, const char *name,
+	 const void *value, size_t size, int flags)
+LSM_HOOK(void, LSM_RET_VOID, inode_post_setxattr, struct dentry *dentry,
+	 const char *name, const void *value, size_t size, int flags)
+LSM_HOOK(int, 0, inode_getxattr, struct dentry *dentry, const char *name)
+LSM_HOOK(int, 0, inode_listxattr, struct dentry *dentry)
+LSM_HOOK(int, 0, inode_removexattr, struct dentry *dentry, const char *name)
+LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry)
+LSM_HOOK(int, 0, inode_killpriv, struct dentry *dentry)
+LSM_HOOK(int, -EOPNOTSUPP, inode_getsecurity, struct inode *inode,
+	 const char *name, void **buffer, bool alloc)
+LSM_HOOK(int, -EOPNOTSUPP, inode_setsecurity, struct inode *inode,
+	 const char *name, const void *value, size_t size, int flags)
+LSM_HOOK(int, 0, inode_listsecurity, struct inode *inode, char *buffer,
+	 size_t buffer_size)
+LSM_HOOK(void, LSM_RET_VOID, inode_getsecid, struct inode *inode, u32 *secid)
+LSM_HOOK(int, 0, inode_copy_up, struct dentry *src, struct cred **new)
+LSM_HOOK(int, 0, inode_copy_up_xattr, const char *name)
+LSM_HOOK(int, 0, kernfs_init_security, struct kernfs_node *kn_dir,
+	 struct kernfs_node *kn)
+LSM_HOOK(int, 0, file_permission, struct file *file, int mask)
+LSM_HOOK(int, 0, file_alloc_security, struct file *file)
+LSM_HOOK(void, LSM_RET_VOID, file_free_security, struct file *file)
+LSM_HOOK(int, 0, file_ioctl, struct file *file, unsigned int cmd,
+	 unsigned long arg)
+LSM_HOOK(int, 0, mmap_addr, unsigned long addr)
+LSM_HOOK(int, 0, mmap_file, struct file *file, unsigned long reqprot,
+	 unsigned long prot, unsigned long flags)
+LSM_HOOK(int, 0, file_mprotect, struct vm_area_struct *vma,
+	 unsigned long reqprot, unsigned long prot)
+LSM_HOOK(int, 0, file_lock, struct file *file, unsigned int cmd)
+LSM_HOOK(int, 0, file_fcntl, struct file *file, unsigned int cmd,
+	 unsigned long arg)
+LSM_HOOK(void, LSM_RET_VOID, file_set_fowner, struct file *file)
+LSM_HOOK(int, 0, file_send_sigiotask, struct task_struct *tsk,
+	 struct fown_struct *fown, int sig)
+LSM_HOOK(int, 0, file_receive, struct file *file)
+LSM_HOOK(int, 0, file_open, struct file *file)
+LSM_HOOK(int, 0, task_alloc, struct task_struct *task,
+	 unsigned long clone_flags)
+LSM_HOOK(void, LSM_RET_VOID, task_free, struct task_struct *task)
+LSM_HOOK(int, 0, cred_alloc_blank, struct cred *cred, gfp_t gfp)
+LSM_HOOK(void, LSM_RET_VOID, cred_free, struct cred *cred)
+LSM_HOOK(int, 0, cred_prepare, struct cred *new, const struct cred *old,
+	 gfp_t gfp)
+LSM_HOOK(void, LSM_RET_VOID, cred_transfer, struct cred *new,
+	 const struct cred *old)
+LSM_HOOK(void, LSM_RET_VOID, cred_getsecid, const struct cred *c, u32 *secid)
+LSM_HOOK(int, 0, kernel_act_as, struct cred *new, u32 secid)
+LSM_HOOK(int, 0, kernel_create_files_as, struct cred *new, struct inode *inode)
+LSM_HOOK(int, 0, kernel_module_request, char *kmod_name)
+LSM_HOOK(int, 0, kernel_load_data, enum kernel_load_data_id id)
+LSM_HOOK(int, 0, kernel_read_file, struct file *file,
+	 enum kernel_read_file_id id)
+LSM_HOOK(int, 0, kernel_post_read_file, struct file *file, char *buf,
+	 loff_t size, enum kernel_read_file_id id)
+LSM_HOOK(int, 0, task_fix_setuid, struct cred *new, const struct cred *old,
+	 int flags)
+LSM_HOOK(int, 0, task_setpgid, struct task_struct *p, pid_t pgid)
+LSM_HOOK(int, 0, task_getpgid, struct task_struct *p)
+LSM_HOOK(int, 0, task_getsid, struct task_struct *p)
+LSM_HOOK(void, LSM_RET_VOID, task_getsecid, struct task_struct *p, u32 *secid)
+LSM_HOOK(int, 0, task_setnice, struct task_struct *p, int nice)
+LSM_HOOK(int, 0, task_setioprio, struct task_struct *p, int ioprio)
+LSM_HOOK(int, 0, task_getioprio, struct task_struct *p)
+LSM_HOOK(int, 0, task_prlimit, const struct cred *cred,
+	 const struct cred *tcred, unsigned int flags)
+LSM_HOOK(int, 0, task_setrlimit, struct task_struct *p, unsigned int resource,
+	 struct rlimit *new_rlim)
+LSM_HOOK(int, 0, task_setscheduler, struct task_struct *p)
+LSM_HOOK(int, 0, task_getscheduler, struct task_struct *p)
+LSM_HOOK(int, 0, task_movememory, struct task_struct *p)
+LSM_HOOK(int, 0, task_kill, struct task_struct *p, struct kernel_siginfo *info,
+	 int sig, const struct cred *cred)
+LSM_HOOK(int, -ENOSYS, task_prctl, int option, unsigned long arg2,
+	 unsigned long arg3, unsigned long arg4, unsigned long arg5)
+LSM_HOOK(void, LSM_RET_VOID, task_to_inode, struct task_struct *p,
+	 struct inode *inode)
+LSM_HOOK(int, 0, ipc_permission, struct kern_ipc_perm *ipcp, short flag)
+LSM_HOOK(void, LSM_RET_VOID, ipc_getsecid, struct kern_ipc_perm *ipcp,
+	 u32 *secid)
+LSM_HOOK(int, 0, msg_msg_alloc_security, struct msg_msg *msg)
+LSM_HOOK(void, LSM_RET_VOID, msg_msg_free_security, struct msg_msg *msg)
+LSM_HOOK(int, 0, msg_queue_alloc_security, struct kern_ipc_perm *perm)
+LSM_HOOK(void, LSM_RET_VOID, msg_queue_free_security,
+	 struct kern_ipc_perm *perm)
+LSM_HOOK(int, 0, msg_queue_associate, struct kern_ipc_perm *perm, int msqflg)
+LSM_HOOK(int, 0, msg_queue_msgctl, struct kern_ipc_perm *perm, int cmd)
+LSM_HOOK(int, 0, msg_queue_msgsnd, struct kern_ipc_perm *perm,
+	 struct msg_msg *msg, int msqflg)
+LSM_HOOK(int, 0, msg_queue_msgrcv, struct kern_ipc_perm *perm,
+	 struct msg_msg *msg, struct task_struct *target, long type, int mode)
+LSM_HOOK(int, 0, shm_alloc_security, struct kern_ipc_perm *perm)
+LSM_HOOK(void, LSM_RET_VOID, shm_free_security, struct kern_ipc_perm *perm)
+LSM_HOOK(int, 0, shm_associate, struct kern_ipc_perm *perm, int shmflg)
+LSM_HOOK(int, 0, shm_shmctl, struct kern_ipc_perm *perm, int cmd)
+LSM_HOOK(int, 0, shm_shmat, struct kern_ipc_perm *perm, char __user *shmaddr,
+	 int shmflg)
+LSM_HOOK(int, 0, sem_alloc_security, struct kern_ipc_perm *perm)
+LSM_HOOK(void, LSM_RET_VOID, sem_free_security, struct kern_ipc_perm *perm)
+LSM_HOOK(int, 0, sem_associate, struct kern_ipc_perm *perm, int semflg)
+LSM_HOOK(int, 0, sem_semctl, struct kern_ipc_perm *perm, int cmd)
+LSM_HOOK(int, 0, sem_semop, struct kern_ipc_perm *perm, struct sembuf *sops,
+	 unsigned nsops, int alter)
+LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb)
+LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry,
+	 struct inode *inode)
+LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, char *name,
+	 char **value)
+LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)
+LSM_HOOK(int, 0, ismaclabel, const char *name)
+LSM_HOOK(int, 0, secid_to_secctx, u32 secid, char **secdata,
+	 u32 *seclen)
+LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid)
+LSM_HOOK(void, LSM_RET_VOID, release_secctx, char *secdata, u32 seclen)
+LSM_HOOK(void, LSM_RET_VOID, inode_invalidate_secctx, struct inode *inode)
+LSM_HOOK(int, 0, inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen)
+LSM_HOOK(int, 0, inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen)
+LSM_HOOK(int, 0, inode_getsecctx, struct inode *inode, void **ctx,
+	 u32 *ctxlen)
+
+#ifdef CONFIG_SECURITY_NETWORK
+LSM_HOOK(int, 0, unix_stream_connect, struct sock *sock, struct sock *other,
+	 struct sock *newsk)
+LSM_HOOK(int, 0, unix_may_send, struct socket *sock, struct socket *other)
+LSM_HOOK(int, 0, socket_create, int family, int type, int protocol, int kern)
+LSM_HOOK(int, 0, socket_post_create, struct socket *sock, int family, int type,
+	 int protocol, int kern)
+LSM_HOOK(int, 0, socket_socketpair, struct socket *socka, struct socket *sockb)
+LSM_HOOK(int, 0, socket_bind, struct socket *sock, struct sockaddr *address,
+	 int addrlen)
+LSM_HOOK(int, 0, socket_connect, struct socket *sock, struct sockaddr *address,
+	 int addrlen)
+LSM_HOOK(int, 0, socket_listen, struct socket *sock, int backlog)
+LSM_HOOK(int, 0, socket_accept, struct socket *sock, struct socket *newsock)
+LSM_HOOK(int, 0, socket_sendmsg, struct socket *sock, struct msghdr *msg,
+	 int size)
+LSM_HOOK(int, 0, socket_recvmsg, struct socket *sock, struct msghdr *msg,
+	 int size, int flags)
+LSM_HOOK(int, 0, socket_getsockname, struct socket *sock)
+LSM_HOOK(int, 0, socket_getpeername, struct socket *sock)
+LSM_HOOK(int, 0, socket_getsockopt, struct socket *sock, int level, int optname)
+LSM_HOOK(int, 0, socket_setsockopt, struct socket *sock, int level, int optname)
+LSM_HOOK(int, 0, socket_shutdown, struct socket *sock, int how)
+LSM_HOOK(int, 0, socket_sock_rcv_skb, struct sock *sk, struct sk_buff *skb)
+LSM_HOOK(int, 0, socket_getpeersec_stream, struct socket *sock,
+	 char __user *optval, int __user *optlen, unsigned len)
+LSM_HOOK(int, 0, socket_getpeersec_dgram, struct socket *sock,
+	 struct sk_buff *skb, u32 *secid)
+LSM_HOOK(int, 0, sk_alloc_security, struct sock *sk, int family, gfp_t priority)
+LSM_HOOK(void, LSM_RET_VOID, sk_free_security, struct sock *sk)
+LSM_HOOK(void, LSM_RET_VOID, sk_clone_security, const struct sock *sk,
+	 struct sock *newsk)
+LSM_HOOK(void, LSM_RET_VOID, sk_getsecid, struct sock *sk, u32 *secid)
+LSM_HOOK(void, LSM_RET_VOID, sock_graft, struct sock *sk, struct socket *parent)
+LSM_HOOK(int, 0, inet_conn_request, struct sock *sk, struct sk_buff *skb,
+	 struct request_sock *req)
+LSM_HOOK(void, LSM_RET_VOID, inet_csk_clone, struct sock *newsk,
+	 const struct request_sock *req)
+LSM_HOOK(void, LSM_RET_VOID, inet_conn_established, struct sock *sk,
+	 struct sk_buff *skb)
+LSM_HOOK(int, 0, secmark_relabel_packet, u32 secid)
+LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_inc, void)
+LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_dec, void)
+LSM_HOOK(void, LSM_RET_VOID, req_classify_flow, const struct request_sock *req,
+	 struct flowi *fl)
+LSM_HOOK(int, 0, tun_dev_alloc_security, void **security)
+LSM_HOOK(void, LSM_RET_VOID, tun_dev_free_security, void *security)
+LSM_HOOK(int, 0, tun_dev_create, void)
+LSM_HOOK(int, 0, tun_dev_attach_queue, void *security)
+LSM_HOOK(int, 0, tun_dev_attach, struct sock *sk, void *security)
+LSM_HOOK(int, 0, tun_dev_open, void *security)
+LSM_HOOK(int, 0, sctp_assoc_request, struct sctp_endpoint *ep,
+	 struct sk_buff *skb)
+LSM_HOOK(int, 0, sctp_bind_connect, struct sock *sk, int optname,
+	 struct sockaddr *address, int addrlen)
+LSM_HOOK(void, LSM_RET_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, 0, ib_pkey_access, void *sec, u64 subnet_prefix, u16 pkey)
+LSM_HOOK(int, 0, ib_endport_manage_subnet, void *sec, const char *dev_name,
+	 u8 port_num)
+LSM_HOOK(int, 0, ib_alloc_security, void **sec)
+LSM_HOOK(void, LSM_RET_VOID, ib_free_security, void *sec)
+#endif /* CONFIG_SECURITY_INFINIBAND */
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+LSM_HOOK(int, 0, xfrm_policy_alloc_security, struct xfrm_sec_ctx **ctxp,
+	 struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp)
+LSM_HOOK(int, 0, xfrm_policy_clone_security, struct xfrm_sec_ctx *old_ctx,
+	 struct xfrm_sec_ctx **new_ctx)
+LSM_HOOK(void, LSM_RET_VOID, xfrm_policy_free_security,
+	 struct xfrm_sec_ctx *ctx)
+LSM_HOOK(int, 0, xfrm_policy_delete_security, struct xfrm_sec_ctx *ctx)
+LSM_HOOK(int, 0, xfrm_state_alloc, struct xfrm_state *x,
+	 struct xfrm_user_sec_ctx *sec_ctx)
+LSM_HOOK(int, 0, xfrm_state_alloc_acquire, struct xfrm_state *x,
+	 struct xfrm_sec_ctx *polsec, u32 secid)
+LSM_HOOK(void, LSM_RET_VOID, xfrm_state_free_security, struct xfrm_state *x)
+LSM_HOOK(int, 0, xfrm_state_delete_security, struct xfrm_state *x)
+LSM_HOOK(int, 0, xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid,
+	 u8 dir)
+LSM_HOOK(int, 1, xfrm_state_pol_flow_match, struct xfrm_state *x,
+	 struct xfrm_policy *xp, const struct flowi *fl)
+LSM_HOOK(int, 0, 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, 0, key_alloc, struct key *key, const struct cred *cred,
+	 unsigned long flags)
+LSM_HOOK(void, LSM_RET_VOID, key_free, struct key *key)
+LSM_HOOK(int, 0, key_permission, key_ref_t key_ref, const struct cred *cred,
+	 unsigned perm)
+LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **_buffer)
+#endif /* CONFIG_KEYS */
+
+#ifdef CONFIG_AUDIT
+LSM_HOOK(int, 0, audit_rule_init, u32 field, u32 op, char *rulestr,
+	 void **lsmrule)
+LSM_HOOK(int, 0, audit_rule_known, struct audit_krule *krule)
+LSM_HOOK(int, 0, audit_rule_match, u32 secid, u32 field, u32 op, void *lsmrule)
+LSM_HOOK(void, LSM_RET_VOID, audit_rule_free, void *lsmrule)
+#endif /* CONFIG_AUDIT */
+
+#ifdef CONFIG_BPF_SYSCALL
+LSM_HOOK(int, 0, bpf, int cmd, union bpf_attr *attr, unsigned int size)
+LSM_HOOK(int, 0, bpf_map, struct bpf_map *map, fmode_t fmode)
+LSM_HOOK(int, 0, bpf_prog, struct bpf_prog *prog)
+LSM_HOOK(int, 0, bpf_map_alloc_security, struct bpf_map *map)
+LSM_HOOK(void, LSM_RET_VOID, bpf_map_free_security, struct bpf_map *map)
+LSM_HOOK(int, 0, bpf_prog_alloc_security, struct bpf_prog_aux *aux)
+LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free_security, struct bpf_prog_aux *aux)
+#endif /* CONFIG_BPF_SYSCALL */
+
+LSM_HOOK(int, 0, locked_down, enum lockdown_reason what)
+
+#ifdef CONFIG_PERF_EVENTS
+LSM_HOOK(int, 0, perf_event_open, struct perf_event_attr *attr, int type)
+LSM_HOOK(int, 0, perf_event_alloc, struct perf_event *event)
+LSM_HOOK(void, LSM_RET_VOID, perf_event_free, struct perf_event *event)
+LSM_HOOK(int, 0, perf_event_read, struct perf_event *event)
+LSM_HOOK(int, 0, perf_event_write, struct perf_event *event)
+#endif /* CONFIG_PERF_EVENTS */
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 20d8cf194fb7..c09623b32489 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, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
+	#include "lsm_hook_defs.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, DEFAULT, NAME, ...) struct hlist_head NAME;
+	#include "lsm_hook_defs.h"
+	#undef LSM_HOOK
 } __randomize_layout;
 
 /*
@@ -2100,6 +1490,12 @@ struct lsm_blob_sizes {
 	int	lbs_task;
 };
 
+/*
+ * LSM_RET_VOID is used as the default value in LSM_HOOK definitions for void
+ * LSM hooks (in include/linux/lsm_hook_defs.h).
+ */
+#define LSM_RET_VOID ((void) 0)
+
 /*
  * Initializing a security_hook_list structure takes
  * up a lot of space in a source file. This macro takes
diff --git a/security/security.c b/security/security.c
index 565bc9b67276..7fed24b9d57e 100644
--- a/security/security.c
+++ b/security/security.c
@@ -668,6 +668,25 @@ static void __init lsm_early_task(struct task_struct *task)
 		panic("%s: Early task alloc failed.\n", __func__);
 }
 
+/*
+ * The default value of the LSM hook is defined in linux/lsm_hook_defs.h and
+ * can be accessed with:
+ *
+ *	LSM_RET_DEFAULT(<hook_name>)
+ *
+ * The macros below define static constants for the default value of each
+ * LSM hook.
+ */
+#define LSM_RET_DEFAULT(NAME) (NAME##_default)
+#define DECLARE_LSM_RET_DEFAULT_void(DEFAULT, NAME)
+#define DECLARE_LSM_RET_DEFAULT_int(DEFAULT, NAME) \
+	static const int LSM_RET_DEFAULT(NAME) = (DEFAULT);
+#define LSM_HOOK(RET, DEFAULT, NAME, ...) \
+	DECLARE_LSM_RET_DEFAULT_##RET(DEFAULT, NAME)
+
+#include <linux/lsm_hook_defs.h>
+#undef LSM_HOOK
+
 /*
  * Hook list operation macros.
  *
@@ -1338,16 +1357,16 @@ int security_inode_getsecurity(struct inode *inode, const char *name, void **buf
 	int rc;
 
 	if (unlikely(IS_PRIVATE(inode)))
-		return -EOPNOTSUPP;
+		return LSM_RET_DEFAULT(inode_getsecurity);
 	/*
 	 * Only one module will provide an attribute with a given name.
 	 */
 	hlist_for_each_entry(hp, &security_hook_heads.inode_getsecurity, list) {
 		rc = hp->hook.inode_getsecurity(inode, name, buffer, alloc);
-		if (rc != -EOPNOTSUPP)
+		if (rc != LSM_RET_DEFAULT(inode_getsecurity))
 			return rc;
 	}
-	return -EOPNOTSUPP;
+	return LSM_RET_DEFAULT(inode_getsecurity);
 }
 
 int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
@@ -1356,17 +1375,17 @@ int security_inode_setsecurity(struct inode *inode, const char *name, const void
 	int rc;
 
 	if (unlikely(IS_PRIVATE(inode)))
-		return -EOPNOTSUPP;
+		return LSM_RET_DEFAULT(inode_setsecurity);
 	/*
 	 * Only one module will provide an attribute with a given name.
 	 */
 	hlist_for_each_entry(hp, &security_hook_heads.inode_setsecurity, list) {
 		rc = hp->hook.inode_setsecurity(inode, name, value, size,
 								flags);
-		if (rc != -EOPNOTSUPP)
+		if (rc != LSM_RET_DEFAULT(inode_setsecurity))
 			return rc;
 	}
-	return -EOPNOTSUPP;
+	return LSM_RET_DEFAULT(inode_setsecurity);
 }
 
 int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
@@ -1740,12 +1759,12 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
 			 unsigned long arg4, unsigned long arg5)
 {
 	int thisrc;
-	int rc = -ENOSYS;
+	int rc = LSM_RET_DEFAULT(task_prctl);
 	struct security_hook_list *hp;
 
 	hlist_for_each_entry(hp, &security_hook_heads.task_prctl, list) {
 		thisrc = hp->hook.task_prctl(option, arg2, arg3, arg4, arg5);
-		if (thisrc != -ENOSYS) {
+		if (thisrc != LSM_RET_DEFAULT(task_prctl)) {
 			rc = thisrc;
 			if (thisrc != 0)
 				break;
@@ -1917,7 +1936,7 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
 			continue;
 		return hp->hook.getprocattr(p, name, value);
 	}
-	return -EINVAL;
+	return LSM_RET_DEFAULT(getprocattr);
 }
 
 int security_setprocattr(const char *lsm, const char *name, void *value,
@@ -1930,7 +1949,7 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
 			continue;
 		return hp->hook.setprocattr(name, value, size);
 	}
-	return -EINVAL;
+	return LSM_RET_DEFAULT(setprocattr);
 }
 
 int security_netlink_send(struct sock *sk, struct sk_buff *skb)
@@ -2315,7 +2334,7 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
 				       const struct flowi *fl)
 {
 	struct security_hook_list *hp;
-	int rc = 1;
+	int rc = LSM_RET_DEFAULT(xfrm_state_pol_flow_match);
 
 	/*
 	 * Since this function is expected to return 0 or 1, the judgment
-- 
2.20.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH bpf-next v7 3/8] bpf: lsm: provide attachment points for BPF LSM programs
  2020-03-26 14:28 [PATCH bpf-next v7 0/8] MAC and Audit policy using eBPF (KRSI) KP Singh
  2020-03-26 14:28 ` [PATCH bpf-next v7 1/8] bpf: Introduce BPF_PROG_TYPE_LSM KP Singh
  2020-03-26 14:28 ` [PATCH bpf-next v7 2/8] security: Refactor declaration of LSM hooks KP Singh
@ 2020-03-26 14:28 ` KP Singh
  2020-03-27  0:29   ` James Morris
  2020-03-26 14:28 ` [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution KP Singh
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 33+ messages in thread
From: KP Singh @ 2020-03-26 14:28 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Brendan Jackman, Florent Revest, Kees Cook, Yonghong Song,
	Alexei Starovoitov, Daniel Borkmann, James Morris, Paul Turner,
	Jann Horn, Florent Revest, Brendan Jackman, Greg Kroah-Hartman

From: KP Singh <kpsingh@google.com>

When CONFIG_BPF_LSM is enabled, nop functions, bpf_lsm_<hook_name>, are
generated for each LSM hook. These functions are initialized as LSM
hooks in a subsequent patch.

Signed-off-by: KP Singh <kpsingh@google.com>
Reviewed-by: Brendan Jackman <jackmanb@google.com>
Reviewed-by: Florent Revest <revest@google.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Acked-by: Yonghong Song <yhs@fb.com>
---
 include/linux/bpf_lsm.h | 22 ++++++++++++++++++++++
 kernel/bpf/bpf_lsm.c    | 14 ++++++++++++++
 2 files changed, 36 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..83b96895829f
--- /dev/null
+++ b/include/linux/bpf_lsm.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Copyright (C) 2020 Google LLC.
+ */
+
+#ifndef _LINUX_BPF_LSM_H
+#define _LINUX_BPF_LSM_H
+
+#include <linux/bpf.h>
+#include <linux/lsm_hooks.h>
+
+#ifdef CONFIG_BPF_LSM
+
+#define LSM_HOOK(RET, DEFAULT, NAME, ...) \
+	RET bpf_lsm_##NAME(__VA_ARGS__);
+#include <linux/lsm_hook_defs.h>
+#undef LSM_HOOK
+
+#endif /* CONFIG_BPF_LSM */
+
+#endif /* _LINUX_BPF_LSM_H */
diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c
index 82875039ca90..e43e29690f22 100644
--- a/kernel/bpf/bpf_lsm.c
+++ b/kernel/bpf/bpf_lsm.c
@@ -7,6 +7,20 @@
 #include <linux/filter.h>
 #include <linux/bpf.h>
 #include <linux/btf.h>
+#include <linux/lsm_hooks.h>
+#include <linux/bpf_lsm.h>
+
+/* For every LSM hook that allows attachment of BPF programs, declare a nop
+ * function where a BPF program can be attached.
+ */
+#define LSM_HOOK(RET, DEFAULT, NAME, ...) 	\
+noinline RET bpf_lsm_##NAME(__VA_ARGS__)	\
+{						\
+	return DEFAULT;				\
+}
+
+#include <linux/lsm_hook_defs.h>
+#undef LSM_HOOK
 
 const struct bpf_prog_ops lsm_prog_ops = {
 };
-- 
2.20.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-26 14:28 [PATCH bpf-next v7 0/8] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (2 preceding siblings ...)
  2020-03-26 14:28 ` [PATCH bpf-next v7 3/8] bpf: lsm: provide attachment points for BPF LSM programs KP Singh
@ 2020-03-26 14:28 ` KP Singh
  2020-03-26 19:12   ` Andrii Nakryiko
                     ` (2 more replies)
  2020-03-26 14:28 ` [PATCH bpf-next v7 5/8] bpf: lsm: Initialize the BPF LSM hooks KP Singh
                   ` (3 subsequent siblings)
  7 siblings, 3 replies; 33+ messages in thread
From: KP Singh @ 2020-03-26 14:28 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Brendan Jackman, Florent Revest, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman

From: KP Singh <kpsingh@google.com>

JITed BPF programs are dynamically attached to the LSM hooks
using BPF trampolines. The trampoline prologue generates code to handle
conversion of the signature of the hook to the appropriate BPF context.

The allocated trampoline programs are attached to the nop functions
initialized as LSM hooks.

BPF_PROG_TYPE_LSM programs must have a GPL compatible license and
and need CAP_SYS_ADMIN (required for loading eBPF programs).

Upon attachment:

* A BPF fexit trampoline is used for LSM hooks with a void return type.
* A BPF fmod_ret trampoline is used for LSM hooks which return an
  int. The attached programs can override the return value of the
  bpf LSM hook to indicate a MAC Policy decision.

Signed-off-by: KP Singh <kpsingh@google.com>
Reviewed-by: Brendan Jackman <jackmanb@google.com>
Reviewed-by: Florent Revest <revest@google.com>
---
 include/linux/bpf_lsm.h | 11 ++++++++
 kernel/bpf/bpf_lsm.c    | 28 ++++++++++++++++++++
 kernel/bpf/btf.c        |  9 ++++++-
 kernel/bpf/syscall.c    | 57 ++++++++++++++++++++++++++++-------------
 kernel/bpf/trampoline.c | 17 +++++++++---
 kernel/bpf/verifier.c   | 19 +++++++++++---
 6 files changed, 114 insertions(+), 27 deletions(-)

diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h
index 83b96895829f..af74712af585 100644
--- a/include/linux/bpf_lsm.h
+++ b/include/linux/bpf_lsm.h
@@ -17,6 +17,17 @@
 #include <linux/lsm_hook_defs.h>
 #undef LSM_HOOK
 
+int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog,
+			const struct bpf_prog *prog);
+
+#else /* !CONFIG_BPF_LSM */
+
+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 e43e29690f22..e6160f0df3f1 100644
--- a/kernel/bpf/bpf_lsm.c
+++ b/kernel/bpf/bpf_lsm.c
@@ -9,6 +9,8 @@
 #include <linux/btf.h>
 #include <linux/lsm_hooks.h>
 #include <linux/bpf_lsm.h>
+#include <linux/kallsyms.h>
+#include <linux/bpf_verifier.h>
 
 /* For every LSM hook that allows attachment of BPF programs, declare a nop
  * function where a BPF program can be attached.
@@ -22,6 +24,32 @@ noinline RET bpf_lsm_##NAME(__VA_ARGS__)	\
 #include <linux/lsm_hook_defs.h>
 #undef LSM_HOOK
 
+#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,
+		    sizeof(BPF_LSM_SYM_PREFX) - 1)) {
+		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 6f397c4da05e..67466dd59a35 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -3710,7 +3710,14 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
 	}
 
 	if (arg == nr_args) {
-		if (prog->expected_attach_type == BPF_TRACE_FEXIT) {
+		/* BPF_LSM_MAC programs only have int and void functions they
+		 * can be attached to. When they are attached to a void function
+		 * they result in the creation of an FEXIT trampoline and when
+		 * to a function that returns an int, a MODIFY_RETURN
+		 * trampoline.
+		 */
+		if (prog->expected_attach_type == BPF_TRACE_FEXIT ||
+		    prog->expected_attach_type == BPF_LSM_MAC) {
 			if (!t)
 				return true;
 			t = btf_type_by_id(btf, t->type);
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 85567a6ea5f9..cea69244c713 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -25,6 +25,7 @@
 #include <linux/nospec.h>
 #include <linux/audit.h>
 #include <uapi/linux/btf.h>
+#include <linux/bpf_lsm.h>
 
 #define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
 			  (map)->map_type == BPF_MAP_TYPE_CGROUP_ARRAY || \
@@ -1935,6 +1936,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;
@@ -2367,10 +2369,28 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog)
 	struct file *link_file;
 	int link_fd, err;
 
-	if (prog->expected_attach_type != BPF_TRACE_FENTRY &&
-	    prog->expected_attach_type != BPF_TRACE_FEXIT &&
-	    prog->expected_attach_type != BPF_MODIFY_RETURN &&
-	    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->expected_attach_type != BPF_MODIFY_RETURN) {
+			err = -EINVAL;
+			goto out_put_prog;
+		}
+		break;
+	case BPF_PROG_TYPE_EXT:
+		if (prog->expected_attach_type != 0) {
+			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;
+		}
+		break;
+	default:
 		err = -EINVAL;
 		goto out_put_prog;
 	}
@@ -2449,16 +2469,10 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
 	if (IS_ERR(prog))
 		return PTR_ERR(prog);
 
-	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_RAW_TRACEPOINT_WRITABLE) {
-		err = -EINVAL;
-		goto out_put_prog;
-	}
-
-	if (prog->type == BPF_PROG_TYPE_TRACING ||
-	    prog->type == BPF_PROG_TYPE_EXT) {
+	switch (prog->type) {
+	case BPF_PROG_TYPE_TRACING:
+	case BPF_PROG_TYPE_EXT:
+	case BPF_PROG_TYPE_LSM:
 		if (attr->raw_tracepoint.name) {
 			/* The attach point for this category of programs
 			 * should be specified via btf_id during program load.
@@ -2466,11 +2480,14 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
 			err = -EINVAL;
 			goto out_put_prog;
 		}
-		if (prog->expected_attach_type == BPF_TRACE_RAW_TP)
+		if (prog->type == BPF_PROG_TYPE_TRACING &&
+		    prog->expected_attach_type == BPF_TRACE_RAW_TP) {
 			tp_name = prog->aux->attach_func_name;
-		else
-			return bpf_tracing_prog_attach(prog);
-	} else {
+			break;
+		}
+		return bpf_tracing_prog_attach(prog);
+	case BPF_PROG_TYPE_RAW_TRACEPOINT:
+	case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
 		if (strncpy_from_user(buf,
 				      u64_to_user_ptr(attr->raw_tracepoint.name),
 				      sizeof(buf) - 1) < 0) {
@@ -2479,6 +2496,10 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
 		}
 		buf[sizeof(buf) - 1] = 0;
 		tp_name = buf;
+		break;
+	default:
+			err = -EINVAL;
+			goto out_put_prog;
 	}
 
 	btp = bpf_get_raw_tracepoint(tp_name);
diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index f30bca2a4d01..9be85aa4ec5f 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -6,6 +6,7 @@
 #include <linux/ftrace.h>
 #include <linux/rbtree_latch.h>
 #include <linux/perf_event.h>
+#include <linux/btf.h>
 
 /* dummy _ops. The verifier will operate on target program's ops. */
 const struct bpf_verifier_ops bpf_extension_verifier_ops = {
@@ -233,15 +234,23 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr)
 	return err;
 }
 
-static enum bpf_tramp_prog_type bpf_attach_type_to_tramp(enum bpf_attach_type t)
+static enum bpf_tramp_prog_type bpf_attach_type_to_tramp(struct bpf_prog *prog)
 {
-	switch (t) {
+	switch (prog->expected_attach_type) {
 	case BPF_TRACE_FENTRY:
 		return BPF_TRAMP_FENTRY;
 	case BPF_MODIFY_RETURN:
 		return BPF_TRAMP_MODIFY_RETURN;
 	case BPF_TRACE_FEXIT:
 		return BPF_TRAMP_FEXIT;
+	case BPF_LSM_MAC:
+		if (!prog->aux->attach_func_proto->type)
+			/* The function returns void, we cannot modify its
+			 * return value.
+			 */
+			return BPF_TRAMP_FEXIT;
+		else
+			return BPF_TRAMP_MODIFY_RETURN;
 	default:
 		return BPF_TRAMP_REPLACE;
 	}
@@ -255,7 +264,7 @@ int bpf_trampoline_link_prog(struct bpf_prog *prog)
 	int cnt;
 
 	tr = prog->aux->trampoline;
-	kind = bpf_attach_type_to_tramp(prog->expected_attach_type);
+	kind = bpf_attach_type_to_tramp(prog);
 	mutex_lock(&tr->mutex);
 	if (tr->extension_prog) {
 		/* cannot attach fentry/fexit if extension prog is attached.
@@ -305,7 +314,7 @@ int bpf_trampoline_unlink_prog(struct bpf_prog *prog)
 	int err;
 
 	tr = prog->aux->trampoline;
-	kind = bpf_attach_type_to_tramp(prog->expected_attach_type);
+	kind = bpf_attach_type_to_tramp(prog);
 	mutex_lock(&tr->mutex);
 	if (kind == BPF_TRAMP_REPLACE) {
 		WARN_ON_ONCE(!tr->extension_prog);
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 2ea2a868324e..8808c06f2571 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -20,6 +20,7 @@
 #include <linux/perf_event.h>
 #include <linux/ctype.h>
 #include <linux/error-injection.h>
+#include <linux/bpf_lsm.h>
 
 #include "disasm.h"
 
@@ -6488,8 +6489,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;
 
@@ -9919,7 +9921,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) {
@@ -10050,8 +10054,16 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
 			return -EINVAL;
 		/* fallthrough */
 	case BPF_MODIFY_RETURN:
+	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);
@@ -10066,7 +10078,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);
-- 
2.20.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH bpf-next v7 5/8] bpf: lsm: Initialize the BPF LSM hooks
  2020-03-26 14:28 [PATCH bpf-next v7 0/8] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (3 preceding siblings ...)
  2020-03-26 14:28 ` [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution KP Singh
@ 2020-03-26 14:28 ` KP Singh
  2020-03-27  0:29   ` James Morris
  2020-03-26 14:28 ` [PATCH bpf-next v7 6/8] tools/libbpf: Add support for BPF_PROG_TYPE_LSM KP Singh
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 33+ messages in thread
From: KP Singh @ 2020-03-26 14:28 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Kees Cook, Brendan Jackman, Florent Revest, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman

From: KP Singh <kpsingh@google.com>

* The hooks are initialized using the definitions in
  include/linux/lsm_hook_defs.h.
* The LSM can be enabled / disabled with CONFIG_BPF_LSM.

Signed-off-by: KP Singh <kpsingh@google.com>
Acked-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Brendan Jackman <jackmanb@google.com>
Reviewed-by: Florent Revest <revest@google.com>
---
 security/Kconfig      | 10 +++++-----
 security/Makefile     |  2 ++
 security/bpf/Makefile |  5 +++++
 security/bpf/hooks.c  | 26 ++++++++++++++++++++++++++
 4 files changed, 38 insertions(+), 5 deletions(-)
 create mode 100644 security/bpf/Makefile
 create mode 100644 security/bpf/hooks.c

diff --git a/security/Kconfig b/security/Kconfig
index 2a1a2d396228..cd3cc7da3a55 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -277,11 +277,11 @@ endchoice
 
 config LSM
 	string "Ordered list of enabled LSMs"
-	default "lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor" if DEFAULT_SECURITY_SMACK
-	default "lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo" if DEFAULT_SECURITY_APPARMOR
-	default "lockdown,yama,loadpin,safesetid,integrity,tomoyo" if DEFAULT_SECURITY_TOMOYO
-	default "lockdown,yama,loadpin,safesetid,integrity" if DEFAULT_SECURITY_DAC
-	default "lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"
+	default "lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK
+	default "lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR
+	default "lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO
+	default "lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC
+	default "lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf"
 	help
 	  A comma-separated list of LSMs, in initialization order.
 	  Any LSMs left off this list will be ignored. This can be
diff --git a/security/Makefile b/security/Makefile
index 746438499029..22e73a3482bd 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -12,6 +12,7 @@ subdir-$(CONFIG_SECURITY_YAMA)		+= yama
 subdir-$(CONFIG_SECURITY_LOADPIN)	+= loadpin
 subdir-$(CONFIG_SECURITY_SAFESETID)    += safesetid
 subdir-$(CONFIG_SECURITY_LOCKDOWN_LSM)	+= lockdown
+subdir-$(CONFIG_BPF_LSM)		+= bpf
 
 # always enable default capabilities
 obj-y					+= commoncap.o
@@ -30,6 +31,7 @@ obj-$(CONFIG_SECURITY_LOADPIN)		+= loadpin/
 obj-$(CONFIG_SECURITY_SAFESETID)       += safesetid/
 obj-$(CONFIG_SECURITY_LOCKDOWN_LSM)	+= lockdown/
 obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o
+obj-$(CONFIG_BPF_LSM)			+= bpf/
 
 # Object integrity file lists
 subdir-$(CONFIG_INTEGRITY)		+= integrity
diff --git a/security/bpf/Makefile b/security/bpf/Makefile
new file mode 100644
index 000000000000..c7a89a962084
--- /dev/null
+++ b/security/bpf/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2020 Google LLC.
+
+obj-$(CONFIG_BPF_LSM) := hooks.o
diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c
new file mode 100644
index 000000000000..32d32d485451
--- /dev/null
+++ b/security/bpf/hooks.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2020 Google LLC.
+ */
+#include <linux/lsm_hooks.h>
+#include <linux/bpf_lsm.h>
+
+static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = {
+	#define LSM_HOOK(RET, DEFAULT, NAME, ...) \
+	LSM_HOOK_INIT(NAME, bpf_lsm_##NAME),
+	#include <linux/lsm_hook_defs.h>
+	#undef LSM_HOOK
+};
+
+static int __init bpf_lsm_init(void)
+{
+	security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks), "bpf");
+	pr_info("LSM support for eBPF active\n");
+	return 0;
+}
+
+DEFINE_LSM(bpf) = {
+	.name = "bpf",
+	.init = bpf_lsm_init,
+};
-- 
2.20.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH bpf-next v7 6/8] tools/libbpf: Add support for BPF_PROG_TYPE_LSM
  2020-03-26 14:28 [PATCH bpf-next v7 0/8] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (4 preceding siblings ...)
  2020-03-26 14:28 ` [PATCH bpf-next v7 5/8] bpf: lsm: Initialize the BPF LSM hooks KP Singh
@ 2020-03-26 14:28 ` KP Singh
  2020-03-27  0:30   ` James Morris
  2020-03-26 14:28 ` [PATCH bpf-next v7 7/8] bpf: lsm: Add selftests " KP Singh
  2020-03-26 14:28 ` [PATCH bpf-next v7 8/8] bpf: lsm: Add Documentation KP Singh
  7 siblings, 1 reply; 33+ messages in thread
From: KP Singh @ 2020-03-26 14:28 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Brendan Jackman, Florent Revest, Yonghong Song, Andrii Nakryiko,
	Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Paul Turner, Jann Horn, Florent Revest, Brendan Jackman,
	Greg Kroah-Hartman

From: KP Singh <kpsingh@google.com>

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_id.

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 <kpsingh@google.com>
Reviewed-by: Brendan Jackman <jackmanb@google.com>
Reviewed-by: Florent Revest <revest@google.com>
Acked-by: Yonghong Song <yhs@fb.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
---
 tools/lib/bpf/bpf.c      |  3 ++-
 tools/lib/bpf/libbpf.c   | 39 +++++++++++++++++++++++++++++++++++----
 tools/lib/bpf/libbpf.h   |  4 ++++
 tools/lib/bpf/libbpf.map |  3 +++
 4 files changed, 44 insertions(+), 5 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 62903302935e..4059717a6470 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -2358,7 +2358,8 @@ 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
@@ -4866,7 +4867,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) {
@@ -4957,6 +4959,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) && !prog->attach_btf_id) {
 		btf_id = libbpf_find_attach_btf_id(prog);
 		if (btf_id <= 0)
@@ -6196,6 +6199,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);
@@ -6262,6 +6266,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;
@@ -6312,6 +6318,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),
@@ -6574,6 +6584,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,
@@ -6601,6 +6612,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);
 
@@ -7454,7 +7468,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_id(struct bpf_program *prog)
 {
 	char errmsg[STRERR_BUFSIZE];
 	struct bpf_link *link;
@@ -7476,7 +7491,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: %s\n",
 			bpf_program__title(prog, false),
 			libbpf_strerror_r(pfd, errmsg, sizeof(errmsg)));
 		return ERR_PTR(pfd);
@@ -7485,12 +7500,28 @@ 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_id(prog);
+}
+
+struct bpf_link *bpf_program__attach_lsm(struct bpf_program *prog)
+{
+	return bpf_program__attach_btf_id(prog);
+}
+
 static struct bpf_link *attach_trace(const struct bpf_sec_def *sec,
 				     struct bpf_program *prog)
 {
 	return bpf_program__attach_trace(prog);
 }
 
+static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec,
+				   struct bpf_program *prog)
+{
+	return bpf_program__attach_lsm(prog);
+}
+
 struct bpf_link *bpf_program__attach(struct bpf_program *prog)
 {
 	const struct bpf_sec_def *sec_def;
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index d38d7a629417..df1be44c8118 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -248,6 +248,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;
@@ -321,6 +323,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);
@@ -347,6 +350,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 5129283c0284..ec29d3aa2700 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -243,5 +243,8 @@ LIBBPF_0.0.8 {
 		bpf_link__pin;
 		bpf_link__pin_path;
 		bpf_link__unpin;
+		bpf_program__attach_lsm;
+		bpf_program__is_lsm;
 		bpf_program__set_attach_target;
+		bpf_program__set_lsm;
 } LIBBPF_0.0.7;
-- 
2.20.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH bpf-next v7 7/8] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
  2020-03-26 14:28 [PATCH bpf-next v7 0/8] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (5 preceding siblings ...)
  2020-03-26 14:28 ` [PATCH bpf-next v7 6/8] tools/libbpf: Add support for BPF_PROG_TYPE_LSM KP Singh
@ 2020-03-26 14:28 ` " KP Singh
  2020-03-26 19:24   ` Andrii Nakryiko
  2020-03-27  0:31   ` James Morris
  2020-03-26 14:28 ` [PATCH bpf-next v7 8/8] bpf: lsm: Add Documentation KP Singh
  7 siblings, 2 replies; 33+ messages in thread
From: KP Singh @ 2020-03-26 14:28 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Brendan Jackman, Florent Revest, Thomas Garnier,
	Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Paul Turner, Jann Horn, Florent Revest, Brendan Jackman,
	Greg Kroah-Hartman

From: KP Singh <kpsingh@google.com>

* Load/attach a BPF program that hooks to file_mprotect (int)
  and bprm_committed_creds (void).
* Perform an action that triggers the hook.
* Verify if the audit event was received using the shared global
  variables for the process executed.
* Verify if the mprotect returns a -EPERM.

Signed-off-by: KP Singh <kpsingh@google.com>
Reviewed-by: Brendan Jackman <jackmanb@google.com>
Reviewed-by: Florent Revest <revest@google.com>
Reviewed-by: Thomas Garnier <thgarnie@google.com>
---
 tools/testing/selftests/bpf/config            |  2 +
 .../selftests/bpf/prog_tests/test_lsm.c       | 86 +++++++++++++++++++
 tools/testing/selftests/bpf/progs/lsm.c       | 48 +++++++++++
 3 files changed, 136 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/test_lsm.c
 create mode 100644 tools/testing/selftests/bpf/progs/lsm.c

diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
index 5dc109f4c097..60e3ae5d4e48 100644
--- a/tools/testing/selftests/bpf/config
+++ b/tools/testing/selftests/bpf/config
@@ -35,3 +35,5 @@ CONFIG_MPLS_ROUTING=m
 CONFIG_MPLS_IPTUNNEL=m
 CONFIG_IPV6_SIT=m
 CONFIG_BPF_JIT=y
+CONFIG_BPF_LSM=y
+CONFIG_SECURITY=y
diff --git a/tools/testing/selftests/bpf/prog_tests/test_lsm.c b/tools/testing/selftests/bpf/prog_tests/test_lsm.c
new file mode 100644
index 000000000000..6eb7060e4422
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/test_lsm.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2020 Google LLC.
+ */
+
+#include <test_progs.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdlib.h>
+
+#include "lsm.skel.h"
+
+char *CMD_ARGS[] = {"true", NULL};
+
+int heap_mprotect(void)
+{
+	void *buf;
+	long sz;
+	int ret;
+
+	sz = sysconf(_SC_PAGESIZE);
+	if (sz < 0)
+		return sz;
+
+	buf = memalign(sz, 2 * sz);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	ret = mprotect(buf, sz, PROT_READ | PROT_EXEC);
+	free(buf);
+	return ret;
+}
+
+int exec_cmd(int *monitored_pid)
+{
+	int child_pid, child_status;
+
+	child_pid = fork();
+	if (child_pid == 0) {
+		*monitored_pid = getpid();
+		execvp(CMD_ARGS[0], CMD_ARGS);
+		return -EINVAL;
+	} else if (child_pid > 0) {
+		waitpid(child_pid, &child_status, 0);
+		return child_status;
+	}
+
+	return -EINVAL;
+}
+
+void test_test_lsm(void)
+{
+	struct lsm *skel = NULL;
+	int err, duration = 0;
+
+	skel = lsm__open_and_load();
+	if (CHECK(!skel, "skel_load", "lsm skeleton failed\n"))
+		goto close_prog;
+
+	err = lsm__attach(skel);
+	if (CHECK(err, "attach", "lsm attach failed: %d\n", err))
+		goto close_prog;
+
+	err = exec_cmd(&skel->bss->monitored_pid);
+	if (CHECK(err < 0, "exec_cmd", "err %d errno %d\n", err, errno))
+		goto close_prog;
+
+	CHECK(skel->bss->bprm_count != 1, "bprm_count", "bprm_count = %d",
+	      skel->bss->bprm_count);
+
+	skel->bss->monitored_pid = getpid();
+
+	err = heap_mprotect();
+	if (CHECK(errno != EPERM, "heap_mprotect", "want errno=EPERM, got %d\n",
+		  errno))
+		goto close_prog;
+
+	CHECK(skel->bss->mprotect_count != 1, "mprotect_count",
+	      "mprotect_count = %d", skel->bss->mprotect_count);
+
+close_prog:
+	lsm__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/lsm.c b/tools/testing/selftests/bpf/progs/lsm.c
new file mode 100644
index 000000000000..a4e3c223028d
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/lsm.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2020 Google LLC.
+ */
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include  <errno.h>
+
+char _license[] SEC("license") = "GPL";
+
+int monitored_pid = 0;
+int mprotect_count = 0;
+int bprm_count = 0;
+
+SEC("lsm/file_mprotect")
+int BPF_PROG(test_int_hook, 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() >> 32;
+	int is_heap = 0;
+
+	is_heap = (vma->vm_start >= vma->vm_mm->start_brk &&
+		   vma->vm_end <= vma->vm_mm->brk);
+
+	if (is_heap && monitored_pid == pid) {
+		mprotect_count++;
+		ret = -EPERM;
+	}
+
+	return ret;
+}
+
+SEC("lsm/bprm_committed_creds")
+int BPF_PROG(test_void_hook, struct linux_binprm *bprm)
+{
+	__u32 pid = bpf_get_current_pid_tgid() >> 32;
+
+	if (monitored_pid == pid)
+		bprm_count++;
+
+	return 0;
+}
-- 
2.20.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH bpf-next v7 8/8] bpf: lsm: Add Documentation
  2020-03-26 14:28 [PATCH bpf-next v7 0/8] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (6 preceding siblings ...)
  2020-03-26 14:28 ` [PATCH bpf-next v7 7/8] bpf: lsm: Add selftests " KP Singh
@ 2020-03-26 14:28 ` KP Singh
  2020-03-26 19:31   ` Andrii Nakryiko
  2020-03-27  0:33   ` James Morris
  7 siblings, 2 replies; 33+ messages in thread
From: KP Singh @ 2020-03-26 14:28 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Brendan Jackman, Florent Revest, Thomas Garnier,
	Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Paul Turner, Jann Horn, Florent Revest, Brendan Jackman,
	Greg Kroah-Hartman

From: KP Singh <kpsingh@google.com>

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 <kpsingh@google.com>
Reviewed-by: Brendan Jackman <jackmanb@google.com>
Reviewed-by: Florent Revest <revest@google.com>
Reviewed-by: Thomas Garnier <thgarnie@google.com>
---
 Documentation/bpf/bpf_lsm.rst | 150 ++++++++++++++++++++++++++++++++++
 Documentation/bpf/index.rst   |   1 +
 2 files changed, 151 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..2a2c3b4a74d4
--- /dev/null
+++ b/Documentation/bpf/bpf_lsm.rst
@@ -0,0 +1,150 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright (C) 2020 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);
+
+Other LSM hooks which can be instrumented can be found in
+``include/linux/lsm_hooks.h``.
+
+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 <path-to-btf-vmlinux> 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/lib/bpf/bpf_tracing.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
+-------
+
+eBPF 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
+--------
+
+An example eBPF programs can be found in
+`tools/testing/selftests/bpf/progs/lsm.c`_ and the corresponding
+userspace code in `tools/testing/selftests/bpf/prog_tests/test_lsm.c`_
+
+.. Links
+.. _tools/lib/bpf/bpf_tracing.h:
+   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/lib/bpf/bpf_tracing.h
+.. _tools/testing/selftests/bpf/progs/lsm.c:
+   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm.c
+.. _tools/testing/selftests/bpf/progs/lsm_void_hook.c:
+   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm_void_hook.c
+.. _tools/testing/selftests/bpf/prog_tests/test_lsm.c:
+   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/prog_tests/test_lsm.c
diff --git a/Documentation/bpf/index.rst b/Documentation/bpf/index.rst
index 7be43c5f2dcf..f99677f3572f 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 and debugging BPF
-- 
2.20.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-26 14:28 ` [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution KP Singh
@ 2020-03-26 19:12   ` Andrii Nakryiko
  2020-03-26 19:39     ` KP Singh
  2020-03-27  0:24   ` James Morris
  2020-03-27  3:12   ` Alexei Starovoitov
  2 siblings, 1 reply; 33+ messages in thread
From: Andrii Nakryiko @ 2020-03-26 19:12 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Alexei Starovoitov, Daniel Borkmann,
	James Morris, Kees Cook, Paul Turner, Jann Horn, Florent Revest,
	Brendan Jackman, Greg Kroah-Hartman

On Thu, Mar 26, 2020 at 7:29 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> JITed BPF programs are dynamically attached to the LSM hooks
> using BPF trampolines. The trampoline prologue generates code to handle
> conversion of the signature of the hook to the appropriate BPF context.
>
> The allocated trampoline programs are attached to the nop functions
> initialized as LSM hooks.
>
> BPF_PROG_TYPE_LSM programs must have a GPL compatible license and
> and need CAP_SYS_ADMIN (required for loading eBPF programs).
>
> Upon attachment:
>
> * A BPF fexit trampoline is used for LSM hooks with a void return type.
> * A BPF fmod_ret trampoline is used for LSM hooks which return an
>   int. The attached programs can override the return value of the
>   bpf LSM hook to indicate a MAC Policy decision.
>
> Signed-off-by: KP Singh <kpsingh@google.com>
> Reviewed-by: Brendan Jackman <jackmanb@google.com>
> Reviewed-by: Florent Revest <revest@google.com>
> ---

Acked-by: Andrii Nakryiko <andriin@fb.com>


>  include/linux/bpf_lsm.h | 11 ++++++++
>  kernel/bpf/bpf_lsm.c    | 28 ++++++++++++++++++++
>  kernel/bpf/btf.c        |  9 ++++++-
>  kernel/bpf/syscall.c    | 57 ++++++++++++++++++++++++++++-------------
>  kernel/bpf/trampoline.c | 17 +++++++++---
>  kernel/bpf/verifier.c   | 19 +++++++++++---
>  6 files changed, 114 insertions(+), 27 deletions(-)
>

[...]

> @@ -2479,6 +2496,10 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
>                 }
>                 buf[sizeof(buf) - 1] = 0;
>                 tp_name = buf;
> +               break;
> +       default:
> +                       err = -EINVAL;
> +                       goto out_put_prog;
>         }

is indentation off here or it's my email client?

[...]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 7/8] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
  2020-03-26 14:28 ` [PATCH bpf-next v7 7/8] bpf: lsm: Add selftests " KP Singh
@ 2020-03-26 19:24   ` Andrii Nakryiko
  2020-03-26 19:44     ` KP Singh
  2020-03-27  0:31   ` James Morris
  1 sibling, 1 reply; 33+ messages in thread
From: Andrii Nakryiko @ 2020-03-26 19:24 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Thomas Garnier, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman

On Thu, Mar 26, 2020 at 7:30 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> * Load/attach a BPF program that hooks to file_mprotect (int)
>   and bprm_committed_creds (void).
> * Perform an action that triggers the hook.
> * Verify if the audit event was received using the shared global
>   variables for the process executed.
> * Verify if the mprotect returns a -EPERM.
>
> Signed-off-by: KP Singh <kpsingh@google.com>
> Reviewed-by: Brendan Jackman <jackmanb@google.com>
> Reviewed-by: Florent Revest <revest@google.com>
> Reviewed-by: Thomas Garnier <thgarnie@google.com>
> ---

Please fix endlines below. With that:

Acked-by: Andrii Nakryiko <andriin@fb.com>

>  tools/testing/selftests/bpf/config            |  2 +
>  .../selftests/bpf/prog_tests/test_lsm.c       | 86 +++++++++++++++++++
>  tools/testing/selftests/bpf/progs/lsm.c       | 48 +++++++++++
>  3 files changed, 136 insertions(+)
>  create mode 100644 tools/testing/selftests/bpf/prog_tests/test_lsm.c
>  create mode 100644 tools/testing/selftests/bpf/progs/lsm.c
>

[...]

> +void test_test_lsm(void)
> +{
> +       struct lsm *skel = NULL;
> +       int err, duration = 0;
> +
> +       skel = lsm__open_and_load();
> +       if (CHECK(!skel, "skel_load", "lsm skeleton failed\n"))
> +               goto close_prog;
> +
> +       err = lsm__attach(skel);
> +       if (CHECK(err, "attach", "lsm attach failed: %d\n", err))
> +               goto close_prog;
> +
> +       err = exec_cmd(&skel->bss->monitored_pid);
> +       if (CHECK(err < 0, "exec_cmd", "err %d errno %d\n", err, errno))
> +               goto close_prog;
> +
> +       CHECK(skel->bss->bprm_count != 1, "bprm_count", "bprm_count = %d",

\n is missing

> +             skel->bss->bprm_count);
> +
> +       skel->bss->monitored_pid = getpid();
> +
> +       err = heap_mprotect();
> +       if (CHECK(errno != EPERM, "heap_mprotect", "want errno=EPERM, got %d\n",
> +                 errno))
> +               goto close_prog;
> +
> +       CHECK(skel->bss->mprotect_count != 1, "mprotect_count",
> +             "mprotect_count = %d", skel->bss->mprotect_count);

\n is missing

> +
> +close_prog:
> +       lsm__destroy(skel);
> +}

[...]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 8/8] bpf: lsm: Add Documentation
  2020-03-26 14:28 ` [PATCH bpf-next v7 8/8] bpf: lsm: Add Documentation KP Singh
@ 2020-03-26 19:31   ` Andrii Nakryiko
  2020-03-26 20:56     ` KP Singh
  2020-03-27  0:33   ` James Morris
  1 sibling, 1 reply; 33+ messages in thread
From: Andrii Nakryiko @ 2020-03-26 19:31 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Thomas Garnier, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman

On Thu, Mar 26, 2020 at 7:29 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> 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 <kpsingh@google.com>
> Reviewed-by: Brendan Jackman <jackmanb@google.com>
> Reviewed-by: Florent Revest <revest@google.com>
> Reviewed-by: Thomas Garnier <thgarnie@google.com>
> ---

This needs another pass and re-reading, has a bunch of outdated info :)

>  Documentation/bpf/bpf_lsm.rst | 150 ++++++++++++++++++++++++++++++++++
>  Documentation/bpf/index.rst   |   1 +
>  2 files changed, 151 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..2a2c3b4a74d4
> --- /dev/null
> +++ b/Documentation/bpf/bpf_lsm.rst
> @@ -0,0 +1,150 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +.. Copyright (C) 2020 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);
> +
> +Other LSM hooks which can be instrumented can be found in
> +``include/linux/lsm_hooks.h``.
> +
> +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.

type should match/be compatible as well?

> +
> +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 <path-to-btf-vmlinux> format c > vmlinux.h
> +

bpftool btf *dump* file

> +.. 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/lib/bpf/bpf_tracing.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
> +                */

return missing?

> +       }
> +
> +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
> +-------
> +
> +eBPF 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);

Can you please update this to not use deprecated/legacy APIs. Please
suggest bpf_object__open/bpf_object__load  and/or BPF skeleton as an
example.

> +
> +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

BPF_PROG_ATTACH is incorrect, it's RAW_TRACEPOINT_OPEN, isn't it?

> +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();

that's not how it works in C ;)

bpf_link__destroy(link);

> +
> +Examples
> +--------
> +
> +An example eBPF programs can be found in
> +`tools/testing/selftests/bpf/progs/lsm.c`_ and the corresponding
> +userspace code in `tools/testing/selftests/bpf/prog_tests/test_lsm.c`_
> +
> +.. Links
> +.. _tools/lib/bpf/bpf_tracing.h:
> +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/lib/bpf/bpf_tracing.h
> +.. _tools/testing/selftests/bpf/progs/lsm.c:
> +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm.c
> +.. _tools/testing/selftests/bpf/progs/lsm_void_hook.c:
> +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm_void_hook.c
> +.. _tools/testing/selftests/bpf/prog_tests/test_lsm.c:
> +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/prog_tests/test_lsm.c
> diff --git a/Documentation/bpf/index.rst b/Documentation/bpf/index.rst
> index 7be43c5f2dcf..f99677f3572f 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 and debugging BPF
> --
> 2.20.1
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-26 19:12   ` Andrii Nakryiko
@ 2020-03-26 19:39     ` KP Singh
  0 siblings, 0 replies; 33+ messages in thread
From: KP Singh @ 2020-03-26 19:39 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: open list, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Alexei Starovoitov, Daniel Borkmann,
	James Morris, Kees Cook, Paul Turner, Jann Horn, Florent Revest,
	Brendan Jackman, Greg Kroah-Hartman

On 26-Mär 12:12, Andrii Nakryiko wrote:
> On Thu, Mar 26, 2020 at 7:29 AM KP Singh <kpsingh@chromium.org> wrote:
> >
> > From: KP Singh <kpsingh@google.com>
> >
> > JITed BPF programs are dynamically attached to the LSM hooks
> > using BPF trampolines. The trampoline prologue generates code to handle
> > conversion of the signature of the hook to the appropriate BPF context.
> >
> > The allocated trampoline programs are attached to the nop functions
> > initialized as LSM hooks.
> >
> > BPF_PROG_TYPE_LSM programs must have a GPL compatible license and
> > and need CAP_SYS_ADMIN (required for loading eBPF programs).
> >
> > Upon attachment:
> >
> > * A BPF fexit trampoline is used for LSM hooks with a void return type.
> > * A BPF fmod_ret trampoline is used for LSM hooks which return an
> >   int. The attached programs can override the return value of the
> >   bpf LSM hook to indicate a MAC Policy decision.
> >
> > Signed-off-by: KP Singh <kpsingh@google.com>
> > Reviewed-by: Brendan Jackman <jackmanb@google.com>
> > Reviewed-by: Florent Revest <revest@google.com>
> > ---
> 
> Acked-by: Andrii Nakryiko <andriin@fb.com>
> 
> 
> >  include/linux/bpf_lsm.h | 11 ++++++++
> >  kernel/bpf/bpf_lsm.c    | 28 ++++++++++++++++++++
> >  kernel/bpf/btf.c        |  9 ++++++-
> >  kernel/bpf/syscall.c    | 57 ++++++++++++++++++++++++++++-------------
> >  kernel/bpf/trampoline.c | 17 +++++++++---
> >  kernel/bpf/verifier.c   | 19 +++++++++++---
> >  6 files changed, 114 insertions(+), 27 deletions(-)
> >
> 
> [...]
> 
> > @@ -2479,6 +2496,10 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
> >                 }
> >                 buf[sizeof(buf) - 1] = 0;
> >                 tp_name = buf;
> > +               break;
> > +       default:
> > +                       err = -EINVAL;
> > +                       goto out_put_prog;
> >         }
> 
> is indentation off here or it's my email client?

You're mail client is fine :) It's me.

- KP

> 
> [...]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 7/8] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
  2020-03-26 19:24   ` Andrii Nakryiko
@ 2020-03-26 19:44     ` KP Singh
  0 siblings, 0 replies; 33+ messages in thread
From: KP Singh @ 2020-03-26 19:44 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: open list, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Thomas Garnier, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman

On 26-Mär 12:24, Andrii Nakryiko wrote:
> On Thu, Mar 26, 2020 at 7:30 AM KP Singh <kpsingh@chromium.org> wrote:
> >
> > From: KP Singh <kpsingh@google.com>
> >
> > * Load/attach a BPF program that hooks to file_mprotect (int)
> >   and bprm_committed_creds (void).
> > * Perform an action that triggers the hook.
> > * Verify if the audit event was received using the shared global
> >   variables for the process executed.
> > * Verify if the mprotect returns a -EPERM.
> >
> > Signed-off-by: KP Singh <kpsingh@google.com>
> > Reviewed-by: Brendan Jackman <jackmanb@google.com>
> > Reviewed-by: Florent Revest <revest@google.com>
> > Reviewed-by: Thomas Garnier <thgarnie@google.com>
> > ---
> 
> Please fix endlines below. With that:
> 
> Acked-by: Andrii Nakryiko <andriin@fb.com>
> 
> >  tools/testing/selftests/bpf/config            |  2 +
> >  .../selftests/bpf/prog_tests/test_lsm.c       | 86 +++++++++++++++++++
> >  tools/testing/selftests/bpf/progs/lsm.c       | 48 +++++++++++
> >  3 files changed, 136 insertions(+)
> >  create mode 100644 tools/testing/selftests/bpf/prog_tests/test_lsm.c
> >  create mode 100644 tools/testing/selftests/bpf/progs/lsm.c
> >
> 
> [...]
> 
> > +void test_test_lsm(void)
> > +{
> > +       struct lsm *skel = NULL;
> > +       int err, duration = 0;
> > +
> > +       skel = lsm__open_and_load();
> > +       if (CHECK(!skel, "skel_load", "lsm skeleton failed\n"))
> > +               goto close_prog;
> > +
> > +       err = lsm__attach(skel);
> > +       if (CHECK(err, "attach", "lsm attach failed: %d\n", err))
> > +               goto close_prog;
> > +
> > +       err = exec_cmd(&skel->bss->monitored_pid);
> > +       if (CHECK(err < 0, "exec_cmd", "err %d errno %d\n", err, errno))
> > +               goto close_prog;
> > +
> > +       CHECK(skel->bss->bprm_count != 1, "bprm_count", "bprm_count = %d",
> 
> \n is missing

Done.

> 
> > +             skel->bss->bprm_count);
> > +
> > +       skel->bss->monitored_pid = getpid();
> > +
> > +       err = heap_mprotect();
> > +       if (CHECK(errno != EPERM, "heap_mprotect", "want errno=EPERM, got %d\n",
> > +                 errno))
> > +               goto close_prog;
> > +
> > +       CHECK(skel->bss->mprotect_count != 1, "mprotect_count",
> > +             "mprotect_count = %d", skel->bss->mprotect_count);
> 
> \n is missing

Done.

- KP

> 
> > +
> > +close_prog:
> > +       lsm__destroy(skel);
> > +}
> 
> [...]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 8/8] bpf: lsm: Add Documentation
  2020-03-26 19:31   ` Andrii Nakryiko
@ 2020-03-26 20:56     ` KP Singh
  2020-03-26 22:01       ` Andrii Nakryiko
  0 siblings, 1 reply; 33+ messages in thread
From: KP Singh @ 2020-03-26 20:56 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: open list, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Thomas Garnier, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman

Thanks for the reviews!

On 26-Mär 12:31, Andrii Nakryiko wrote:
> On Thu, Mar 26, 2020 at 7:29 AM KP Singh <kpsingh@chromium.org> wrote:
> >
> > From: KP Singh <kpsingh@google.com>
> >
> > 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 <kpsingh@google.com>
> > Reviewed-by: Brendan Jackman <jackmanb@google.com>
> > Reviewed-by: Florent Revest <revest@google.com>
> > Reviewed-by: Thomas Garnier <thgarnie@google.com>
> > ---
> 
> This needs another pass and re-reading, has a bunch of outdated info :)

Indeed :)

> 
> >  Documentation/bpf/bpf_lsm.rst | 150 ++++++++++++++++++++++++++++++++++
> >  Documentation/bpf/index.rst   |   1 +
> >  2 files changed, 151 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..2a2c3b4a74d4
> > --- /dev/null
> > +++ b/Documentation/bpf/bpf_lsm.rst
> > @@ -0,0 +1,150 @@
> > +.. SPDX-License-Identifier: GPL-2.0+
> > +.. Copyright (C) 2020 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);
> > +
> > +Other LSM hooks which can be instrumented can be found in
> > +``include/linux/lsm_hooks.h``.
> > +
> > +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.
> 
> type should match/be compatible as well?

I changed it to simply be:

.. note:: 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 <path-to-btf-vmlinux> format c > vmlinux.h
> > +
> 
> bpftool btf *dump* file

Done.

> 
> > +.. 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/lib/bpf/bpf_tracing.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
> > +                */
> 
> return missing?

Fixed.

> 
> > +       }
> > +
> > +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
> > +-------
> > +
> > +eBPF 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);
> 
> Can you please update this to not use deprecated/legacy APIs. Please
> suggest bpf_object__open/bpf_object__load  and/or BPF skeleton as an
> example.


Simplified and modernized this section as:


Loading
-------

eBPF programs can be loaded with the :manpage:`bpf(2)` syscall's
``BPF_PROG_LOAD`` operation:

.. code-block:: c

	struct bpf_object *obj;

	obj = bpf_object__open("./my_prog.o");
	bpf_object__load(obj);

This can be simplified by using a skeleton header generated by ``bpftool``:

.. code-block:: console

	# bpftool gen skeleton my_prog.o > my_prog.skel.h

and the program can be loaded by including ``my_prog.skel.h`` and using
the generated helper, ``my_prog__open_and_load``.

Attachment to LSM Hooks
-----------------------

The LSM allows attachment of eBPF programs as LSM hooks using :manpage:`bpf(2)`
syscall's ``BPF_RAW_TRACEPOINT_OPEN`` operation or more simply by
using the libbpf helper ``bpf_program__attach_lsm``.

The program can be detached from the LSM hook by *destroying* the ``link``
link returned by ``bpf_program__attach_lsm`` using ``bpf_link__destroy``.

One can also use the helpers generated in ``my_prog.skel.h`` i.e.
``my_prog__attach`` for attachment and ``my_prog__destroy`` for cleaning up.

</end>

If this looks okay, I will send a v8 with this updated and other
fixes.

- KP

> 
> > +
> > +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
> 
> BPF_PROG_ATTACH is incorrect, it's RAW_TRACEPOINT_OPEN, isn't it?

Correct, updated. Thanks!

> 
> > +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();
> 
> that's not how it works in C ;)

Oops, I incorrectly picked it up from link->destroy(link); and wrote
something stupid.

> 
> bpf_link__destroy(link);

Updated in the snippet posted above.

- KP

> 
> > +
> > +Examples
> > +--------
> > +
> > +An example eBPF programs can be found in
> > +`tools/testing/selftests/bpf/progs/lsm.c`_ and the corresponding
> > +userspace code in `tools/testing/selftests/bpf/prog_tests/test_lsm.c`_
> > +
> > +.. Links
> > +.. _tools/lib/bpf/bpf_tracing.h:
> > +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/lib/bpf/bpf_tracing.h
> > +.. _tools/testing/selftests/bpf/progs/lsm.c:
> > +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm.c
> > +.. _tools/testing/selftests/bpf/progs/lsm_void_hook.c:
> > +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm_void_hook.c
> > +.. _tools/testing/selftests/bpf/prog_tests/test_lsm.c:
> > +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/prog_tests/test_lsm.c
> > diff --git a/Documentation/bpf/index.rst b/Documentation/bpf/index.rst
> > index 7be43c5f2dcf..f99677f3572f 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 and debugging BPF
> > --
> > 2.20.1
> >

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 8/8] bpf: lsm: Add Documentation
  2020-03-26 20:56     ` KP Singh
@ 2020-03-26 22:01       ` Andrii Nakryiko
  0 siblings, 0 replies; 33+ messages in thread
From: Andrii Nakryiko @ 2020-03-26 22:01 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Thomas Garnier, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman

On Thu, Mar 26, 2020 at 1:56 PM KP Singh <kpsingh@chromium.org> wrote:
>
> Thanks for the reviews!
>
> On 26-Mär 12:31, Andrii Nakryiko wrote:
> > On Thu, Mar 26, 2020 at 7:29 AM KP Singh <kpsingh@chromium.org> wrote:
> > >
> > > From: KP Singh <kpsingh@google.com>
> > >
> > > 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 <kpsingh@google.com>
> > > Reviewed-by: Brendan Jackman <jackmanb@google.com>
> > > Reviewed-by: Florent Revest <revest@google.com>
> > > Reviewed-by: Thomas Garnier <thgarnie@google.com>
> > > ---
> >
> > This needs another pass and re-reading, has a bunch of outdated info :)
>
> Indeed :)
>
> >
> > >  Documentation/bpf/bpf_lsm.rst | 150 ++++++++++++++++++++++++++++++++++
> > >  Documentation/bpf/index.rst   |   1 +
> > >  2 files changed, 151 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..2a2c3b4a74d4
> > > --- /dev/null
> > > +++ b/Documentation/bpf/bpf_lsm.rst
> > > @@ -0,0 +1,150 @@
> > > +.. SPDX-License-Identifier: GPL-2.0+
> > > +.. Copyright (C) 2020 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);
> > > +
> > > +Other LSM hooks which can be instrumented can be found in
> > > +``include/linux/lsm_hooks.h``.
> > > +
> > > +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.
> >
> > type should match/be compatible as well?
>
> I changed it to simply be:
>
> .. note:: 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 <path-to-btf-vmlinux> format c > vmlinux.h
> > > +
> >
> > bpftool btf *dump* file
>
> Done.
>
> >
> > > +.. 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/lib/bpf/bpf_tracing.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
> > > +                */
> >
> > return missing?
>
> Fixed.
>
> >
> > > +       }
> > > +
> > > +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
> > > +-------
> > > +
> > > +eBPF 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);
> >
> > Can you please update this to not use deprecated/legacy APIs. Please
> > suggest bpf_object__open/bpf_object__load  and/or BPF skeleton as an
> > example.
>
>
> Simplified and modernized this section as:
>
>
> Loading
> -------
>
> eBPF programs can be loaded with the :manpage:`bpf(2)` syscall's
> ``BPF_PROG_LOAD`` operation:
>
> .. code-block:: c
>
>         struct bpf_object *obj;
>
>         obj = bpf_object__open("./my_prog.o");
>         bpf_object__load(obj);
>
> This can be simplified by using a skeleton header generated by ``bpftool``:
>
> .. code-block:: console
>
>         # bpftool gen skeleton my_prog.o > my_prog.skel.h
>
> and the program can be loaded by including ``my_prog.skel.h`` and using
> the generated helper, ``my_prog__open_and_load``.
>
> Attachment to LSM Hooks
> -----------------------
>
> The LSM allows attachment of eBPF programs as LSM hooks using :manpage:`bpf(2)`
> syscall's ``BPF_RAW_TRACEPOINT_OPEN`` operation or more simply by
> using the libbpf helper ``bpf_program__attach_lsm``.
>
> The program can be detached from the LSM hook by *destroying* the ``link``
> link returned by ``bpf_program__attach_lsm`` using ``bpf_link__destroy``.
>
> One can also use the helpers generated in ``my_prog.skel.h`` i.e.
> ``my_prog__attach`` for attachment and ``my_prog__destroy`` for cleaning up.
>
> </end>
>
> If this looks okay, I will send a v8 with this updated and other
> fixes.
>

Sounds good.

> - KP
>
> >
> > > +
> > > +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
> >
> > BPF_PROG_ATTACH is incorrect, it's RAW_TRACEPOINT_OPEN, isn't it?
>
> Correct, updated. Thanks!
>
> >
> > > +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();
> >
> > that's not how it works in C ;)
>
> Oops, I incorrectly picked it up from link->destroy(link); and wrote
> something stupid.
>
> >
> > bpf_link__destroy(link);
>
> Updated in the snippet posted above.
>
> - KP
>
> >
> > > +
> > > +Examples
> > > +--------
> > > +
> > > +An example eBPF programs can be found in
> > > +`tools/testing/selftests/bpf/progs/lsm.c`_ and the corresponding
> > > +userspace code in `tools/testing/selftests/bpf/prog_tests/test_lsm.c`_
> > > +
> > > +.. Links
> > > +.. _tools/lib/bpf/bpf_tracing.h:
> > > +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/lib/bpf/bpf_tracing.h
> > > +.. _tools/testing/selftests/bpf/progs/lsm.c:
> > > +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm.c
> > > +.. _tools/testing/selftests/bpf/progs/lsm_void_hook.c:
> > > +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm_void_hook.c
> > > +.. _tools/testing/selftests/bpf/prog_tests/test_lsm.c:
> > > +   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/prog_tests/test_lsm.c
> > > diff --git a/Documentation/bpf/index.rst b/Documentation/bpf/index.rst
> > > index 7be43c5f2dcf..f99677f3572f 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 and debugging BPF
> > > --
> > > 2.20.1
> > >

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-26 14:28 ` [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution KP Singh
  2020-03-26 19:12   ` Andrii Nakryiko
@ 2020-03-27  0:24   ` James Morris
  2020-03-27 12:27     ` Stephen Smalley
  2020-03-27  3:12   ` Alexei Starovoitov
  2 siblings, 1 reply; 33+ messages in thread
From: James Morris @ 2020-03-27  0:24 UTC (permalink / raw)
  To: KP Singh, Stephen Smalley
  Cc: linux-kernel, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Alexei Starovoitov, Daniel Borkmann, Kees Cook,
	Paul Turner, Jann Horn, Florent Revest, Brendan Jackman,
	Greg Kroah-Hartman

On Thu, 26 Mar 2020, KP Singh wrote:

> +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;
> +

Stephen, can you confirm that your concerns around this are resolved 
(IIRC, by SELinux implementing a bpf_prog callback) ?


-- 
James Morris
<jmorris@namei.org>


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 1/8] bpf: Introduce BPF_PROG_TYPE_LSM
  2020-03-26 14:28 ` [PATCH bpf-next v7 1/8] bpf: Introduce BPF_PROG_TYPE_LSM KP Singh
@ 2020-03-27  0:27   ` James Morris
  0 siblings, 0 replies; 33+ messages in thread
From: James Morris @ 2020-03-27  0:27 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Thomas Garnier, Yonghong Song, Andrii Nakryiko,
	Alexei Starovoitov, Daniel Borkmann, Kees Cook, Paul Turner,
	Jann Horn, Florent Revest, Brendan Jackman, Greg Kroah-Hartman

On Thu, 26 Mar 2020, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> 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 <kpsingh@google.com>
> Reviewed-by: Brendan Jackman <jackmanb@google.com>
> Reviewed-by: Florent Revest <revest@google.com>
> Reviewed-by: Thomas Garnier <thgarnie@google.com>
> Acked-by: Yonghong Song <yhs@fb.com>
> Acked-by: Andrii Nakryiko <andriin@fb.com>


Acked-by: James Morris <jamorris@linux.microsoft.com>
 

-- 
James Morris
<jmorris@namei.org>


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 2/8] security: Refactor declaration of LSM hooks
  2020-03-26 14:28 ` [PATCH bpf-next v7 2/8] security: Refactor declaration of LSM hooks KP Singh
@ 2020-03-27  0:28   ` James Morris
  0 siblings, 0 replies; 33+ messages in thread
From: James Morris @ 2020-03-27  0:28 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Kees Cook, Casey Schaufler, Alexei Starovoitov,
	Daniel Borkmann, Paul Turner, Jann Horn, Florent Revest,
	Brendan Jackman, Greg Kroah-Hartman

On Thu, 26 Mar 2020, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> 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_defs.h which is then used to generate all
> the data structures required by the LSM framework.
> 
> The LSM hooks are defined as:
> 
>   LSM_HOOK(<return_type>, <default_value>, <hook_name>, args...)
> 
> with <default_value> acccessible in security.c as:
> 
>   LSM_RET_DEFAULT(<hook_name>)
> 
> Signed-off-by: KP Singh <kpsingh@google.com>
> Reviewed-by: Brendan Jackman <jackmanb@google.com>
> Reviewed-by: Florent Revest <revest@google.com>
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>


Acked-by: James Morris <jamorris@linux.microsoft.com>


-- 
James Morris
<jmorris@namei.org>


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 3/8] bpf: lsm: provide attachment points for BPF LSM programs
  2020-03-26 14:28 ` [PATCH bpf-next v7 3/8] bpf: lsm: provide attachment points for BPF LSM programs KP Singh
@ 2020-03-27  0:29   ` James Morris
  0 siblings, 0 replies; 33+ messages in thread
From: James Morris @ 2020-03-27  0:29 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Kees Cook, Yonghong Song, Alexei Starovoitov,
	Daniel Borkmann, Paul Turner, Jann Horn, Florent Revest,
	Brendan Jackman, Greg Kroah-Hartman

On Thu, 26 Mar 2020, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> When CONFIG_BPF_LSM is enabled, nop functions, bpf_lsm_<hook_name>, are
> generated for each LSM hook. These functions are initialized as LSM
> hooks in a subsequent patch.
> 
> Signed-off-by: KP Singh <kpsingh@google.com>
> Reviewed-by: Brendan Jackman <jackmanb@google.com>
> Reviewed-by: Florent Revest <revest@google.com>
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Acked-by: Yonghong Song <yhs@fb.com>


Acked-by: James Morris <jamorris@linux.microsoft.com>


-- 
James Morris
<jmorris@namei.org>


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 5/8] bpf: lsm: Initialize the BPF LSM hooks
  2020-03-26 14:28 ` [PATCH bpf-next v7 5/8] bpf: lsm: Initialize the BPF LSM hooks KP Singh
@ 2020-03-27  0:29   ` James Morris
  0 siblings, 0 replies; 33+ messages in thread
From: James Morris @ 2020-03-27  0:29 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Kees Cook,
	Brendan Jackman, Florent Revest, Alexei Starovoitov,
	Daniel Borkmann, Paul Turner, Jann Horn, Florent Revest,
	Brendan Jackman, Greg Kroah-Hartman

On Thu, 26 Mar 2020, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> * The hooks are initialized using the definitions in
>   include/linux/lsm_hook_defs.h.
> * The LSM can be enabled / disabled with CONFIG_BPF_LSM.
> 
> Signed-off-by: KP Singh <kpsingh@google.com>
> Acked-by: Kees Cook <keescook@chromium.org>
> Reviewed-by: Brendan Jackman <jackmanb@google.com>
> Reviewed-by: Florent Revest <revest@google.com>
> ---
>  security/Kconfig      | 10 +++++-----
>  security/Makefile     |  2 ++
>  security/bpf/Makefile |  5 +++++
>  security/bpf/hooks.c  | 26 ++++++++++++++++++++++++++
>  4 files changed, 38 insertions(+), 5 deletions(-)
>  create mode 100644 security/bpf/Makefile
>  create mode 100644 security/bpf/hooks.c


Acked-by: James Morris <jamorris@linux.microsoft.com>


-- 
James Morris
<jmorris@namei.org>


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 6/8] tools/libbpf: Add support for BPF_PROG_TYPE_LSM
  2020-03-26 14:28 ` [PATCH bpf-next v7 6/8] tools/libbpf: Add support for BPF_PROG_TYPE_LSM KP Singh
@ 2020-03-27  0:30   ` James Morris
  0 siblings, 0 replies; 33+ messages in thread
From: James Morris @ 2020-03-27  0:30 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Yonghong Song, Andrii Nakryiko,
	Alexei Starovoitov, Daniel Borkmann, Kees Cook, Paul Turner,
	Jann Horn, Florent Revest, Brendan Jackman, Greg Kroah-Hartman

On Thu, 26 Mar 2020, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> 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_id.
> 
> 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 <kpsingh@google.com>
> Reviewed-by: Brendan Jackman <jackmanb@google.com>
> Reviewed-by: Florent Revest <revest@google.com>
> Acked-by: Yonghong Song <yhs@fb.com>
> Acked-by: Andrii Nakryiko <andriin@fb.com>


Reviewed-by: James Morris <jamorris@linux.microsoft.com>


-- 
James Morris
<jmorris@namei.org>


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 7/8] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
  2020-03-26 14:28 ` [PATCH bpf-next v7 7/8] bpf: lsm: Add selftests " KP Singh
  2020-03-26 19:24   ` Andrii Nakryiko
@ 2020-03-27  0:31   ` James Morris
  1 sibling, 0 replies; 33+ messages in thread
From: James Morris @ 2020-03-27  0:31 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Thomas Garnier, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman

On Thu, 26 Mar 2020, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> * Load/attach a BPF program that hooks to file_mprotect (int)
>   and bprm_committed_creds (void).
> * Perform an action that triggers the hook.
> * Verify if the audit event was received using the shared global
>   variables for the process executed.
> * Verify if the mprotect returns a -EPERM.
> 
> Signed-off-by: KP Singh <kpsingh@google.com>
> Reviewed-by: Brendan Jackman <jackmanb@google.com>
> Reviewed-by: Florent Revest <revest@google.com>
> Reviewed-by: Thomas Garnier <thgarnie@google.com>

Cool stuff!

Reviewed-by: James Morris <jamorris@linux.microsoft.com>


-- 
James Morris
<jmorris@namei.org>


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 8/8] bpf: lsm: Add Documentation
  2020-03-26 14:28 ` [PATCH bpf-next v7 8/8] bpf: lsm: Add Documentation KP Singh
  2020-03-26 19:31   ` Andrii Nakryiko
@ 2020-03-27  0:33   ` James Morris
  1 sibling, 0 replies; 33+ messages in thread
From: James Morris @ 2020-03-27  0:33 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Thomas Garnier, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman

On Thu, 26 Mar 2020, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> 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 <kpsingh@google.com>
> Reviewed-by: Brendan Jackman <jackmanb@google.com>
> Reviewed-by: Florent Revest <revest@google.com>
> Reviewed-by: Thomas Garnier <thgarnie@google.com>


Reviewed-by: James Morris <jamorris@linux.microsoft.com>


-- 
James Morris
<jmorris@namei.org>


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-26 14:28 ` [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution KP Singh
  2020-03-26 19:12   ` Andrii Nakryiko
  2020-03-27  0:24   ` James Morris
@ 2020-03-27  3:12   ` Alexei Starovoitov
  2020-03-27 15:06     ` KP Singh
  2 siblings, 1 reply; 33+ messages in thread
From: Alexei Starovoitov @ 2020-03-27  3:12 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Alexei Starovoitov, Daniel Borkmann,
	James Morris, Kees Cook, Paul Turner, Jann Horn, Florent Revest,
	Brendan Jackman, Greg Kroah-Hartman

On Thu, Mar 26, 2020 at 03:28:19PM +0100, KP Singh wrote:
>  
>  	if (arg == nr_args) {
> -		if (prog->expected_attach_type == BPF_TRACE_FEXIT) {
> +		/* BPF_LSM_MAC programs only have int and void functions they
> +		 * can be attached to. When they are attached to a void function
> +		 * they result in the creation of an FEXIT trampoline and when
> +		 * to a function that returns an int, a MODIFY_RETURN
> +		 * trampoline.
> +		 */
> +		if (prog->expected_attach_type == BPF_TRACE_FEXIT ||
> +		    prog->expected_attach_type == BPF_LSM_MAC) {
>  			if (!t)
>  				return true;
>  			t = btf_type_by_id(btf, t->type);

Could you add a comment here that though BPF_MODIFY_RETURN-like check
if (ret_type != 'int') return -EINVAL;
is _not_ done here. It is still safe, since LSM hooks have only
void and int return types.

> +	case BPF_LSM_MAC:
> +		if (!prog->aux->attach_func_proto->type)
> +			/* The function returns void, we cannot modify its
> +			 * return value.
> +			 */
> +			return BPF_TRAMP_FEXIT;
> +		else
> +			return BPF_TRAMP_MODIFY_RETURN;

I was thinking whether it would help performance significantly enough
if we add a flavor of BPF_TRAMP_FEXIT that doesn't have
BPF_TRAMP_F_CALL_ORIG.
That will save the cost of nop call, but I guess indirect call due
to lsm infra is slow enough, so this extra few cycles won't be noticeable.
So I'm fine with it as-is. When lsm hooks will get rid of indirect call
we can optimize it further.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-27  0:24   ` James Morris
@ 2020-03-27 12:27     ` Stephen Smalley
  2020-03-27 12:41       ` KP Singh
  0 siblings, 1 reply; 33+ messages in thread
From: Stephen Smalley @ 2020-03-27 12:27 UTC (permalink / raw)
  To: James Morris, KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Alexei Starovoitov, Daniel Borkmann, Kees Cook,
	Paul Turner, Jann Horn, Florent Revest, Brendan Jackman,
	Greg Kroah-Hartman, Paul Moore

On 3/26/20 8:24 PM, James Morris wrote:
> On Thu, 26 Mar 2020, KP Singh wrote:
> 
>> +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;
>> +
> 
> Stephen, can you confirm that your concerns around this are resolved
> (IIRC, by SELinux implementing a bpf_prog callback) ?

I guess the only residual concern I have is that CAP_MAC_ADMIN means 
something different to SELinux (ability to get/set file security 
contexts unknown to the currently loaded policy), so leaving the 
CAP_MAC_ADMIN check here (versus calling a new security hook here and 
checking CAP_MAC_ADMIN in the implementation of that hook for the 
modules that want that) conflates two very different things.  Prior to 
this patch, there are no users of CAP_MAC_ADMIN outside of individual 
security modules; it is only checked in module-specific logic within 
apparmor, safesetid, selinux, and smack, so the meaning was module-specific.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-27 12:27     ` Stephen Smalley
@ 2020-03-27 12:41       ` KP Singh
  2020-03-27 13:43         ` Stephen Smalley
  0 siblings, 1 reply; 33+ messages in thread
From: KP Singh @ 2020-03-27 12:41 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: James Morris, linux-kernel, bpf, linux-security-module,
	Brendan Jackman, Florent Revest, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman, Paul Moore

On 27-Mär 08:27, Stephen Smalley wrote:
> On 3/26/20 8:24 PM, James Morris wrote:
> > On Thu, 26 Mar 2020, KP Singh wrote:
> > 
> > > +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;
> > > +
> > 
> > Stephen, can you confirm that your concerns around this are resolved
> > (IIRC, by SELinux implementing a bpf_prog callback) ?
> 
> I guess the only residual concern I have is that CAP_MAC_ADMIN means
> something different to SELinux (ability to get/set file security contexts
> unknown to the currently loaded policy), so leaving the CAP_MAC_ADMIN check
> here (versus calling a new security hook here and checking CAP_MAC_ADMIN in
> the implementation of that hook for the modules that want that) conflates
> two very different things.  Prior to this patch, there are no users of
> CAP_MAC_ADMIN outside of individual security modules; it is only checked in
> module-specific logic within apparmor, safesetid, selinux, and smack, so the
> meaning was module-specific.

As we had discussed, We do have a security hook as well:

https://lore.kernel.org/bpf/20200324180652.GA11855@chromium.org/

The bpf_prog hook which can check for BPF_PROG_TYPE_LSM and implement
module specific logic for LSM programs. I thougt that was okay?

Kees was in favor of keeping the CAP_MAC_ADMIN check here:

https://lore.kernel.org/bpf/202003241133.16C02BE5B@keescook

If you feel strongly and Kees agrees, we can remove the CAP_MAC_ADMIN
check here, but given that we already have a security hook that meets
the requirements, we probably don't need another one.

- KP


> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-27 12:41       ` KP Singh
@ 2020-03-27 13:43         ` Stephen Smalley
  2020-03-27 14:29           ` KP Singh
  2020-03-27 16:36           ` Casey Schaufler
  0 siblings, 2 replies; 33+ messages in thread
From: Stephen Smalley @ 2020-03-27 13:43 UTC (permalink / raw)
  To: KP Singh
  Cc: James Morris, linux-kernel, bpf, linux-security-module,
	Brendan Jackman, Florent Revest, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman, Paul Moore

On 3/27/20 8:41 AM, KP Singh wrote:
> On 27-Mär 08:27, Stephen Smalley wrote:
>> On 3/26/20 8:24 PM, James Morris wrote:
>>> On Thu, 26 Mar 2020, KP Singh wrote:
>>>
>>>> +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;
>>>> +
>>>
>>> Stephen, can you confirm that your concerns around this are resolved
>>> (IIRC, by SELinux implementing a bpf_prog callback) ?
>>
>> I guess the only residual concern I have is that CAP_MAC_ADMIN means
>> something different to SELinux (ability to get/set file security contexts
>> unknown to the currently loaded policy), so leaving the CAP_MAC_ADMIN check
>> here (versus calling a new security hook here and checking CAP_MAC_ADMIN in
>> the implementation of that hook for the modules that want that) conflates
>> two very different things.  Prior to this patch, there are no users of
>> CAP_MAC_ADMIN outside of individual security modules; it is only checked in
>> module-specific logic within apparmor, safesetid, selinux, and smack, so the
>> meaning was module-specific.
> 
> As we had discussed, We do have a security hook as well:
> 
> https://lore.kernel.org/bpf/20200324180652.GA11855@chromium.org/
> 
> The bpf_prog hook which can check for BPF_PROG_TYPE_LSM and implement
> module specific logic for LSM programs. I thougt that was okay?
> 
> Kees was in favor of keeping the CAP_MAC_ADMIN check here:
> 
> https://lore.kernel.org/bpf/202003241133.16C02BE5B@keescook
> 
> If you feel strongly and Kees agrees, we can remove the CAP_MAC_ADMIN
> check here, but given that we already have a security hook that meets
> the requirements, we probably don't need another one.

I would favor removing the CAP_MAC_ADMIN check here, and implementing it 
in a bpf_prog hook for Smack and AppArmor if they want that.  SELinux 
would implement its own check in its existing bpf_prog hook.




^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-27 13:43         ` Stephen Smalley
@ 2020-03-27 14:29           ` KP Singh
  2020-03-27 16:36           ` Casey Schaufler
  1 sibling, 0 replies; 33+ messages in thread
From: KP Singh @ 2020-03-27 14:29 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: James Morris, linux-kernel, bpf, linux-security-module,
	Brendan Jackman, Florent Revest, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman, Paul Moore

On 27-Mär 09:43, Stephen Smalley wrote:
> On 3/27/20 8:41 AM, KP Singh wrote:
> > On 27-Mär 08:27, Stephen Smalley wrote:
> > > On 3/26/20 8:24 PM, James Morris wrote:
> > > > On Thu, 26 Mar 2020, KP Singh wrote:
> > > > 
> > > > > +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;
> > > > > +
> > > > 
> > > > Stephen, can you confirm that your concerns around this are resolved
> > > > (IIRC, by SELinux implementing a bpf_prog callback) ?
> > > 
> > > I guess the only residual concern I have is that CAP_MAC_ADMIN means
> > > something different to SELinux (ability to get/set file security contexts
> > > unknown to the currently loaded policy), so leaving the CAP_MAC_ADMIN check
> > > here (versus calling a new security hook here and checking CAP_MAC_ADMIN in
> > > the implementation of that hook for the modules that want that) conflates
> > > two very different things.  Prior to this patch, there are no users of
> > > CAP_MAC_ADMIN outside of individual security modules; it is only checked in
> > > module-specific logic within apparmor, safesetid, selinux, and smack, so the
> > > meaning was module-specific.
> > 
> > As we had discussed, We do have a security hook as well:
> > 
> > https://lore.kernel.org/bpf/20200324180652.GA11855@chromium.org/
> > 
> > The bpf_prog hook which can check for BPF_PROG_TYPE_LSM and implement
> > module specific logic for LSM programs. I thougt that was okay?
> > 
> > Kees was in favor of keeping the CAP_MAC_ADMIN check here:
> > 
> > https://lore.kernel.org/bpf/202003241133.16C02BE5B@keescook
> > 
> > If you feel strongly and Kees agrees, we can remove the CAP_MAC_ADMIN
> > check here, but given that we already have a security hook that meets
> > the requirements, we probably don't need another one.
> 
> I would favor removing the CAP_MAC_ADMIN check here, and implementing it in

Okay. For the scope of this series I will remove this check in the
next revision. If people feel strongly that we need it centrally
within the BPF infrastructure, we can do that as a separate patch and
discuss it there.

> a bpf_prog hook for Smack and AppArmor if they want that.  SELinux would
> implement its own check in its existing bpf_prog hook.

I think Smack and AppArmor can also use the same hook. Since we
already have a hook, I don't think anyone is blocked from
implementing policy logic for loading LSM BPF programs.

James/Kees does this sound okay?

- KP

> 
> 
> 

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-27  3:12   ` Alexei Starovoitov
@ 2020-03-27 15:06     ` KP Singh
  0 siblings, 0 replies; 33+ messages in thread
From: KP Singh @ 2020-03-27 15:06 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: linux-kernel, bpf, linux-security-module, Brendan Jackman,
	Florent Revest, Alexei Starovoitov, Daniel Borkmann,
	James Morris, Kees Cook, Paul Turner, Jann Horn, Florent Revest,
	Brendan Jackman, Greg Kroah-Hartman

On 26-Mär 20:12, Alexei Starovoitov wrote:
> On Thu, Mar 26, 2020 at 03:28:19PM +0100, KP Singh wrote:
> >  
> >  	if (arg == nr_args) {
> > -		if (prog->expected_attach_type == BPF_TRACE_FEXIT) {
> > +		/* BPF_LSM_MAC programs only have int and void functions they
> > +		 * can be attached to. When they are attached to a void function
> > +		 * they result in the creation of an FEXIT trampoline and when
> > +		 * to a function that returns an int, a MODIFY_RETURN
> > +		 * trampoline.
> > +		 */
> > +		if (prog->expected_attach_type == BPF_TRACE_FEXIT ||
> > +		    prog->expected_attach_type == BPF_LSM_MAC) {
> >  			if (!t)
> >  				return true;
> >  			t = btf_type_by_id(btf, t->type);
> 
> Could you add a comment here that though BPF_MODIFY_RETURN-like check
> if (ret_type != 'int') return -EINVAL;
> is _not_ done here. It is still safe, since LSM hooks have only
> void and int return types.

Good idea, I reworded the comment to make this explicit and moved
the comment to inside the if condition.

> 
> > +	case BPF_LSM_MAC:
> > +		if (!prog->aux->attach_func_proto->type)
> > +			/* The function returns void, we cannot modify its
> > +			 * return value.
> > +			 */
> > +			return BPF_TRAMP_FEXIT;
> > +		else
> > +			return BPF_TRAMP_MODIFY_RETURN;
> 
> I was thinking whether it would help performance significantly enough
> if we add a flavor of BPF_TRAMP_FEXIT that doesn't have
> BPF_TRAMP_F_CALL_ORIG.

Agreed.

> That will save the cost of nop call, but I guess indirect call due
> to lsm infra is slow enough, so this extra few cycles won't be noticeable.
> So I'm fine with it as-is. When lsm hooks will get rid of indirect call
> we can optimize it further.

Also agreed, that's the next step. :)

- KP

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-27 13:43         ` Stephen Smalley
  2020-03-27 14:29           ` KP Singh
@ 2020-03-27 16:36           ` Casey Schaufler
  2020-03-27 18:59             ` Kees Cook
  1 sibling, 1 reply; 33+ messages in thread
From: Casey Schaufler @ 2020-03-27 16:36 UTC (permalink / raw)
  To: Stephen Smalley, KP Singh
  Cc: James Morris, linux-kernel, bpf, linux-security-module,
	Brendan Jackman, Florent Revest, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman, Paul Moore,
	Casey Schaufler

On 3/27/2020 6:43 AM, Stephen Smalley wrote:
> On 3/27/20 8:41 AM, KP Singh wrote:
>> On 27-Mär 08:27, Stephen Smalley wrote:
>>> On 3/26/20 8:24 PM, James Morris wrote:
>>>> On Thu, 26 Mar 2020, KP Singh wrote:
>>>>
>>>>> +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;
>>>>> +
>>>>
>>>> Stephen, can you confirm that your concerns around this are resolved
>>>> (IIRC, by SELinux implementing a bpf_prog callback) ?
>>>
>>> I guess the only residual concern I have is that CAP_MAC_ADMIN means
>>> something different to SELinux (ability to get/set file security contexts
>>> unknown to the currently loaded policy), so leaving the CAP_MAC_ADMIN check
>>> here (versus calling a new security hook here and checking CAP_MAC_ADMIN in
>>> the implementation of that hook for the modules that want that) conflates
>>> two very different things.  Prior to this patch, there are no users of
>>> CAP_MAC_ADMIN outside of individual security modules; it is only checked in
>>> module-specific logic within apparmor, safesetid, selinux, and smack, so the
>>> meaning was module-specific.
>>
>> As we had discussed, We do have a security hook as well:
>>
>> https://lore.kernel.org/bpf/20200324180652.GA11855@chromium.org/
>>
>> The bpf_prog hook which can check for BPF_PROG_TYPE_LSM and implement
>> module specific logic for LSM programs. I thougt that was okay?
>>
>> Kees was in favor of keeping the CAP_MAC_ADMIN check here:
>>
>> https://lore.kernel.org/bpf/202003241133.16C02BE5B@keescook
>>
>> If you feel strongly and Kees agrees, we can remove the CAP_MAC_ADMIN
>> check here, but given that we already have a security hook that meets
>> the requirements, we probably don't need another one.
>
> I would favor removing the CAP_MAC_ADMIN check here, and implementing it in a bpf_prog hook for Smack and AppArmor if they want that.  SELinux would implement its own check in its existing bpf_prog hook.
>
The whole notion of one security module calling into another for permission
to do something still gives me the heebee jeebees, but if more nimble minds
than mine think this is a good idea I won't nack it.


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-27 16:36           ` Casey Schaufler
@ 2020-03-27 18:59             ` Kees Cook
  2020-03-27 19:17               ` KP Singh
  0 siblings, 1 reply; 33+ messages in thread
From: Kees Cook @ 2020-03-27 18:59 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Stephen Smalley, KP Singh, James Morris, linux-kernel, bpf,
	linux-security-module, Brendan Jackman, Florent Revest,
	Alexei Starovoitov, Daniel Borkmann, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman, Paul Moore

On Fri, Mar 27, 2020 at 09:36:15AM -0700, Casey Schaufler wrote:
> On 3/27/2020 6:43 AM, Stephen Smalley wrote:
> > On 3/27/20 8:41 AM, KP Singh wrote:
> >> On 27-Mär 08:27, Stephen Smalley wrote:
> >>> On 3/26/20 8:24 PM, James Morris wrote:
> >>>> On Thu, 26 Mar 2020, KP Singh wrote:
> >>>>
> >>>>> +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;
> >>>>> +
> >>>>
> >>>> Stephen, can you confirm that your concerns around this are resolved
> >>>> (IIRC, by SELinux implementing a bpf_prog callback) ?
> >>>
> >>> I guess the only residual concern I have is that CAP_MAC_ADMIN means
> >>> something different to SELinux (ability to get/set file security contexts
> >>> unknown to the currently loaded policy), so leaving the CAP_MAC_ADMIN check
> >>> here (versus calling a new security hook here and checking CAP_MAC_ADMIN in
> >>> the implementation of that hook for the modules that want that) conflates
> >>> two very different things.  Prior to this patch, there are no users of
> >>> CAP_MAC_ADMIN outside of individual security modules; it is only checked in
> >>> module-specific logic within apparmor, safesetid, selinux, and smack, so the
> >>> meaning was module-specific.
> >>
> >> As we had discussed, We do have a security hook as well:
> >>
> >> https://lore.kernel.org/bpf/20200324180652.GA11855@chromium.org/
> >>
> >> The bpf_prog hook which can check for BPF_PROG_TYPE_LSM and implement
> >> module specific logic for LSM programs. I thougt that was okay?
> >>
> >> Kees was in favor of keeping the CAP_MAC_ADMIN check here:
> >>
> >> https://lore.kernel.org/bpf/202003241133.16C02BE5B@keescook
> >>
> >> If you feel strongly and Kees agrees, we can remove the CAP_MAC_ADMIN
> >> check here, but given that we already have a security hook that meets
> >> the requirements, we probably don't need another one.
> >
> > I would favor removing the CAP_MAC_ADMIN check here, and implementing it in a bpf_prog hook for Smack and AppArmor if they want that.  SELinux would implement its own check in its existing bpf_prog hook.
> >
> The whole notion of one security module calling into another for permission
> to do something still gives me the heebee jeebees, but if more nimble minds
> than mine think this is a good idea I won't nack it.

Well, it's a hook into BPF prog creation, not the BPF LSM specifically,
so that's why I think it's general enough control without it being
directly weird. :)

As far as dropping CAP_MAC_ADMIN, yeah, that should be fine. Creating LSM
BPF programs already requires CAP_SYS_ADMIN, so for SELinux-less systems,
that's likely fine. If we need to change the BPF program creation access
control in the future we can revisit it then.

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution
  2020-03-27 18:59             ` Kees Cook
@ 2020-03-27 19:17               ` KP Singh
  0 siblings, 0 replies; 33+ messages in thread
From: KP Singh @ 2020-03-27 19:17 UTC (permalink / raw)
  To: Kees Cook, James Morris
  Cc: Casey Schaufler, Stephen Smalley, linux-kernel, bpf,
	linux-security-module, Brendan Jackman, Florent Revest,
	Alexei Starovoitov, Daniel Borkmann, Paul Turner, Jann Horn,
	Florent Revest, Brendan Jackman, Greg Kroah-Hartman, Paul Moore

On 27-Mär 11:59, Kees Cook wrote:
> On Fri, Mar 27, 2020 at 09:36:15AM -0700, Casey Schaufler wrote:
> > On 3/27/2020 6:43 AM, Stephen Smalley wrote:
> > > On 3/27/20 8:41 AM, KP Singh wrote:
> > >> On 27-Mär 08:27, Stephen Smalley wrote:
> > >>>>> +        return -EPERM;

[...]

> > >
> > > I would favor removing the CAP_MAC_ADMIN check here, and implementing it in a bpf_prog hook for Smack and AppArmor if they want that.  SELinux would implement its own check in its existing bpf_prog hook.
> > >
> > The whole notion of one security module calling into another for permission
> > to do something still gives me the heebee jeebees, but if more nimble minds
> > than mine think this is a good idea I won't nack it.
> 
> Well, it's a hook into BPF prog creation, not the BPF LSM specifically,
> so that's why I think it's general enough control without it being
> directly weird. :)
> 
> As far as dropping CAP_MAC_ADMIN, yeah, that should be fine. Creating LSM
> BPF programs already requires CAP_SYS_ADMIN, so for SELinux-less systems,
> that's likely fine. If we need to change the BPF program creation access
> control in the future we can revisit it then.

Sounds good, I will send out v8 carrying James and Andri's
Acks/Review tags, CAP_MAC_ADMIN check removed and some other minor
fixes.

- KP

> 
> -- 
> Kees Cook

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, back to index

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-26 14:28 [PATCH bpf-next v7 0/8] MAC and Audit policy using eBPF (KRSI) KP Singh
2020-03-26 14:28 ` [PATCH bpf-next v7 1/8] bpf: Introduce BPF_PROG_TYPE_LSM KP Singh
2020-03-27  0:27   ` James Morris
2020-03-26 14:28 ` [PATCH bpf-next v7 2/8] security: Refactor declaration of LSM hooks KP Singh
2020-03-27  0:28   ` James Morris
2020-03-26 14:28 ` [PATCH bpf-next v7 3/8] bpf: lsm: provide attachment points for BPF LSM programs KP Singh
2020-03-27  0:29   ` James Morris
2020-03-26 14:28 ` [PATCH bpf-next v7 4/8] bpf: lsm: Implement attach, detach and execution KP Singh
2020-03-26 19:12   ` Andrii Nakryiko
2020-03-26 19:39     ` KP Singh
2020-03-27  0:24   ` James Morris
2020-03-27 12:27     ` Stephen Smalley
2020-03-27 12:41       ` KP Singh
2020-03-27 13:43         ` Stephen Smalley
2020-03-27 14:29           ` KP Singh
2020-03-27 16:36           ` Casey Schaufler
2020-03-27 18:59             ` Kees Cook
2020-03-27 19:17               ` KP Singh
2020-03-27  3:12   ` Alexei Starovoitov
2020-03-27 15:06     ` KP Singh
2020-03-26 14:28 ` [PATCH bpf-next v7 5/8] bpf: lsm: Initialize the BPF LSM hooks KP Singh
2020-03-27  0:29   ` James Morris
2020-03-26 14:28 ` [PATCH bpf-next v7 6/8] tools/libbpf: Add support for BPF_PROG_TYPE_LSM KP Singh
2020-03-27  0:30   ` James Morris
2020-03-26 14:28 ` [PATCH bpf-next v7 7/8] bpf: lsm: Add selftests " KP Singh
2020-03-26 19:24   ` Andrii Nakryiko
2020-03-26 19:44     ` KP Singh
2020-03-27  0:31   ` James Morris
2020-03-26 14:28 ` [PATCH bpf-next v7 8/8] bpf: lsm: Add Documentation KP Singh
2020-03-26 19:31   ` Andrii Nakryiko
2020-03-26 20:56     ` KP Singh
2020-03-26 22:01       ` Andrii Nakryiko
2020-03-27  0:33   ` James Morris

Linux-Security-Module Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-security-module/0 linux-security-module/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-security-module linux-security-module/ https://lore.kernel.org/linux-security-module \
		linux-security-module@vger.kernel.org
	public-inbox-index linux-security-module

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-security-module


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git