BPF Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
@ 2019-12-20 15:41 KP Singh
  2019-12-20 15:41 ` [PATCH bpf-next v1 01/13] bpf: Refactor BPF_EVENT context macros to its own header KP Singh
                   ` (16 more replies)
  0 siblings, 17 replies; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:41 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

This patch series is a continuation of the KRSI RFC
(https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/)

# Motivation

Google does rich analysis of runtime security data collected from
internal Linux deployments (corporate devices and servers) 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 proposes a new stackable and privileged LSM which allows
the LSM hooks to be implemented using eBPF. 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 LSM introduces a new eBPF (https://docs.cilium.io/en/v1.6/bpf/)
program type, BPF_PROG_TYPE_LSM, which can only be attached to a LSM
hook.  All LSM hooks are exposed as files in securityfs. Attachment
requires CAP_SYS_ADMIN for loading eBPF programs and CAP_MAC_ADMIN for
modifying MAC policies.

The eBPF programs are passed the same arguments as the LSM hooks and
executed in the body of the hook. If any of the eBPF programs returns an
error (like ENOPERM), the behaviour represented by the hook is denied.

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

# Limitations of RFC v1

In the previous design
(https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/),
the BPF programs received a context which could be queried to retrieve
specific pieces of information using specific helpers.

For example, a program that attaches to the file_mprotect LSM hook and
queries the VMA region could have had the following context:

// Special context for the hook.
struct bpf_mprotect_ctx {
	struct vm_area_struct *vma;
};

and accessed the fields using a hypothetical helper
"bpf_mprotect_vma_get_start:

SEC("lsm/file_mprotect")
int mprotect_audit(bpf_mprotect_ctx *ctx)
{
	unsigned long vm_start = bpf_mprotect_vma_get_start(ctx);
	return 0;
}

or directly read them from the context by updating the verifier to allow
accessing the fields:

int mprotect_audit(bpf_mprotect_ctx *ctx)
{
	unsigned long vm_start = ctx->vma->vm_start;
	return 0;
}

As we prototyped policies based on this design, we realized that this
approach is not general enough. Adding helpers or verifier code for all
usages would imply a high maintenance cost while severely restricting
the instrumentation capabilities which is the key value add of our
eBPF-based LSM.

Feedback from the BPF maintainers at Linux Plumbers also pushed us
towards the following, more general, approach.

# 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:

/* Clang builtin to handle field accesses. */
#define _(P) (__builtin_preserve_access_index(P))

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

// Declare the eBPF program mprotect_audit which attaches to
// to the file_mprotect LSM hook and accepts three arguments.
BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
	    struct vm_area_struct *, vma,
	    unsigned long, reqprot, unsigned long, prot
{
	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 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 previous design
(https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/).

# Distinction from Landlock

We believe there exist two distinct use-cases with distinct set of users:

* Unprivileged processes voluntarily relinquishing privileges with the
  primary users being software developers.

* Flexible privileged (CAP_MAC_ADMIN, CAP_SYS_ADMIN) MAC and Audit with
  the primary users being system policy admins.

These use-cases imply different APIs and trade-offs:

* The unprivileged use case requires defining more stable and custom APIs
  (through opaque contexts and precise helpers).

* Privileged Audit and MAC requires deeper introspection of the kernel
  data structures to maximise the flexibility that can be achieved without
  kernel modification.

Landlock has demonstrated filesystem sandboxes and now Ptrace access
control in its patches which are excellent use cases for an unprivileged
process voluntarily relinquishing privileges.

However, Landlock has expanded its original goal, "towards unprivileged
sandboxing", to being a "low-level framework to build
access-control/audit systems" (https://landlock.io). We feel that the
design and implementation are still driven by the constraints and
trade-offs of the former use-case, and do not provide a satisfactory
solution to the latter.

We also believe that our approach, direct access to common kernel data
structures as with BTF, is inappropriate for unprivileged processes and
probably not a good option for Landlock.

In conclusion, we feel that the design for a privileged LSM and
unprivileged LSM are mutually exclusive and that one cannot be built
"on-top-of" the other. Doing so would limit the capabilities of what can
be done for an LSM that provides flexible audit and MAC capabilities or
provide in-appropriate access to kernel internals to an unprivileged
process.

Furthermore, the Landlock design supports its historical use-case only
when unprivileged eBPF is allowed. This is something that warrants
discussion before an unprivileged LSM that uses eBPF is upstreamed.

# Why not tracepoints or kprobes?

In order to do MAC with tracepoints or kprobes, we would need to
override the return value of the security hook. This is not possible
with tracepoints or call-site kprobes.

Attaching to the return boundary (kretprobe) implies that BPF programs
would always get called after all the other LSM hooks are called and
clobber the pre-existing LSM semantics.

Enforcing MAC policy with an actual LSM helps leverage the verified
semantics of the framework.

# 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 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 (13):
  bpf: Refactor BPF_EVENT context macros to its own header.
  bpf: lsm: Add a skeleton and config options
  bpf: lsm: Introduce types for eBPF based LSM
  bpf: lsm: Allow btf_id based attachment for LSM hooks
  tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM
  bpf: lsm: Init Hooks and create files in securityfs
  bpf: lsm: Implement attach, detach and execution.
  bpf: lsm: Show attached program names in hook read handler.
  bpf: lsm: Add a helper function bpf_lsm_event_output
  bpf: lsm: Handle attachment of the same program
  tools/libbpf: Add bpf_program__attach_lsm
  bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
  bpf: lsm: Add Documentation

 Documentation/security/bpf.rst                |  164 +++
 Documentation/security/index.rst              |    1 +
 MAINTAINERS                                   |   11 +
 include/linux/bpf_event.h                     |   78 ++
 include/linux/bpf_lsm.h                       |   25 +
 include/linux/bpf_types.h                     |    4 +
 include/trace/bpf_probe.h                     |   30 +-
 include/uapi/linux/bpf.h                      |   12 +-
 kernel/bpf/syscall.c                          |   10 +
 kernel/bpf/verifier.c                         |   84 +-
 kernel/trace/bpf_trace.c                      |   24 +-
 security/Kconfig                              |   11 +-
 security/Makefile                             |    2 +
 security/bpf/Kconfig                          |   25 +
 security/bpf/Makefile                         |    7 +
 security/bpf/include/bpf_lsm.h                |   63 +
 security/bpf/include/fs.h                     |   23 +
 security/bpf/include/hooks.h                  | 1015 +++++++++++++++++
 security/bpf/lsm.c                            |  160 +++
 security/bpf/lsm_fs.c                         |  176 +++
 security/bpf/ops.c                            |  224 ++++
 tools/include/uapi/linux/bpf.h                |   12 +-
 tools/lib/bpf/bpf.c                           |    2 +-
 tools/lib/bpf/bpf.h                           |    6 +
 tools/lib/bpf/libbpf.c                        |  163 ++-
 tools/lib/bpf/libbpf.h                        |    4 +
 tools/lib/bpf/libbpf.map                      |    7 +
 tools/lib/bpf/libbpf_probes.c                 |    1 +
 .../bpf/prog_tests/lsm_mprotect_audit.c       |  129 +++
 .../selftests/bpf/progs/lsm_mprotect_audit.c  |   58 +
 30 files changed, 2451 insertions(+), 80 deletions(-)
 create mode 100644 Documentation/security/bpf.rst
 create mode 100644 include/linux/bpf_event.h
 create mode 100644 include/linux/bpf_lsm.h
 create mode 100644 security/bpf/Kconfig
 create mode 100644 security/bpf/Makefile
 create mode 100644 security/bpf/include/bpf_lsm.h
 create mode 100644 security/bpf/include/fs.h
 create mode 100644 security/bpf/include/hooks.h
 create mode 100644 security/bpf/lsm.c
 create mode 100644 security/bpf/lsm_fs.c
 create mode 100644 security/bpf/ops.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
 create mode 100644 tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c

-- 
2.20.1


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

* [PATCH bpf-next v1 01/13] bpf: Refactor BPF_EVENT context macros to its own header.
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
@ 2019-12-20 15:41 ` KP Singh
  2019-12-20 20:10   ` Andrii Nakryiko
  2019-12-20 15:41 ` [PATCH bpf-next v1 02/13] bpf: lsm: Add a skeleton and config options KP Singh
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:41 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

These macros are useful for other program types than tracing.
i.e. KRSI (an upccoming BPF based LSM) which does not use
BPF_PROG_TYPE_TRACE but uses verifiable BTF accesses similar
to raw tracepoints.

Signed-off-by: KP Singh <kpsingh@google.com>
---
 include/linux/bpf_event.h | 78 +++++++++++++++++++++++++++++++++++++++
 include/trace/bpf_probe.h | 30 +--------------
 kernel/trace/bpf_trace.c  | 24 +-----------
 3 files changed, 81 insertions(+), 51 deletions(-)
 create mode 100644 include/linux/bpf_event.h

diff --git a/include/linux/bpf_event.h b/include/linux/bpf_event.h
new file mode 100644
index 000000000000..353eb1f5a3d0
--- /dev/null
+++ b/include/linux/bpf_event.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+
+/*
+ * Copyright (c) 2018 Facebook
+ * Copyright 2019 Google LLC.
+ */
+
+#ifndef _LINUX_BPF_EVENT_H
+#define _LINUX_BPF_EVENT_H
+
+#ifdef CONFIG_BPF_EVENTS
+
+/* cast any integer, pointer, or small struct to u64 */
+#define UINTTYPE(size) \
+	__typeof__(__builtin_choose_expr(size == 1,  (u8)1, \
+		   __builtin_choose_expr(size == 2, (u16)2, \
+		   __builtin_choose_expr(size == 4, (u32)3, \
+		   __builtin_choose_expr(size == 8, (u64)4, \
+					 (void)5)))))
+#define __CAST_TO_U64(x) ({ \
+	typeof(x) __src = (x); \
+	UINTTYPE(sizeof(x)) __dst; \
+	memcpy(&__dst, &__src, sizeof(__dst)); \
+	(u64)__dst; })
+
+#define __CAST0(...) 0
+#define __CAST1(a, ...) __CAST_TO_U64(a)
+#define __CAST2(a, ...) __CAST_TO_U64(a), __CAST1(__VA_ARGS__)
+#define __CAST3(a, ...) __CAST_TO_U64(a), __CAST2(__VA_ARGS__)
+#define __CAST4(a, ...) __CAST_TO_U64(a), __CAST3(__VA_ARGS__)
+#define __CAST5(a, ...) __CAST_TO_U64(a), __CAST4(__VA_ARGS__)
+#define __CAST6(a, ...) __CAST_TO_U64(a), __CAST5(__VA_ARGS__)
+#define __CAST7(a, ...) __CAST_TO_U64(a), __CAST6(__VA_ARGS__)
+#define __CAST8(a, ...) __CAST_TO_U64(a), __CAST7(__VA_ARGS__)
+#define __CAST9(a, ...) __CAST_TO_U64(a), __CAST8(__VA_ARGS__)
+#define __CAST10(a ,...) __CAST_TO_U64(a), __CAST9(__VA_ARGS__)
+#define __CAST11(a, ...) __CAST_TO_U64(a), __CAST10(__VA_ARGS__)
+#define __CAST12(a, ...) __CAST_TO_U64(a), __CAST11(__VA_ARGS__)
+/* tracepoints with more than 12 arguments will hit build error */
+#define CAST_TO_U64(...) CONCATENATE(__CAST, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
+
+#define UINTTYPE(size) \
+	__typeof__(__builtin_choose_expr(size == 1,  (u8)1, \
+		   __builtin_choose_expr(size == 2, (u16)2, \
+		   __builtin_choose_expr(size == 4, (u32)3, \
+		   __builtin_choose_expr(size == 8, (u64)4, \
+					 (void)5)))))
+
+#define UNPACK(...)			__VA_ARGS__
+#define REPEAT_1(FN, DL, X, ...)	FN(X)
+#define REPEAT_2(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_1(FN, DL, __VA_ARGS__)
+#define REPEAT_3(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_2(FN, DL, __VA_ARGS__)
+#define REPEAT_4(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_3(FN, DL, __VA_ARGS__)
+#define REPEAT_5(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_4(FN, DL, __VA_ARGS__)
+#define REPEAT_6(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_5(FN, DL, __VA_ARGS__)
+#define REPEAT_7(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_6(FN, DL, __VA_ARGS__)
+#define REPEAT_8(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_7(FN, DL, __VA_ARGS__)
+#define REPEAT_9(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_8(FN, DL, __VA_ARGS__)
+#define REPEAT_10(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_9(FN, DL, __VA_ARGS__)
+#define REPEAT_11(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_10(FN, DL, __VA_ARGS__)
+#define REPEAT_12(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_11(FN, DL, __VA_ARGS__)
+#define REPEAT(X, FN, DL, ...)		REPEAT_##X(FN, DL, __VA_ARGS__)
+
+#define SARG(X)		u64 arg##X
+#ifdef COPY
+#undef COPY
+#endif
+
+#define COPY(X)		args[X] = arg##X
+#define __DL_COM	(,)
+#define __DL_SEM	(;)
+
+#define __SEQ_0_11	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+
+#endif
+#endif /* _LINUX_BPF_EVENT_H */
+
diff --git a/include/trace/bpf_probe.h b/include/trace/bpf_probe.h
index b04c29270973..5165dbc66098 100644
--- a/include/trace/bpf_probe.h
+++ b/include/trace/bpf_probe.h
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 
+#include <linux/bpf_event.h>
+
 #undef TRACE_SYSTEM_VAR
 
 #ifdef CONFIG_BPF_EVENTS
@@ -27,34 +29,6 @@
 #undef __perf_task
 #define __perf_task(t)	(t)
 
-/* cast any integer, pointer, or small struct to u64 */
-#define UINTTYPE(size) \
-	__typeof__(__builtin_choose_expr(size == 1,  (u8)1, \
-		   __builtin_choose_expr(size == 2, (u16)2, \
-		   __builtin_choose_expr(size == 4, (u32)3, \
-		   __builtin_choose_expr(size == 8, (u64)4, \
-					 (void)5)))))
-#define __CAST_TO_U64(x) ({ \
-	typeof(x) __src = (x); \
-	UINTTYPE(sizeof(x)) __dst; \
-	memcpy(&__dst, &__src, sizeof(__dst)); \
-	(u64)__dst; })
-
-#define __CAST1(a,...) __CAST_TO_U64(a)
-#define __CAST2(a,...) __CAST_TO_U64(a), __CAST1(__VA_ARGS__)
-#define __CAST3(a,...) __CAST_TO_U64(a), __CAST2(__VA_ARGS__)
-#define __CAST4(a,...) __CAST_TO_U64(a), __CAST3(__VA_ARGS__)
-#define __CAST5(a,...) __CAST_TO_U64(a), __CAST4(__VA_ARGS__)
-#define __CAST6(a,...) __CAST_TO_U64(a), __CAST5(__VA_ARGS__)
-#define __CAST7(a,...) __CAST_TO_U64(a), __CAST6(__VA_ARGS__)
-#define __CAST8(a,...) __CAST_TO_U64(a), __CAST7(__VA_ARGS__)
-#define __CAST9(a,...) __CAST_TO_U64(a), __CAST8(__VA_ARGS__)
-#define __CAST10(a,...) __CAST_TO_U64(a), __CAST9(__VA_ARGS__)
-#define __CAST11(a,...) __CAST_TO_U64(a), __CAST10(__VA_ARGS__)
-#define __CAST12(a,...) __CAST_TO_U64(a), __CAST11(__VA_ARGS__)
-/* tracepoints with more than 12 arguments will hit build error */
-#define CAST_TO_U64(...) CONCATENATE(__CAST, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
-
 #undef DECLARE_EVENT_CLASS
 #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print)	\
 static notrace void							\
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index ffc91d4935ac..3fb02fe799ab 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -7,6 +7,7 @@
 #include <linux/slab.h>
 #include <linux/bpf.h>
 #include <linux/bpf_perf_event.h>
+#include <linux/bpf_event.h>
 #include <linux/filter.h>
 #include <linux/uaccess.h>
 #include <linux/ctype.h>
@@ -1461,29 +1462,6 @@ void __bpf_trace_run(struct bpf_prog *prog, u64 *args)
 	rcu_read_unlock();
 }
 
-#define UNPACK(...)			__VA_ARGS__
-#define REPEAT_1(FN, DL, X, ...)	FN(X)
-#define REPEAT_2(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_1(FN, DL, __VA_ARGS__)
-#define REPEAT_3(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_2(FN, DL, __VA_ARGS__)
-#define REPEAT_4(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_3(FN, DL, __VA_ARGS__)
-#define REPEAT_5(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_4(FN, DL, __VA_ARGS__)
-#define REPEAT_6(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_5(FN, DL, __VA_ARGS__)
-#define REPEAT_7(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_6(FN, DL, __VA_ARGS__)
-#define REPEAT_8(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_7(FN, DL, __VA_ARGS__)
-#define REPEAT_9(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_8(FN, DL, __VA_ARGS__)
-#define REPEAT_10(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_9(FN, DL, __VA_ARGS__)
-#define REPEAT_11(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_10(FN, DL, __VA_ARGS__)
-#define REPEAT_12(FN, DL, X, ...)	FN(X) UNPACK DL REPEAT_11(FN, DL, __VA_ARGS__)
-#define REPEAT(X, FN, DL, ...)		REPEAT_##X(FN, DL, __VA_ARGS__)
-
-#define SARG(X)		u64 arg##X
-#define COPY(X)		args[X] = arg##X
-
-#define __DL_COM	(,)
-#define __DL_SEM	(;)
-
-#define __SEQ_0_11	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
-
 #define BPF_TRACE_DEFN_x(x)						\
 	void bpf_trace_run##x(struct bpf_prog *prog,			\
 			      REPEAT(x, SARG, __DL_COM, __SEQ_0_11))	\
-- 
2.20.1


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

* [PATCH bpf-next v1 02/13] bpf: lsm: Add a skeleton and config options
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
  2019-12-20 15:41 ` [PATCH bpf-next v1 01/13] bpf: Refactor BPF_EVENT context macros to its own header KP Singh
@ 2019-12-20 15:41 ` KP Singh
  2020-01-07 21:13   ` James Morris
  2019-12-20 15:41 ` [PATCH bpf-next v1 03/13] bpf: lsm: Introduce types for eBPF based LSM KP Singh
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:41 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

The LSM can be enabled by CONFIG_SECURITY_BPF.
Without CONFIG_SECURITY_BPF_ENFORCE, the LSM will run the
attached eBPF programs but not enforce MAC policy based
on the return value of the attached programs.

Signed-off-by: KP Singh <kpsingh@google.com>
---
 MAINTAINERS           |  7 +++++++
 security/Kconfig      | 11 ++++++-----
 security/Makefile     |  2 ++
 security/bpf/Kconfig  | 25 +++++++++++++++++++++++++
 security/bpf/Makefile |  5 +++++
 security/bpf/lsm.c    | 28 ++++++++++++++++++++++++++++
 6 files changed, 73 insertions(+), 5 deletions(-)
 create mode 100644 security/bpf/Kconfig
 create mode 100644 security/bpf/Makefile
 create mode 100644 security/bpf/lsm.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 8f075b866aaf..3b82d8ff21fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3175,6 +3175,13 @@ S:	Supported
 F:	arch/x86/net/
 X:	arch/x86/net/bpf_jit_comp32.c
 
+BPF SECURITY MODULE
+M:	KP Singh <kpsingh@chromium.org>
+L:	linux-security-module@vger.kernel.org
+L:	bpf@vger.kernel.org
+S:	Maintained
+F:	security/bpf/
+
 BROADCOM B44 10/100 ETHERNET DRIVER
 M:	Michael Chan <michael.chan@broadcom.com>
 L:	netdev@vger.kernel.org
diff --git a/security/Kconfig b/security/Kconfig
index 2a1a2d396228..6f1aab195e7d 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -236,6 +236,7 @@ source "security/tomoyo/Kconfig"
 source "security/apparmor/Kconfig"
 source "security/loadpin/Kconfig"
 source "security/yama/Kconfig"
+source "security/bpf/Kconfig"
 source "security/safesetid/Kconfig"
 source "security/lockdown/Kconfig"
 
@@ -277,11 +278,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 be1dd9d2cb2f..50e6821dd7b7 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_SECURITY_BPF)		+= bpf
 
 # always enable default capabilities
 obj-y					+= commoncap.o
@@ -29,6 +30,7 @@ obj-$(CONFIG_SECURITY_YAMA)		+= yama/
 obj-$(CONFIG_SECURITY_LOADPIN)		+= loadpin/
 obj-$(CONFIG_SECURITY_SAFESETID)       += safesetid/
 obj-$(CONFIG_SECURITY_LOCKDOWN_LSM)	+= lockdown/
+obj-$(CONFIG_SECURITY_BPF)		+= bpf/
 obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o
 
 # Object integrity file lists
diff --git a/security/bpf/Kconfig b/security/bpf/Kconfig
new file mode 100644
index 000000000000..1aaa1340e795
--- /dev/null
+++ b/security/bpf/Kconfig
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC.
+
+config SECURITY_BPF
+	bool "BPF-based MAC and audit policy"
+	depends on SECURITY
+	depends on SECURITYFS
+	depends on BPF
+	depends on BPF_SYSCALL
+	help
+	  This enables instrumentation of the security hooks with
+	  eBPF programs. The LSM creates per-hook files in securityfs to which
+	  eBPF programs can be attached.
+
+	  If you are unsure how to answer this question, answer N.
+
+config SECURITY_BPF_ENFORCE
+	bool "Deny operations based on the evaluation of the attached programs"
+	depends on SECURITY_BPF
+	help
+	  eBPF programs attached to hooks can be used for both auditing and
+	  enforcement. Enabling enforcement implies that the evaluation result
+	  from the attached eBPF programs will allow or deny the operation
+	  guarded by the security hook.
diff --git a/security/bpf/Makefile b/security/bpf/Makefile
new file mode 100644
index 000000000000..26a0ab6f99b7
--- /dev/null
+++ b/security/bpf/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC.
+
+obj-$(CONFIG_SECURITY_BPF) := lsm.o
diff --git a/security/bpf/lsm.c b/security/bpf/lsm.c
new file mode 100644
index 000000000000..fe5c65bbdd45
--- /dev/null
+++ b/security/bpf/lsm.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2019 Google LLC.
+ */
+
+#include <linux/lsm_hooks.h>
+
+static int process_execution(struct linux_binprm *bprm)
+{
+	return 0;
+}
+
+static struct security_hook_list lsm_hooks[] __lsm_ro_after_init = {
+	LSM_HOOK_INIT(bprm_check_security, process_execution),
+};
+
+static int __init lsm_init(void)
+{
+	security_add_hooks(lsm_hooks, ARRAY_SIZE(lsm_hooks), "bpf");
+	pr_info("eBPF and LSM are friends now.\n");
+	return 0;
+}
+
+DEFINE_LSM(bpf) = {
+	.name = "bpf",
+	.init = lsm_init,
+};
-- 
2.20.1


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

* [PATCH bpf-next v1 03/13] bpf: lsm: Introduce types for eBPF based LSM
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
  2019-12-20 15:41 ` [PATCH bpf-next v1 01/13] bpf: Refactor BPF_EVENT context macros to its own header KP Singh
  2019-12-20 15:41 ` [PATCH bpf-next v1 02/13] bpf: lsm: Add a skeleton and config options KP Singh
@ 2019-12-20 15:41 ` KP Singh
  2019-12-20 15:41 ` [PATCH bpf-next v1 04/13] bpf: lsm: Allow btf_id based attachment for LSM hooks KP Singh
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:41 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

A new eBPF program type BPF_PROG_TYPE_LSM with an
expected attach type of BPF_LSM_MAC. An -EINVAL error is returned if an
attachment is currently requested.

Signed-off-by: KP Singh <kpsingh@google.com>
---
 include/linux/bpf_types.h      |  4 ++++
 include/uapi/linux/bpf.h       |  2 ++
 kernel/bpf/syscall.c           |  6 ++++++
 security/bpf/Makefile          |  2 +-
 security/bpf/ops.c             | 14 ++++++++++++++
 tools/include/uapi/linux/bpf.h |  2 ++
 6 files changed, 29 insertions(+), 1 deletion(-)
 create mode 100644 security/bpf/ops.c

diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
index 93740b3614d7..5f48161529b4 100644
--- a/include/linux/bpf_types.h
+++ b/include/linux/bpf_types.h
@@ -65,6 +65,10 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_LIRC_MODE2, lirc_mode2,
 BPF_PROG_TYPE(BPF_PROG_TYPE_SK_REUSEPORT, sk_reuseport,
 	      struct sk_reuseport_md, struct sk_reuseport_kern)
 #endif
+#ifdef CONFIG_SECURITY_BPF
+BPF_PROG_TYPE(BPF_PROG_TYPE_LSM, lsm,
+	       void *, void *)
+#endif
 
 BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops)
 BPF_MAP_TYPE(BPF_MAP_TYPE_PERCPU_ARRAY, percpu_array_map_ops)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index dbbcf0b02970..fc64ae865526 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -174,6 +174,7 @@ enum bpf_prog_type {
 	BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
 	BPF_PROG_TYPE_CGROUP_SOCKOPT,
 	BPF_PROG_TYPE_TRACING,
+	BPF_PROG_TYPE_LSM,
 };
 
 enum bpf_attach_type {
@@ -203,6 +204,7 @@ enum bpf_attach_type {
 	BPF_TRACE_RAW_TP,
 	BPF_TRACE_FENTRY,
 	BPF_TRACE_FEXIT,
+	BPF_LSM_MAC,
 	__MAX_BPF_ATTACH_TYPE
 };
 
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index e3461ec59570..5a773fc6f9f5 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2096,6 +2096,9 @@ static int bpf_prog_attach(const union bpf_attr *attr)
 	case BPF_LIRC_MODE2:
 		ptype = BPF_PROG_TYPE_LIRC_MODE2;
 		break;
+	case BPF_LSM_MAC:
+		ptype = BPF_PROG_TYPE_LSM;
+		break;
 	case BPF_FLOW_DISSECTOR:
 		ptype = BPF_PROG_TYPE_FLOW_DISSECTOR;
 		break;
@@ -2127,6 +2130,9 @@ static int bpf_prog_attach(const union bpf_attr *attr)
 	case BPF_PROG_TYPE_LIRC_MODE2:
 		ret = lirc_prog_attach(attr, prog);
 		break;
+	case BPF_PROG_TYPE_LSM:
+		ret = -EINVAL;
+		break;
 	case BPF_PROG_TYPE_FLOW_DISSECTOR:
 		ret = skb_flow_dissector_bpf_prog_attach(attr, prog);
 		break;
diff --git a/security/bpf/Makefile b/security/bpf/Makefile
index 26a0ab6f99b7..c78a8a056e7e 100644
--- a/security/bpf/Makefile
+++ b/security/bpf/Makefile
@@ -2,4 +2,4 @@
 #
 # Copyright 2019 Google LLC.
 
-obj-$(CONFIG_SECURITY_BPF) := lsm.o
+obj-$(CONFIG_SECURITY_BPF) := lsm.o ops.o
diff --git a/security/bpf/ops.c b/security/bpf/ops.c
new file mode 100644
index 000000000000..2fa3ebdf598d
--- /dev/null
+++ b/security/bpf/ops.c
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2019 Google LLC.
+ */
+
+#include <linux/filter.h>
+#include <linux/bpf.h>
+
+const struct bpf_prog_ops lsm_prog_ops = {
+};
+
+const struct bpf_verifier_ops lsm_verifier_ops = {
+};
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index dbbcf0b02970..fc64ae865526 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -174,6 +174,7 @@ enum bpf_prog_type {
 	BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
 	BPF_PROG_TYPE_CGROUP_SOCKOPT,
 	BPF_PROG_TYPE_TRACING,
+	BPF_PROG_TYPE_LSM,
 };
 
 enum bpf_attach_type {
@@ -203,6 +204,7 @@ enum bpf_attach_type {
 	BPF_TRACE_RAW_TP,
 	BPF_TRACE_FENTRY,
 	BPF_TRACE_FEXIT,
+	BPF_LSM_MAC,
 	__MAX_BPF_ATTACH_TYPE
 };
 
-- 
2.20.1


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

* [PATCH bpf-next v1 04/13] bpf: lsm: Allow btf_id based attachment for LSM hooks
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (2 preceding siblings ...)
  2019-12-20 15:41 ` [PATCH bpf-next v1 03/13] bpf: lsm: Introduce types for eBPF based LSM KP Singh
@ 2019-12-20 15:41 ` KP Singh
  2019-12-23 23:54   ` Andrii Nakryiko
  2019-12-20 15:42 ` [PATCH bpf-next v1 05/13] tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM KP Singh
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:41 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

Refactor and re-use most of the logic for BPF_PROG_TYPE_TRACING with a few
changes.

- The LSM hook BTF types are prefixed with "lsm_btf_"
- These types do not need the first (void *) pointer argument. The verifier
  only looks for this argument if prod->aux->attach_btf_trace is set.

Signed-off-by: KP Singh <kpsingh@google.com>
---
 kernel/bpf/syscall.c  |  1 +
 kernel/bpf/verifier.c | 83 ++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 80 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 5a773fc6f9f5..4fcaf6042c07 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1642,6 +1642,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:
 		if (btf_id > BTF_MAX_TYPE)
 			return -EINVAL;
 		break;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index a0482e1c4a77..0d1231d9c1ef 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -9504,7 +9504,71 @@ static void print_verification_stats(struct bpf_verifier_env *env)
 		env->peak_states, env->longest_mark_read_walk);
 }
 
-static int check_attach_btf_id(struct bpf_verifier_env *env)
+/*
+ * LSM hooks have a typedef associated with them. The BTF information for this
+ * type is used by the verifier to validate memory accesses made by the
+ * attached information.
+ *
+ * For example the:
+ *
+ *	int bprm_check_security(struct linux_binprm *brpm)
+ *
+ * has the following typedef:
+ *
+ *	typedef int (*lsm_btf_bprm_check_security)(struct linux_binprm *bprm);
+ */
+#define BTF_LSM_PREFIX "lsm_btf_"
+
+static inline int check_attach_btf_id_lsm(struct bpf_verifier_env *env)
+{
+	struct bpf_prog *prog = env->prog;
+	u32 btf_id = prog->aux->attach_btf_id;
+	const struct btf_type *t;
+	const char *tname;
+
+	if (!btf_id) {
+		verbose(env, "LSM programs must provide btf_id\n");
+		return -EINVAL;
+	}
+
+	t = btf_type_by_id(btf_vmlinux, btf_id);
+	if (!t) {
+		verbose(env, "attach_btf_id %u is invalid\n", btf_id);
+		return -EINVAL;
+	}
+
+	tname = btf_name_by_offset(btf_vmlinux, t->name_off);
+	if (!tname) {
+		verbose(env, "attach_btf_id %u doesn't have a name\n", btf_id);
+		return -EINVAL;
+	}
+
+	if (!btf_type_is_typedef(t)) {
+		verbose(env, "attach_btf_id %u is not a typedef\n", btf_id);
+		return -EINVAL;
+	}
+	if (strncmp(BTF_LSM_PREFIX, tname, sizeof(BTF_LSM_PREFIX) - 1)) {
+		verbose(env, "attach_btf_id %u points to wrong type name %s\n",
+			btf_id, tname);
+		return -EINVAL;
+	}
+
+	t = btf_type_by_id(btf_vmlinux, t->type);
+	/* should never happen in valid vmlinux build */
+	if (!btf_type_is_ptr(t))
+		return -EINVAL;
+	t = btf_type_by_id(btf_vmlinux, t->type);
+	/* should never happen in valid vmlinux build */
+	if (!btf_type_is_func_proto(t))
+		return -EINVAL;
+
+	tname += sizeof(BTF_LSM_PREFIX) - 1;
+	prog->aux->attach_func_name = tname;
+	prog->aux->attach_func_proto = t;
+	return 0;
+}
+
+static int check_attach_btf_id_tracing(struct bpf_verifier_env *env)
 {
 	struct bpf_prog *prog = env->prog;
 	struct bpf_prog *tgt_prog = prog->aux->linked_prog;
@@ -9519,9 +9583,6 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
 	long addr;
 	u64 key;
 
-	if (prog->type != BPF_PROG_TYPE_TRACING)
-		return 0;
-
 	if (!btf_id) {
 		verbose(env, "Tracing programs must provide btf_id\n");
 		return -EINVAL;
@@ -9659,6 +9720,20 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
 	}
 }
 
+static int check_attach_btf_id(struct bpf_verifier_env *env)
+{
+	struct bpf_prog *prog = env->prog;
+
+	switch (prog->type) {
+	case BPF_PROG_TYPE_TRACING:
+		return check_attach_btf_id_tracing(env);
+	case BPF_PROG_TYPE_LSM:
+		return check_attach_btf_id_lsm(env);
+	default:
+		return 0;
+	}
+}
+
 int bpf_check(struct bpf_prog **prog, union bpf_attr *attr,
 	      union bpf_attr __user *uattr)
 {
-- 
2.20.1


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

* [PATCH bpf-next v1 05/13] tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (3 preceding siblings ...)
  2019-12-20 15:41 ` [PATCH bpf-next v1 04/13] bpf: lsm: Allow btf_id based attachment for LSM hooks KP Singh
@ 2019-12-20 15:42 ` KP Singh
  2019-12-24  0:07   ` Andrii Nakryiko
  2019-12-20 15:42 ` [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs KP Singh
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:42 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

Update the libbpf library with functionality to load and
attach a program type BPF_PROG_TYPE_LSM, currently with
only one expected attach type BPF_LSM_MAC.

Signed-off-by: KP Singh <kpsingh@google.com>
---
 tools/lib/bpf/bpf.c           |  2 +-
 tools/lib/bpf/bpf.h           |  6 +++++
 tools/lib/bpf/libbpf.c        | 44 +++++++++++++++++++++--------------
 tools/lib/bpf/libbpf.h        |  2 ++
 tools/lib/bpf/libbpf.map      |  6 +++++
 tools/lib/bpf/libbpf_probes.c |  1 +
 6 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 98596e15390f..9c6fb083f7de 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -228,7 +228,7 @@ 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_TRACING) {
+	if (needs_btf_attach(attr.prog_type)) {
 		attr.attach_btf_id = load_attr->attach_btf_id;
 		attr.attach_prog_fd = load_attr->attach_prog_fd;
 	} else {
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 3c791fa8e68e..df2a00ff349f 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -177,6 +177,12 @@ LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
 				 __u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
 				 __u64 *probe_offset, __u64 *probe_addr);
 
+static inline bool needs_btf_attach(enum bpf_prog_type prog_type)
+{
+	return (prog_type == BPF_PROG_TYPE_TRACING ||
+		prog_type == BPF_PROG_TYPE_LSM);
+}
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index b20f82e58989..b0b27d8e5a37 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -3738,7 +3738,7 @@ 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_TRACING) {
+	if (needs_btf_attach(prog->type)) {
 		load_attr.attach_prog_fd = prog->attach_prog_fd;
 		load_attr.attach_btf_id = prog->attach_btf_id;
 	} else {
@@ -3983,7 +3983,7 @@ __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
 
 		bpf_program__set_type(prog, prog_type);
 		bpf_program__set_expected_attach_type(prog, attach_type);
-		if (prog_type == BPF_PROG_TYPE_TRACING) {
+		if (needs_btf_attach(prog_type)) {
 			err = libbpf_find_attach_btf_id(prog->section_name,
 							attach_type,
 							attach_prog_fd);
@@ -4933,6 +4933,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);
@@ -5009,6 +5010,8 @@ static const struct {
 	BPF_PROG_SEC("lwt_out",			BPF_PROG_TYPE_LWT_OUT),
 	BPF_PROG_SEC("lwt_xmit",		BPF_PROG_TYPE_LWT_XMIT),
 	BPF_PROG_SEC("lwt_seg6local",		BPF_PROG_TYPE_LWT_SEG6LOCAL),
+	BPF_PROG_BTF("lsm/",			BPF_PROG_TYPE_LSM,
+						BPF_LSM_MAC),
 	BPF_APROG_SEC("cgroup_skb/ingress",	BPF_PROG_TYPE_CGROUP_SKB,
 						BPF_CGROUP_INET_INGRESS),
 	BPF_APROG_SEC("cgroup_skb/egress",	BPF_PROG_TYPE_CGROUP_SKB,
@@ -5119,32 +5122,39 @@ int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
 	return -ESRCH;
 }
 
-#define BTF_PREFIX "btf_trace_"
+static inline int __btf__typdef_with_prefix(struct btf *btf, const char *name,
+					    const char *prefix)
+{
+
+	size_t prefix_len = strlen(prefix);
+	char btf_type_name[128];
+
+	strcpy(btf_type_name, prefix);
+	strncat(btf_type_name, name, sizeof(btf_type_name) - (prefix_len + 1));
+	return btf__find_by_name_kind(btf, btf_type_name, BTF_KIND_TYPEDEF);
+}
+
+#define BTF_TRACE_PREFIX "btf_trace_"
+#define BTF_LSM_PREFIX "lsm_btf_"
+
 int libbpf_find_vmlinux_btf_id(const char *name,
 			       enum bpf_attach_type attach_type)
 {
 	struct btf *btf = bpf_core_find_kernel_btf();
-	char raw_tp_btf[128] = BTF_PREFIX;
-	char *dst = raw_tp_btf + sizeof(BTF_PREFIX) - 1;
-	const char *btf_name;
 	int err = -EINVAL;
-	__u32 kind;
 
 	if (IS_ERR(btf)) {
 		pr_warn("vmlinux BTF is not found\n");
 		return -EINVAL;
 	}
 
-	if (attach_type == BPF_TRACE_RAW_TP) {
-		/* prepend "btf_trace_" prefix per kernel convention */
-		strncat(dst, name, sizeof(raw_tp_btf) - sizeof(BTF_PREFIX));
-		btf_name = raw_tp_btf;
-		kind = BTF_KIND_TYPEDEF;
-	} else {
-		btf_name = name;
-		kind = BTF_KIND_FUNC;
-	}
-	err = btf__find_by_name_kind(btf, btf_name, kind);
+	if (attach_type == BPF_TRACE_RAW_TP)
+		err = __btf__typdef_with_prefix(btf, name, BTF_TRACE_PREFIX);
+	else if (attach_type == BPF_LSM_MAC)
+		err = __btf__typdef_with_prefix(btf, name, BTF_LSM_PREFIX);
+	else
+		err = btf__find_by_name_kind(btf, name, BTF_KIND_FUNC);
+
 	btf__free(btf);
 	return err;
 }
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 0dbf4bfba0c4..9cd69d602c82 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -332,6 +332,7 @@ LIBBPF_API int bpf_program__set_sched_act(struct bpf_program *prog);
 LIBBPF_API int bpf_program__set_xdp(struct bpf_program *prog);
 LIBBPF_API int bpf_program__set_perf_event(struct bpf_program *prog);
 LIBBPF_API int bpf_program__set_tracing(struct bpf_program *prog);
+LIBBPF_API int bpf_program__set_lsm(struct bpf_program *prog);
 
 LIBBPF_API enum bpf_prog_type bpf_program__get_type(struct bpf_program *prog);
 LIBBPF_API void bpf_program__set_type(struct bpf_program *prog,
@@ -352,6 +353,7 @@ 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);
 LIBBPF_API bool bpf_program__is_perf_event(const struct bpf_program *prog);
 LIBBPF_API bool bpf_program__is_tracing(const struct bpf_program *prog);
+LIBBPF_API bool bpf_program__is_lsm(const struct bpf_program *prog);
 
 /*
  * No need for __attribute__((packed)), all members of 'bpf_map_def'
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 8ddc2c40e482..3d396149755d 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -208,3 +208,9 @@ LIBBPF_0.0.6 {
 		btf__find_by_name_kind;
 		libbpf_find_vmlinux_btf_id;
 } LIBBPF_0.0.5;
+
+LIBBPF_0.0.7 {
+	global:
+		bpf_program__is_lsm;
+		bpf_program__set_lsm;
+} LIBBPF_0.0.6;
diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
index a9eb8b322671..203b4ecf7a0b 100644
--- a/tools/lib/bpf/libbpf_probes.c
+++ b/tools/lib/bpf/libbpf_probes.c
@@ -103,6 +103,7 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
 	case BPF_PROG_TYPE_CGROUP_SYSCTL:
 	case BPF_PROG_TYPE_CGROUP_SOCKOPT:
 	case BPF_PROG_TYPE_TRACING:
+	case BPF_PROG_TYPE_LSM:
 	default:
 		break;
 	}
-- 
2.20.1


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

* [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (4 preceding siblings ...)
  2019-12-20 15:42 ` [PATCH bpf-next v1 05/13] tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM KP Singh
@ 2019-12-20 15:42 ` KP Singh
  2019-12-24  6:28   ` Andrii Nakryiko
  2020-01-07 21:22   ` James Morris
  2019-12-20 15:42 ` [PATCH bpf-next v1 07/13] bpf: lsm: Implement attach, detach and execution KP Singh
                   ` (10 subsequent siblings)
  16 siblings, 2 replies; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:42 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

The LSM creates files in securityfs for each hook registered with the
LSM.

    /sys/kernel/security/bpf/<h_name>

The list of LSM hooks are maintained in an internal header "hooks.h"
Eventually, this list should either be defined collectively in
include/linux/lsm_hooks.h or auto-generated from it.

* Creation of a file for the hook in the securityfs.
* Allocation of a bpf_lsm_hook data structure which stores
  a pointer to the dentry of the newly created file in securityfs.
* Creation of a typedef for the hook so that BTF information
  can be generated for the LSM hooks to:

  - Make them "Compile Once, Run Everywhere".
  - Pass the right arguments when the attached programs are run.
  - Verify the accesses made by the program by using the BTF
    information.

Signed-off-by: KP Singh <kpsingh@google.com>
---
 include/linux/bpf_lsm.h        |   12 +
 security/bpf/Makefile          |    4 +-
 security/bpf/include/bpf_lsm.h |   63 ++
 security/bpf/include/fs.h      |   23 +
 security/bpf/include/hooks.h   | 1015 ++++++++++++++++++++++++++++++++
 security/bpf/lsm.c             |  138 ++++-
 security/bpf/lsm_fs.c          |   82 +++
 7 files changed, 1333 insertions(+), 4 deletions(-)
 create mode 100644 include/linux/bpf_lsm.h
 create mode 100644 security/bpf/include/bpf_lsm.h
 create mode 100644 security/bpf/include/fs.h
 create mode 100644 security/bpf/include/hooks.h
 create mode 100644 security/bpf/lsm_fs.c

diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h
new file mode 100644
index 000000000000..76f81e642dc2
--- /dev/null
+++ b/include/linux/bpf_lsm.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _LINUX_BPF_LSM_H
+#define _LINUX_BPF_LSM_H
+
+#include <linux/bpf.h>
+
+#ifdef CONFIG_SECURITY_BPF
+extern int bpf_lsm_fs_initialized;
+#endif /* CONFIG_SECURITY_BPF */
+
+#endif /* _LINUX_BPF_LSM_H */
diff --git a/security/bpf/Makefile b/security/bpf/Makefile
index c78a8a056e7e..8bb5bfc936ee 100644
--- a/security/bpf/Makefile
+++ b/security/bpf/Makefile
@@ -2,4 +2,6 @@
 #
 # Copyright 2019 Google LLC.
 
-obj-$(CONFIG_SECURITY_BPF) := lsm.o ops.o
+obj-$(CONFIG_SECURITY_BPF) := lsm.o ops.o lsm_fs.o
+
+ccflags-y := -I$(srctree)/security/bpf -I$(srctree)/security/bpf/include
diff --git a/security/bpf/include/bpf_lsm.h b/security/bpf/include/bpf_lsm.h
new file mode 100644
index 000000000000..f2409d75d932
--- /dev/null
+++ b/security/bpf/include/bpf_lsm.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _BPF_LSM_H
+#define _BPF_LSM_H
+
+#include <linux/bpf_event.h>
+#include <linux/filter.h>
+#include <linux/bpf.h>
+#include "fs.h"
+
+/*
+ * This enum indexes one of the LSM hooks defined in hooks.h.
+ * Each value of the enum is defined as <hook>_type.
+ */
+enum lsm_hook_type {
+	#define BPF_LSM_HOOK(hook, ...) hook##_type,
+	#include "hooks.h"
+	#undef BPF_LSM_HOOK
+	__MAX_LSM_HOOK_TYPE,
+};
+
+/*
+ * This data structure contains all the information required by the LSM for a
+ * a hook.
+ */
+struct bpf_lsm_hook {
+	/*
+	 * The name of the security hook, a file with this name will be created
+	 * in the securityfs.
+	 */
+	const char *name;
+	/*
+	 * The type of the LSM hook, the LSM uses this to index the list of the
+	 * hooks to run the eBPF programs that may have been attached.
+	 */
+	enum lsm_hook_type h_type;
+	/*
+	 * The dentry of the file created in securityfs.
+	 */
+	struct dentry *h_dentry;
+	/*
+	 * The mutex must be held when updating the progs attached to the hook.
+	 */
+	struct mutex mutex;
+	/*
+	 * The eBPF programs that are attached to this hook.
+	 */
+	struct bpf_prog_array __rcu *progs;
+	/*
+	 * The actual implementation of the hook. This also ensures that
+	 * BTF information is generated for the hook.
+	 */
+	void *btf_hook_func;
+};
+
+extern struct bpf_lsm_hook bpf_lsm_hooks_list[];
+
+#define lsm_for_each_hook(hook) \
+	for ((hook) = &bpf_lsm_hooks_list[0]; \
+	     (hook) < &bpf_lsm_hooks_list[__MAX_LSM_HOOK_TYPE]; \
+	     (hook)++)
+
+#endif /* _BPF_LSM_H */
diff --git a/security/bpf/include/fs.h b/security/bpf/include/fs.h
new file mode 100644
index 000000000000..9d87a0b2bf41
--- /dev/null
+++ b/security/bpf/include/fs.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Copyright 2019 Google LLC.
+ */
+
+#ifndef _BPF_LSM_FS_H
+#define _BPF_LSM_FS_H
+
+#include <linux/bpf.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+
+bool is_bpf_lsm_hook_file(struct file *f);
+
+/*
+ * The name of the directory created in securityfs
+ *
+ *	/sys/kernel/security/<dir_name>
+ */
+#define BPF_LSM_SFS_NAME "bpf"
+
+#endif /* _BPF_LSM_FS_H */
diff --git a/security/bpf/include/hooks.h b/security/bpf/include/hooks.h
new file mode 100644
index 000000000000..c91c6fae8058
--- /dev/null
+++ b/security/bpf/include/hooks.h
@@ -0,0 +1,1015 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Copyright 2019 Google LLC.
+ *
+ * The hooks for the KRSI LSM are declared in this file.
+ *
+ * This header MUST NOT be included directly and is included inline
+ * for generating various data structurs for the hooks using the
+ * following pattern:
+ *
+ * #define BPF_LSM_HOOK RET NAME(PROTO);
+ * #include "hooks.h"
+ * #undef BPF_LSM_HOOK
+ *
+ * Format:
+ *
+ *	BPF_LSM_HOOK(NAME, RET, PROTO, ARGS)
+ *
+ */
+#define BPF_LSM_ARGS(args...) args
+
+BPF_LSM_HOOK(binder_set_context_mgr,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *mgr),
+	     BPF_LSM_ARGS(mgr))
+BPF_LSM_HOOK(binder_transaction,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *from, struct task_struct *to),
+	     BPF_LSM_ARGS(from, to))
+BPF_LSM_HOOK(binder_transfer_binder,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *from, struct task_struct *to),
+	     BPF_LSM_ARGS(from, to))
+BPF_LSM_HOOK(binder_transfer_file,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *from, struct task_struct *to,
+			  struct file *file),
+	     BPF_LSM_ARGS(from, to, file))
+BPF_LSM_HOOK(ptrace_access_check,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *child, unsigned int mode),
+	     BPF_LSM_ARGS(child, mode))
+BPF_LSM_HOOK(ptrace_traceme,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *parent),
+	     BPF_LSM_ARGS(parent))
+BPF_LSM_HOOK(capget,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *target, kernel_cap_t *effective,
+		     kernel_cap_t *inheritable, kernel_cap_t *permitted),
+	     BPF_LSM_ARGS(target, effective, inheritable, permitted))
+BPF_LSM_HOOK(capset,
+	 int,
+	 BPF_LSM_ARGS(struct cred *new, const struct cred *old,
+		     const kernel_cap_t *effective,
+		     const kernel_cap_t *inheritable,
+		     const kernel_cap_t *permitted),
+	 BPF_LSM_ARGS(new, old, effective, inheritable, permitted))
+BPF_LSM_HOOK(capable,
+	     int,
+	     BPF_LSM_ARGS(const struct cred *cred, struct user_namespace *ns,
+	      int cap, unsigned int opts),
+	     BPF_LSM_ARGS(cred, ns, cap, opts))
+BPF_LSM_HOOK(quotactl,
+	     int,
+	     BPF_LSM_ARGS(int cmds, int type, int id, struct super_block *sb),
+	     BPF_LSM_ARGS(cmds, type, id, sb))
+BPF_LSM_HOOK(quota_on,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry),
+	     BPF_LSM_ARGS(dentry))
+BPF_LSM_HOOK(syslog,
+	     int,
+	     BPF_LSM_ARGS(int type),
+	     BPF_LSM_ARGS(type))
+BPF_LSM_HOOK(settime,
+	     int,
+	     BPF_LSM_ARGS(const struct timespec64 *ts,
+			  const struct timezone *tz),
+	     BPF_LSM_ARGS(ts, tz))
+BPF_LSM_HOOK(vm_enough_memory,
+	     int,
+	     BPF_LSM_ARGS(struct mm_struct *mm, long pages),
+	     BPF_LSM_ARGS(mm, pages))
+BPF_LSM_HOOK(bprm_set_creds,
+	     int,
+	     BPF_LSM_ARGS(struct linux_binprm *bprm),
+	     BPF_LSM_ARGS(bprm))
+BPF_LSM_HOOK(bprm_check_security,
+	     int,
+	     BPF_LSM_ARGS(struct linux_binprm *bprm),
+	     BPF_LSM_ARGS(bprm))
+BPF_LSM_HOOK(bprm_committing_creds,
+	     void,
+	     BPF_LSM_ARGS(struct linux_binprm *bprm),
+	     BPF_LSM_ARGS(bprm))
+BPF_LSM_HOOK(bprm_committed_creds,
+	     void,
+	     BPF_LSM_ARGS(struct linux_binprm *bprm),
+	     BPF_LSM_ARGS(bprm))
+BPF_LSM_HOOK(fs_context_dup,
+	     int,
+	     BPF_LSM_ARGS(struct fs_context *fc, struct fs_context *src_sc),
+	     BPF_LSM_ARGS(fc, src_sc))
+BPF_LSM_HOOK(fs_context_parse_param,
+	     int,
+	     BPF_LSM_ARGS(struct fs_context *fc, struct fs_parameter *param),
+	     BPF_LSM_ARGS(fc, param))
+BPF_LSM_HOOK(sb_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(struct super_block *sb),
+	     BPF_LSM_ARGS(sb))
+BPF_LSM_HOOK(sb_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct super_block *sb),
+	     BPF_LSM_ARGS(sb))
+BPF_LSM_HOOK(sb_free_mnt_opts,
+	     void,
+	     BPF_LSM_ARGS(void *mnt_opts),
+	     BPF_LSM_ARGS(mnt_opts))
+BPF_LSM_HOOK(sb_eat_lsm_opts,
+	     int,
+	     BPF_LSM_ARGS(char *orig, void **mnt_opts),
+	     BPF_LSM_ARGS(orig, mnt_opts))
+BPF_LSM_HOOK(sb_remount,
+	     int,
+	     BPF_LSM_ARGS(struct super_block *sb, void *mnt_opts),
+	     BPF_LSM_ARGS(sb, mnt_opts))
+BPF_LSM_HOOK(sb_kern_mount,
+	     int,
+	     BPF_LSM_ARGS(struct super_block *sb),
+	     BPF_LSM_ARGS(sb))
+BPF_LSM_HOOK(sb_show_options,
+	     int,
+	     BPF_LSM_ARGS(struct seq_file *m, struct super_block *sb),
+	     BPF_LSM_ARGS(m, sb))
+BPF_LSM_HOOK(sb_statfs,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry),
+	     BPF_LSM_ARGS(dentry))
+BPF_LSM_HOOK(sb_mount,
+	     int,
+	     BPF_LSM_ARGS(const char *dev_name, const struct path *path,
+		      const char *type, unsigned long flags, void *data),
+	     BPF_LSM_ARGS(dev_name, path, type, flags, data))
+BPF_LSM_HOOK(sb_umount,
+	     int,
+	     BPF_LSM_ARGS(struct vfsmount *mnt, int flags),
+	     BPF_LSM_ARGS(mnt, flags))
+BPF_LSM_HOOK(sb_pivotroot,
+	     int,
+	     BPF_LSM_ARGS(const struct path *old_path,
+			  const struct path *new_path),
+	     BPF_LSM_ARGS(old_path, new_path))
+BPF_LSM_HOOK(sb_set_mnt_opts,
+	     int,
+	     BPF_LSM_ARGS(struct super_block *sb, void *mnt_opts,
+		     unsigned long kern_flags, unsigned long *set_kern_flags),
+	     BPF_LSM_ARGS(sb, mnt_opts, kern_flags, set_kern_flags))
+BPF_LSM_HOOK(sb_clone_mnt_opts,
+	     int,
+	     BPF_LSM_ARGS(const struct super_block *oldsb,
+			  struct super_block *newsb, unsigned long kern_flags,
+			  unsigned long *set_kern_flags),
+	     BPF_LSM_ARGS(oldsb, newsb, kern_flags, set_kern_flags))
+BPF_LSM_HOOK(sb_add_mnt_opt,
+	     int,
+	     BPF_LSM_ARGS(const char *option, const char *val, int len,
+		     void **mnt_opts),
+	     BPF_LSM_ARGS(option, val, len, mnt_opts))
+BPF_LSM_HOOK(move_mount,
+	     int,
+	     BPF_LSM_ARGS(const struct path *from_path,
+			  const struct path *to_path),
+	     BPF_LSM_ARGS(from_path, to_path))
+BPF_LSM_HOOK(dentry_init_security,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry, int mode,
+			  const struct qstr *name,
+		     void **ctx, u32 *ctxlen),
+	     BPF_LSM_ARGS(dentry, mode, name, ctx, ctxlen))
+BPF_LSM_HOOK(dentry_create_files_as,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry, int mode, struct qstr *name,
+		     const struct cred *old, struct cred *new),
+	     BPF_LSM_ARGS(dentry, mode, name, old, new))
+
+#ifdef CONFIG_SECURITY_PATH
+BPF_LSM_HOOK(path_unlink,
+	     int,
+	     BPF_LSM_ARGS(const struct path *dir, struct dentry *dentry),
+	     BPF_LSM_ARGS(dir, dentry))
+BPF_LSM_HOOK(path_mkdir,
+	     int,
+	     BPF_LSM_ARGS(const struct path *dir, struct dentry *dentry,
+		     umode_t mode),
+	     BPF_LSM_ARGS(dir, dentry, mode))
+BPF_LSM_HOOK(path_rmdir,
+	     int,
+	     BPF_LSM_ARGS(const struct path *dir, struct dentry *dentry),
+	     BPF_LSM_ARGS(dir, dentry))
+BPF_LSM_HOOK(path_mknod,
+	     int,
+	     BPF_LSM_ARGS(const struct path *dir, struct dentry *dentry,
+			  umode_t mode,
+		     unsigned int dev),
+	     BPF_LSM_ARGS(dir, dentry, mode, dev))
+BPF_LSM_HOOK(path_truncate,
+	     int,
+	     BPF_LSM_ARGS(const struct path *path),
+	     BPF_LSM_ARGS(path))
+BPF_LSM_HOOK(path_symlink,
+	     int,
+	     BPF_LSM_ARGS(const struct path *dir, struct dentry *dentry,
+		     const char *old_name),
+	     BPF_LSM_ARGS(dir, dentry, old_name))
+BPF_LSM_HOOK(path_link,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *old_dentry, const struct path *new_dir,
+		     struct dentry *new_dentry),
+	     BPF_LSM_ARGS(old_dentry, new_dir, new_dentry))
+BPF_LSM_HOOK(path_rename,
+	     int,
+	     BPF_LSM_ARGS(const struct path *old_dir, struct dentry *old_dentry,
+		     const struct path *new_dir, struct dentry *new_dentry),
+	     BPF_LSM_ARGS(old_dir, old_dentry, new_dir, new_dentry))
+BPF_LSM_HOOK(path_chmod,
+	     int,
+	     BPF_LSM_ARGS(const struct path *path, umode_t mode),
+	     BPF_LSM_ARGS(path, mode))
+BPF_LSM_HOOK(path_chown,
+	     int,
+	     BPF_LSM_ARGS(const struct path *path, kuid_t uid, kgid_t gid),
+	     BPF_LSM_ARGS(path, uid, gid))
+BPF_LSM_HOOK(path_chroot,
+	     int,
+	     BPF_LSM_ARGS(const struct path *path),
+	     BPF_LSM_ARGS(path))
+#endif /* CONFIG_SECURITY_PATH */
+
+BPF_LSM_HOOK(path_notify,
+	     int,
+	     BPF_LSM_ARGS(const struct path *path, u64 mask,
+			  unsigned int obj_type),
+	     BPF_LSM_ARGS(path, mask, obj_type))
+BPF_LSM_HOOK(inode_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(struct inode *inode),
+	     BPF_LSM_ARGS(inode))
+BPF_LSM_HOOK(inode_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct inode *inode),
+	     BPF_LSM_ARGS(inode))
+BPF_LSM_HOOK(inode_init_security,
+	     int,
+	     BPF_LSM_ARGS(struct inode *inode, struct inode *dir,
+		     const struct qstr *qstr, const char **name, void **value,
+		     size_t *len),
+	     BPF_LSM_ARGS(inode, dir, qstr, name, value, len))
+BPF_LSM_HOOK(inode_create,
+	     int,
+	     BPF_LSM_ARGS(struct inode *dir, struct dentry *dentry,
+			  umode_t mode),
+	     BPF_LSM_ARGS(dir, dentry, mode))
+BPF_LSM_HOOK(inode_link,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *old_dentry, struct inode *dir,
+		     struct dentry *new_dentry),
+	     BPF_LSM_ARGS(old_dentry, dir, new_dentry))
+BPF_LSM_HOOK(inode_unlink,
+	     int,
+	     BPF_LSM_ARGS(struct inode *dir, struct dentry *dentry),
+	     BPF_LSM_ARGS(dir, dentry))
+BPF_LSM_HOOK(inode_symlink,
+	     int,
+	     BPF_LSM_ARGS(struct inode *dir, struct dentry *dentry,
+		     const char *old_name),
+	     BPF_LSM_ARGS(dir, dentry, old_name))
+BPF_LSM_HOOK(inode_mkdir,
+	     int,
+	     BPF_LSM_ARGS(struct inode *dir, struct dentry *dentry,
+			  umode_t mode),
+	     BPF_LSM_ARGS(dir, dentry, mode))
+BPF_LSM_HOOK(inode_rmdir,
+	     int,
+	     BPF_LSM_ARGS(struct inode *dir, struct dentry *dentry),
+	     BPF_LSM_ARGS(dir, dentry))
+BPF_LSM_HOOK(inode_mknod,
+	     int,
+	     BPF_LSM_ARGS(struct inode *dir, struct dentry *dentry,
+			  umode_t mode,
+		     dev_t dev),
+	     BPF_LSM_ARGS(dir, dentry, mode, dev))
+BPF_LSM_HOOK(inode_rename,
+	     int,
+	     BPF_LSM_ARGS(struct inode *old_dir, struct dentry *old_dentry,
+		     struct inode *new_dir, struct dentry *new_dentry),
+	     BPF_LSM_ARGS(old_dir, old_dentry, new_dir, new_dentry))
+BPF_LSM_HOOK(inode_readlink,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry),
+	     BPF_LSM_ARGS(dentry))
+BPF_LSM_HOOK(inode_follow_link,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry, struct inode *inode, bool rcu),
+	     BPF_LSM_ARGS(dentry, inode, rcu))
+BPF_LSM_HOOK(inode_permission,
+	     int,
+	     BPF_LSM_ARGS(struct inode *inode, int mask),
+	     BPF_LSM_ARGS(inode, mask))
+BPF_LSM_HOOK(inode_setattr,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry, struct iattr *attr),
+	     BPF_LSM_ARGS(dentry, attr))
+BPF_LSM_HOOK(inode_getattr,
+	     int,
+	     BPF_LSM_ARGS(const struct path *path),
+	     BPF_LSM_ARGS(path))
+BPF_LSM_HOOK(inode_setxattr,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry, const char *name,
+			  const void *value,
+		     size_t size, int flags),
+	     BPF_LSM_ARGS(dentry, name, value, size, flags))
+BPF_LSM_HOOK(inode_post_setxattr,
+	     void,
+	     BPF_LSM_ARGS(struct dentry *dentry, const char *name,
+			  const void *value,
+		     size_t size, int flags),
+	     BPF_LSM_ARGS(dentry, name, value, size, flags))
+BPF_LSM_HOOK(inode_getxattr,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry, const char *name),
+	     BPF_LSM_ARGS(dentry, name))
+BPF_LSM_HOOK(inode_listxattr,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry),
+	     BPF_LSM_ARGS(dentry))
+BPF_LSM_HOOK(inode_removexattr,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry, const char *name),
+	     BPF_LSM_ARGS(dentry, name))
+BPF_LSM_HOOK(inode_need_killpriv,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry),
+	     BPF_LSM_ARGS(dentry))
+BPF_LSM_HOOK(inode_killpriv,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry),
+	     BPF_LSM_ARGS(dentry))
+BPF_LSM_HOOK(inode_getsecurity,
+	     int,
+	     BPF_LSM_ARGS(struct inode *inode, const char *name, void **buffer,
+		     bool alloc),
+	     BPF_LSM_ARGS(inode, name, buffer, alloc))
+BPF_LSM_HOOK(inode_setsecurity,
+	     int,
+	     BPF_LSM_ARGS(struct inode *inode, const char *name,
+			  const void *value,
+		     size_t size, int flags),
+	     BPF_LSM_ARGS(inode, name, value, size, flags))
+BPF_LSM_HOOK(inode_listsecurity,
+	     int,
+	     BPF_LSM_ARGS(struct inode *inode, char *buffer,
+			  size_t buffer_size),
+	     BPF_LSM_ARGS(inode, buffer, buffer_size))
+BPF_LSM_HOOK(inode_getsecid,
+	     void,
+	     BPF_LSM_ARGS(struct inode *inode, u32 *secid),
+	     BPF_LSM_ARGS(inode, secid))
+BPF_LSM_HOOK(inode_copy_up,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *src, struct cred **new),
+	     BPF_LSM_ARGS(src, new))
+BPF_LSM_HOOK(inode_copy_up_xattr,
+	     int,
+	     BPF_LSM_ARGS(const char *name),
+	     BPF_LSM_ARGS(name))
+BPF_LSM_HOOK(kernfs_init_security,
+	     int,
+	     BPF_LSM_ARGS(struct kernfs_node *kn_dir, struct kernfs_node *kn),
+	     BPF_LSM_ARGS(kn_dir, kn))
+BPF_LSM_HOOK(file_permission,
+	     int,
+	     BPF_LSM_ARGS(struct file *file, int mask),
+	     BPF_LSM_ARGS(file, mask))
+BPF_LSM_HOOK(file_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(struct file *file),
+	     BPF_LSM_ARGS(file))
+BPF_LSM_HOOK(file_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct file *file),
+	     BPF_LSM_ARGS(file))
+BPF_LSM_HOOK(file_ioctl,
+	     int,
+	     BPF_LSM_ARGS(struct file *file, unsigned int cmd,
+			  unsigned long arg),
+	     BPF_LSM_ARGS(file, cmd, arg))
+BPF_LSM_HOOK(mmap_addr,
+	     int,
+	     BPF_LSM_ARGS(unsigned long addr),
+	     BPF_LSM_ARGS(addr))
+BPF_LSM_HOOK(mmap_file,
+	     int,
+	     BPF_LSM_ARGS(struct file *file, unsigned long reqprot,
+		     unsigned long prot, unsigned long flags),
+	     BPF_LSM_ARGS(file, reqprot, prot, flags))
+BPF_LSM_HOOK(file_mprotect,
+	     int,
+	     BPF_LSM_ARGS(struct vm_area_struct *vma, unsigned long reqprot,
+		     unsigned long prot),
+	     BPF_LSM_ARGS(vma, reqprot, prot))
+BPF_LSM_HOOK(file_lock,
+	     int,
+	     BPF_LSM_ARGS(struct file *file, unsigned int cmd),
+	     BPF_LSM_ARGS(file, cmd))
+BPF_LSM_HOOK(file_fcntl,
+	     int,
+	     BPF_LSM_ARGS(struct file *file, unsigned int cmd,
+			  unsigned long arg),
+	     BPF_LSM_ARGS(file, cmd, arg))
+BPF_LSM_HOOK(file_set_fowner,
+	     void,
+	     BPF_LSM_ARGS(struct file *file),
+	     BPF_LSM_ARGS(file))
+BPF_LSM_HOOK(file_send_sigiotask,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *tsk, struct fown_struct *fown,
+			  int sig),
+	     BPF_LSM_ARGS(tsk, fown, sig))
+BPF_LSM_HOOK(file_receive,
+	     int,
+	     BPF_LSM_ARGS(struct file *file),
+	     BPF_LSM_ARGS(file))
+BPF_LSM_HOOK(file_open,
+	     int,
+	     BPF_LSM_ARGS(struct file *file),
+	     BPF_LSM_ARGS(file))
+BPF_LSM_HOOK(task_alloc,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *task, unsigned long clone_flags),
+	     BPF_LSM_ARGS(task, clone_flags))
+BPF_LSM_HOOK(task_free,
+	     void,
+	     BPF_LSM_ARGS(struct task_struct *task),
+	     BPF_LSM_ARGS(task))
+BPF_LSM_HOOK(cred_alloc_blank,
+	     int,
+	     BPF_LSM_ARGS(struct cred *cred, gfp_t gfp),
+	     BPF_LSM_ARGS(cred, gfp))
+BPF_LSM_HOOK(cred_free,
+	     void,
+	     BPF_LSM_ARGS(struct cred *cred),
+	     BPF_LSM_ARGS(cred))
+BPF_LSM_HOOK(cred_prepare,
+	     int,
+	     BPF_LSM_ARGS(struct cred *new, const struct cred *old, gfp_t gfp),
+	     BPF_LSM_ARGS(new, old, gfp))
+BPF_LSM_HOOK(cred_transfer,
+	     void,
+	     BPF_LSM_ARGS(struct cred *new, const struct cred *old),
+	     BPF_LSM_ARGS(new, old))
+BPF_LSM_HOOK(cred_getsecid,
+	     void,
+	     BPF_LSM_ARGS(const struct cred *c, u32 *secid),
+	     BPF_LSM_ARGS(c, secid))
+BPF_LSM_HOOK(kernel_act_as,
+	     int,
+	     BPF_LSM_ARGS(struct cred *new, u32 secid),
+	     BPF_LSM_ARGS(new, secid))
+BPF_LSM_HOOK(kernel_create_files_as,
+	     int,
+	     BPF_LSM_ARGS(struct cred *new, struct inode *inode),
+	     BPF_LSM_ARGS(new, inode))
+BPF_LSM_HOOK(kernel_module_request,
+	     int,
+	     BPF_LSM_ARGS(char *kmod_name),
+	     BPF_LSM_ARGS(kmod_name))
+BPF_LSM_HOOK(kernel_load_data,
+	     int,
+	     BPF_LSM_ARGS(enum kernel_load_data_id id),
+	     BPF_LSM_ARGS(id))
+BPF_LSM_HOOK(kernel_read_file,
+	     int,
+	     BPF_LSM_ARGS(struct file *file, enum kernel_read_file_id id),
+	     BPF_LSM_ARGS(file, id))
+BPF_LSM_HOOK(kernel_post_read_file,
+	     int,
+	     BPF_LSM_ARGS(struct file *file, char *buf, loff_t size,
+		     enum kernel_read_file_id id),
+	     BPF_LSM_ARGS(file, buf, size, id))
+BPF_LSM_HOOK(task_fix_setuid,
+	     int,
+	     BPF_LSM_ARGS(struct cred *new, const struct cred *old, int flags),
+	     BPF_LSM_ARGS(new, old, flags))
+BPF_LSM_HOOK(task_setpgid,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p, pid_t pgid),
+	     BPF_LSM_ARGS(p, pgid))
+BPF_LSM_HOOK(task_getpgid,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p),
+	     BPF_LSM_ARGS(p))
+BPF_LSM_HOOK(task_getsid,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p),
+	     BPF_LSM_ARGS(p))
+BPF_LSM_HOOK(task_getsecid,
+	     void,
+	     BPF_LSM_ARGS(struct task_struct *p, u32 *secid),
+	     BPF_LSM_ARGS(p, secid))
+BPF_LSM_HOOK(task_setnice,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p, int nice),
+	     BPF_LSM_ARGS(p, nice))
+BPF_LSM_HOOK(task_setioprio,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p, int ioprio),
+	     BPF_LSM_ARGS(p, ioprio))
+BPF_LSM_HOOK(task_getioprio,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p),
+	     BPF_LSM_ARGS(p))
+BPF_LSM_HOOK(task_prlimit,
+	     int,
+	     BPF_LSM_ARGS(const struct cred *cred, const struct cred *tcred,
+		     unsigned int flags),
+	     BPF_LSM_ARGS(cred, tcred, flags))
+BPF_LSM_HOOK(task_setrlimit,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p, unsigned int resource,
+		     struct rlimit *new_rlim),
+	     BPF_LSM_ARGS(p, resource, new_rlim))
+BPF_LSM_HOOK(task_setscheduler,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p),
+	     BPF_LSM_ARGS(p))
+BPF_LSM_HOOK(task_getscheduler,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p),
+	     BPF_LSM_ARGS(p))
+BPF_LSM_HOOK(task_movememory,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p),
+	     BPF_LSM_ARGS(p))
+BPF_LSM_HOOK(task_kill,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p, struct kernel_siginfo *info,
+			  int sig,
+		     const struct cred *cred),
+	     BPF_LSM_ARGS(p, info, sig, cred))
+BPF_LSM_HOOK(task_prctl,
+	     int,
+	     BPF_LSM_ARGS(int option, unsigned long arg2, unsigned long arg3,
+		     unsigned long arg4, unsigned long arg5),
+	     BPF_LSM_ARGS(option, arg2, arg3, arg4, arg5))
+BPF_LSM_HOOK(task_to_inode,
+	     void,
+	     BPF_LSM_ARGS(struct task_struct *p, struct inode *inode),
+	     BPF_LSM_ARGS(p, inode))
+BPF_LSM_HOOK(ipc_permission,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *ipcp, short flag),
+	     BPF_LSM_ARGS(ipcp, flag))
+BPF_LSM_HOOK(ipc_getsecid,
+	     void,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *ipcp, u32 *secid),
+	     BPF_LSM_ARGS(ipcp, secid))
+BPF_LSM_HOOK(msg_msg_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(struct msg_msg *msg),
+	     BPF_LSM_ARGS(msg))
+BPF_LSM_HOOK(msg_msg_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct msg_msg *msg),
+	     BPF_LSM_ARGS(msg))
+BPF_LSM_HOOK(msg_queue_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm),
+	     BPF_LSM_ARGS(perm))
+BPF_LSM_HOOK(msg_queue_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm),
+	     BPF_LSM_ARGS(perm))
+BPF_LSM_HOOK(msg_queue_associate,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm, int msqflg),
+	     BPF_LSM_ARGS(perm, msqflg))
+BPF_LSM_HOOK(msg_queue_msgctl,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm, int cmd),
+	     BPF_LSM_ARGS(perm, cmd))
+BPF_LSM_HOOK(msg_queue_msgsnd,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm, struct msg_msg *msg,
+			  int msqflg),
+	     BPF_LSM_ARGS(perm, msg, msqflg))
+BPF_LSM_HOOK(msg_queue_msgrcv,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm, struct msg_msg *msg,
+		     struct task_struct *target, long type, int mode),
+	     BPF_LSM_ARGS(perm, msg, target, type, mode))
+BPF_LSM_HOOK(shm_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm),
+	     BPF_LSM_ARGS(perm))
+BPF_LSM_HOOK(shm_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm),
+	     BPF_LSM_ARGS(perm))
+BPF_LSM_HOOK(shm_associate,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm, int shmflg),
+	     BPF_LSM_ARGS(perm, shmflg))
+BPF_LSM_HOOK(shm_shmctl,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm, int cmd),
+	     BPF_LSM_ARGS(perm, cmd))
+BPF_LSM_HOOK(shm_shmat,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm, char __user *shmaddr,
+		     int shmflg),
+	     BPF_LSM_ARGS(perm, shmaddr, shmflg))
+BPF_LSM_HOOK(sem_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm),
+	     BPF_LSM_ARGS(perm))
+BPF_LSM_HOOK(sem_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm),
+	     BPF_LSM_ARGS(perm))
+BPF_LSM_HOOK(sem_associate,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm, int semflg),
+	     BPF_LSM_ARGS(perm, semflg))
+BPF_LSM_HOOK(sem_semctl,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm, int cmd),
+	     BPF_LSM_ARGS(perm, cmd))
+BPF_LSM_HOOK(sem_semop,
+	     int,
+	     BPF_LSM_ARGS(struct kern_ipc_perm *perm, struct sembuf *sops,
+		     unsigned nsops, int alter),
+	     BPF_LSM_ARGS(perm, sops, nsops, alter))
+BPF_LSM_HOOK(netlink_send,
+	     int,
+	     BPF_LSM_ARGS(struct sock *sk, struct sk_buff *skb),
+	     BPF_LSM_ARGS(sk, skb))
+BPF_LSM_HOOK(d_instantiate,
+	     void,
+	     BPF_LSM_ARGS(struct dentry *dentry, struct inode *inode),
+	     BPF_LSM_ARGS(dentry, inode))
+BPF_LSM_HOOK(getprocattr,
+	     int,
+	     BPF_LSM_ARGS(struct task_struct *p, char *name, char **value),
+	     BPF_LSM_ARGS(p, name, value))
+BPF_LSM_HOOK(setprocattr,
+	     int,
+	     BPF_LSM_ARGS(const char *name, void *value, size_t size),
+	     BPF_LSM_ARGS(name, value, size))
+BPF_LSM_HOOK(ismaclabel,
+	     int,
+	     BPF_LSM_ARGS(const char *name),
+	     BPF_LSM_ARGS(name))
+BPF_LSM_HOOK(secid_to_secctx,
+	     int,
+	     BPF_LSM_ARGS(u32 secid, char **secdata, u32 *seclen),
+	     BPF_LSM_ARGS(secid, secdata, seclen))
+BPF_LSM_HOOK(secctx_to_secid,
+	     int,
+	     BPF_LSM_ARGS(const char *secdata, u32 seclen, u32 *secid),
+	     BPF_LSM_ARGS(secdata, seclen, secid))
+BPF_LSM_HOOK(release_secctx,
+	     void,
+	     BPF_LSM_ARGS(char *secdata, u32 seclen),
+	     BPF_LSM_ARGS(secdata, seclen))
+BPF_LSM_HOOK(inode_invalidate_secctx,
+	     void,
+	     BPF_LSM_ARGS(struct inode *inode),
+	     BPF_LSM_ARGS(inode))
+BPF_LSM_HOOK(inode_notifysecctx,
+	     int,
+	     BPF_LSM_ARGS(struct inode *inode, void *ctx, u32 ctxlen),
+	     BPF_LSM_ARGS(inode, ctx, ctxlen))
+BPF_LSM_HOOK(inode_setsecctx,
+	     int,
+	     BPF_LSM_ARGS(struct dentry *dentry, void *ctx, u32 ctxlen),
+	     BPF_LSM_ARGS(dentry, ctx, ctxlen))
+BPF_LSM_HOOK(inode_getsecctx,
+	     int,
+	     BPF_LSM_ARGS(struct inode *inode, void **ctx, u32 *ctxlen),
+	     BPF_LSM_ARGS(inode, ctx, ctxlen))
+
+#ifdef CONFIG_SECURITY_NETWORK
+BPF_LSM_HOOK(unix_stream_connect,
+	     int,
+	     BPF_LSM_ARGS(struct sock *sock, struct sock *other,
+			  struct sock *newsk),
+	     BPF_LSM_ARGS(sock, other, newsk))
+BPF_LSM_HOOK(unix_may_send,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, struct socket *other),
+	     BPF_LSM_ARGS(sock, other))
+BPF_LSM_HOOK(socket_create,
+	     int,
+	     BPF_LSM_ARGS(int family, int type, int protocol, int kern),
+	     BPF_LSM_ARGS(family, type, protocol, kern))
+BPF_LSM_HOOK(socket_post_create,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, int family, int type,
+			  int protocol,
+		     int kern),
+	     BPF_LSM_ARGS(sock, family, type, protocol, kern))
+BPF_LSM_HOOK(socket_socketpair,
+	     int,
+	     BPF_LSM_ARGS(struct socket *socka, struct socket *sockb),
+	     BPF_LSM_ARGS(socka, sockb))
+BPF_LSM_HOOK(socket_bind,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, struct sockaddr *address,
+			  int addrlen),
+	     BPF_LSM_ARGS(sock, address, addrlen))
+BPF_LSM_HOOK(socket_connect,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, struct sockaddr *address,
+			  int addrlen),
+	     BPF_LSM_ARGS(sock, address, addrlen))
+BPF_LSM_HOOK(socket_listen,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, int backlog),
+	     BPF_LSM_ARGS(sock, backlog))
+BPF_LSM_HOOK(socket_accept,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, struct socket *newsock),
+	     BPF_LSM_ARGS(sock, newsock))
+BPF_LSM_HOOK(socket_sendmsg,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, struct msghdr *msg, int size),
+	     BPF_LSM_ARGS(sock, msg, size))
+BPF_LSM_HOOK(socket_recvmsg,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, struct msghdr *msg, int size,
+		     int flags),
+	     BPF_LSM_ARGS(sock, msg, size, flags))
+BPF_LSM_HOOK(socket_getsockname,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock),
+	     BPF_LSM_ARGS(sock))
+BPF_LSM_HOOK(socket_getpeername,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock),
+	     BPF_LSM_ARGS(sock))
+BPF_LSM_HOOK(socket_getsockopt,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, int level, int optname),
+	     BPF_LSM_ARGS(sock, level, optname))
+BPF_LSM_HOOK(socket_setsockopt,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, int level, int optname),
+	     BPF_LSM_ARGS(sock, level, optname))
+BPF_LSM_HOOK(socket_shutdown,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, int how),
+	     BPF_LSM_ARGS(sock, how))
+BPF_LSM_HOOK(socket_sock_rcv_skb,
+	     int,
+	     BPF_LSM_ARGS(struct sock *sk, struct sk_buff *skb),
+	     BPF_LSM_ARGS(sk, skb))
+BPF_LSM_HOOK(socket_getpeersec_stream,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, char __user *optval,
+		     int __user *optlen, unsigned len),
+	     BPF_LSM_ARGS(sock, optval, optlen, len))
+BPF_LSM_HOOK(socket_getpeersec_dgram,
+	     int,
+	     BPF_LSM_ARGS(struct socket *sock, struct sk_buff *skb, u32 *secid),
+	     BPF_LSM_ARGS(sock, skb, secid))
+BPF_LSM_HOOK(sk_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(struct sock *sk, int family, gfp_t priority),
+	     BPF_LSM_ARGS(sk, family, priority))
+BPF_LSM_HOOK(sk_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct sock *sk),
+	     BPF_LSM_ARGS(sk))
+BPF_LSM_HOOK(sk_clone_security,
+	     void,
+	     BPF_LSM_ARGS(const struct sock *sk, struct sock *newsk),
+	     BPF_LSM_ARGS(sk, newsk))
+BPF_LSM_HOOK(sk_getsecid,
+	     void,
+	     BPF_LSM_ARGS(struct sock *sk, u32 *secid),
+	     BPF_LSM_ARGS(sk, secid))
+BPF_LSM_HOOK(sock_graft,
+	     void,
+	     BPF_LSM_ARGS(struct sock *sk, struct socket *parent),
+	     BPF_LSM_ARGS(sk, parent))
+BPF_LSM_HOOK(inet_conn_request,
+	     int,
+	     BPF_LSM_ARGS(struct sock *sk, struct sk_buff *skb,
+		     struct request_sock *req),
+	     BPF_LSM_ARGS(sk, skb, req))
+BPF_LSM_HOOK(inet_csk_clone,
+	     void,
+	     BPF_LSM_ARGS(struct sock *newsk, const struct request_sock *req),
+	     BPF_LSM_ARGS(newsk, req))
+BPF_LSM_HOOK(inet_conn_established,
+	     void,
+	     BPF_LSM_ARGS(struct sock *sk, struct sk_buff *skb),
+	     BPF_LSM_ARGS(sk, skb))
+BPF_LSM_HOOK(secmark_relabel_packet,
+	     int,
+	     BPF_LSM_ARGS(u32 secid),
+	     BPF_LSM_ARGS(secid))
+BPF_LSM_HOOK(secmark_refcount_inc,
+	     void,
+	     BPF_LSM_ARGS(void),
+	     BPF_LSM_ARGS())
+BPF_LSM_HOOK(secmark_refcount_dec,
+	     void,
+	     BPF_LSM_ARGS(void),
+	     BPF_LSM_ARGS())
+BPF_LSM_HOOK(req_classify_flow,
+	     void,
+	     BPF_LSM_ARGS(const struct request_sock *req, struct flowi *fl),
+	     BPF_LSM_ARGS(req, fl))
+BPF_LSM_HOOK(tun_dev_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(void **security),
+	     BPF_LSM_ARGS(security))
+BPF_LSM_HOOK(tun_dev_free_security,
+	     void,
+	     BPF_LSM_ARGS(void *security),
+	     BPF_LSM_ARGS(security))
+BPF_LSM_HOOK(tun_dev_create,
+	     int,
+	     BPF_LSM_ARGS(void),
+	     BPF_LSM_ARGS())
+BPF_LSM_HOOK(tun_dev_attach_queue,
+	     int,
+	     BPF_LSM_ARGS(void *security),
+	     BPF_LSM_ARGS(security))
+BPF_LSM_HOOK(tun_dev_attach,
+	     int,
+	     BPF_LSM_ARGS(struct sock *sk, void *security),
+	     BPF_LSM_ARGS(sk, security))
+BPF_LSM_HOOK(tun_dev_open,
+	     int,
+	     BPF_LSM_ARGS(void *security),
+	     BPF_LSM_ARGS(security))
+BPF_LSM_HOOK(sctp_assoc_request,
+	     int,
+	     BPF_LSM_ARGS(struct sctp_endpoint *ep, struct sk_buff *skb),
+	     BPF_LSM_ARGS(ep, skb))
+BPF_LSM_HOOK(sctp_bind_connect,
+	     int,
+	     BPF_LSM_ARGS(struct sock *sk, int optname,
+			  struct sockaddr *address,
+		     int addrlen),
+	     BPF_LSM_ARGS(sk, optname, address, addrlen))
+BPF_LSM_HOOK(sctp_sk_clone,
+	     void,
+	     BPF_LSM_ARGS(struct sctp_endpoint *ep, struct sock *sk,
+			  struct sock *newsk),
+	     BPF_LSM_ARGS(ep, sk, newsk))
+#endif	/* CONFIG_SECURITY_NETWORK */
+
+#ifdef CONFIG_SECURITY_INFINIBAND
+BPF_LSM_HOOK(ib_pkey_access,
+	     int,
+	     BPF_LSM_ARGS(void *sec, u64 subnet_prefix, u16 pkey),
+	     BPF_LSM_ARGS(sec, subnet_prefix, pkey))
+BPF_LSM_HOOK(ib_endport_manage_subnet,
+	     int,
+	     BPF_LSM_ARGS(void *sec, const char *dev_name, u8 port_num),
+	     BPF_LSM_ARGS(sec, dev_name, port_num))
+BPF_LSM_HOOK(ib_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(void **sec),
+	     BPF_LSM_ARGS(sec))
+BPF_LSM_HOOK(ib_free_security,
+	     void,
+	     BPF_LSM_ARGS(void *sec),
+	     BPF_LSM_ARGS(sec))
+#endif	/* CONFIG_SECURITY_INFINIBAND */
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+BPF_LSM_HOOK(xfrm_policy_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(struct xfrm_sec_ctx **ctxp,
+		     struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp),
+	     BPF_LSM_ARGS(ctxp, sec_ctx, gfp))
+BPF_LSM_HOOK(xfrm_policy_clone_security,
+	     int,
+	     BPF_LSM_ARGS(struct xfrm_sec_ctx *old_ctx,
+			  struct xfrm_sec_ctx **new_ctx),
+	     BPF_LSM_ARGS(old_ctx, new_ctx))
+BPF_LSM_HOOK(xfrm_policy_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct xfrm_sec_ctx *ctx),
+	     BPF_LSM_ARGS(ctx))
+BPF_LSM_HOOK(xfrm_policy_delete_security,
+	     int,
+	     BPF_LSM_ARGS(struct xfrm_sec_ctx *ctx),
+	     BPF_LSM_ARGS(ctx))
+BPF_LSM_HOOK(xfrm_state_alloc,
+	     int,
+	     BPF_LSM_ARGS(struct xfrm_state *x,
+			  struct xfrm_user_sec_ctx *sec_ctx),
+	     BPF_LSM_ARGS(x, sec_ctx))
+BPF_LSM_HOOK(xfrm_state_alloc_acquire,
+	     int,
+	     BPF_LSM_ARGS(struct xfrm_state *x, struct xfrm_sec_ctx *polsec,
+		     u32 secid),
+	     BPF_LSM_ARGS(x, polsec, secid))
+BPF_LSM_HOOK(xfrm_state_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct xfrm_state *x),
+	     BPF_LSM_ARGS(x))
+BPF_LSM_HOOK(xfrm_state_delete_security,
+	     int,
+	     BPF_LSM_ARGS(struct xfrm_state *x),
+	     BPF_LSM_ARGS(x))
+BPF_LSM_HOOK(xfrm_policy_lookup,
+	     int,
+	     BPF_LSM_ARGS(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir),
+	     BPF_LSM_ARGS(ctx, fl_secid, dir))
+BPF_LSM_HOOK(xfrm_state_pol_flow_match,
+	     int,
+	     BPF_LSM_ARGS(struct xfrm_state *x, struct xfrm_policy *xp,
+		     const struct flowi *fl),
+	     BPF_LSM_ARGS(x, xp, fl))
+BPF_LSM_HOOK(xfrm_decode_session,
+	     int,
+	     BPF_LSM_ARGS(struct sk_buff *skb, u32 *secid, int ckall),
+	     BPF_LSM_ARGS(skb, secid, ckall))
+#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
+
+#ifdef CONFIG_KEYS
+BPF_LSM_HOOK(key_alloc,
+	     int,
+	     BPF_LSM_ARGS(struct key *key, const struct cred *cred,
+		     unsigned long flags),
+	     BPF_LSM_ARGS(key, cred, flags))
+BPF_LSM_HOOK(key_free,
+	     void,
+	     BPF_LSM_ARGS(struct key *key),
+	     BPF_LSM_ARGS(key))
+BPF_LSM_HOOK(key_permission,
+	     int,
+	     BPF_LSM_ARGS(key_ref_t key_ref, const struct cred *cred,
+			  unsigned perm),
+	     BPF_LSM_ARGS(key_ref, cred, perm))
+BPF_LSM_HOOK(key_getsecurity,
+	     int,
+	     BPF_LSM_ARGS(struct key *key, char **_buffer),
+	     BPF_LSM_ARGS(key, _buffer))
+#endif	/* CONFIG_KEYS */
+
+#ifdef CONFIG_AUDIT
+BPF_LSM_HOOK(audit_rule_init,
+	     int,
+	     BPF_LSM_ARGS(u32 field, u32 op, char *rulestr, void **lsmrule),
+	     BPF_LSM_ARGS(field, op, rulestr, lsmrule))
+BPF_LSM_HOOK(audit_rule_known,
+	     int,
+	     BPF_LSM_ARGS(struct audit_krule *krule),
+	     BPF_LSM_ARGS(krule))
+BPF_LSM_HOOK(audit_rule_match,
+	     int,
+	     BPF_LSM_ARGS(u32 secid, u32 field, u32 op, void *lsmrule),
+	     BPF_LSM_ARGS(secid, field, op, lsmrule))
+BPF_LSM_HOOK(audit_rule_free,
+	     void,
+	     BPF_LSM_ARGS(void *lsmrule),
+	     BPF_LSM_ARGS(lsmrule))
+#endif /* CONFIG_AUDIT */
+
+#ifdef CONFIG_BPF_SYSCALL
+BPF_LSM_HOOK(bpf,
+	     int,
+	     BPF_LSM_ARGS(int cmd, union bpf_attr *attr, unsigned int size),
+	     BPF_LSM_ARGS(cmd, attr, size))
+BPF_LSM_HOOK(bpf_map,
+	     int,
+	     BPF_LSM_ARGS(struct bpf_map *map, fmode_t fmode),
+	     BPF_LSM_ARGS(map, fmode))
+BPF_LSM_HOOK(bpf_prog,
+	     int,
+	     BPF_LSM_ARGS(struct bpf_prog *prog),
+	     BPF_LSM_ARGS(prog))
+BPF_LSM_HOOK(bpf_map_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(struct bpf_map *map),
+	     BPF_LSM_ARGS(map))
+BPF_LSM_HOOK(bpf_map_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct bpf_map *map),
+	     BPF_LSM_ARGS(map))
+BPF_LSM_HOOK(bpf_prog_alloc_security,
+	     int,
+	     BPF_LSM_ARGS(struct bpf_prog_aux *aux),
+	     BPF_LSM_ARGS(aux))
+BPF_LSM_HOOK(bpf_prog_free_security,
+	     void,
+	     BPF_LSM_ARGS(struct bpf_prog_aux *aux),
+	     BPF_LSM_ARGS(aux))
+#endif /* CONFIG_BPF_SYSCALL */
+
+BPF_LSM_HOOK(locked_down,
+	     int,
+	     BPF_LSM_ARGS(enum lockdown_reason what),
+	     BPF_LSM_ARGS(what))
diff --git a/security/bpf/lsm.c b/security/bpf/lsm.c
index fe5c65bbdd45..8586ddfe8cda 100644
--- a/security/bpf/lsm.c
+++ b/security/bpf/lsm.c
@@ -5,14 +5,146 @@
  */
 
 #include <linux/lsm_hooks.h>
+#include <linux/bpf_lsm.h>
 
-static int process_execution(struct linux_binprm *bprm)
+#include "bpf_lsm.h"
+
+/*
+ * Run the eBPF programs of the hook indexed by the type t with the arguments
+ * packed into an array of u64 integers as the context.
+ */
+static inline int __run_progs(enum lsm_hook_type t, u64 *args)
 {
-	return 0;
+	struct bpf_lsm_hook *h = &bpf_lsm_hooks_list[t];
+	struct bpf_prog_array_item *item;
+	struct bpf_prog_array *array;
+	int ret, retval = 0;
+
+	/*
+	 * Some hooks might get called before the securityFS is initialized,
+	 * this will result in a NULL pointer exception.
+	 */
+	if (!bpf_lsm_fs_initialized)
+		return 0;
+
+	preempt_disable();
+	rcu_read_lock();
+
+	array = rcu_dereference(h->progs);
+	if (!array)
+		goto out;
+
+	for (item = array->items; item->prog; item++) {
+		ret = BPF_PROG_RUN(item->prog, args);
+		if (ret < 0) {
+			retval = ret;
+			break;
+		}
+	}
+out:
+	rcu_read_unlock();
+	preempt_enable();
+	return IS_ENABLED(CONFIG_SECURITY_BPF_ENFORCE) ? retval : 0;
+}
+
+/*
+ * This macro creates a bpf_lsm_run_progs_<x> function which accepts a known
+ * number of arguments and packs them into an array of u64 integers. The array
+ * is used as a context to run the BPF programs attached to the hook.
+ */
+#define DEFINE_LSM_RUN_PROGS_x(x)					\
+	static int bpf_lsm_run_progs##x(enum lsm_hook_type t,		\
+				 REPEAT(x, SARG, __DL_COM, __SEQ_0_11))	\
+	{								\
+		u64 args[x];						\
+		REPEAT(x, COPY, __DL_SEM, __SEQ_0_11);			\
+		return __run_progs(t, args);				\
+	}
+
+/*
+ * There are some hooks that have no arguments, so there's nothing to pack and
+ * the attached BPF programs get a NULL context.
+ */
+int bpf_lsm_run_progs0(enum lsm_hook_type t, u64 args)
+{
+	return __run_progs(t, NULL);
+}
+
+/*
+ * The largest number of args accepted by an LSM hook is currently 6. Define
+ * bpf_lsm_run_progs_1 to bpf_lsm_run_progs_6.
+ */
+DEFINE_LSM_RUN_PROGS_x(1);
+DEFINE_LSM_RUN_PROGS_x(2);
+DEFINE_LSM_RUN_PROGS_x(3);
+DEFINE_LSM_RUN_PROGS_x(4);
+DEFINE_LSM_RUN_PROGS_x(5);
+DEFINE_LSM_RUN_PROGS_x(6);
+
+/*
+ * This macro calls one of the bpf_lsm_args_<x> functions based on the number of
+ * arguments of the variadic macro. Each argument is casted to a u64 bit integer
+ * as expected by BTF.
+ */
+#define LSM_RUN_PROGS(T, args...) \
+	CONCATENATE(bpf_lsm_run_progs, COUNT_ARGS(args))(T, CAST_TO_U64(args))
+
+/*
+ * The hooks can have an int or void return type, these macros allow having a
+ * single implementation of DEFINE_LSM_HOOK irrespective of the return type.
+ */
+#define LSM_HOOK_RET(ret, x) LSM_HOOK_RET_##ret(x)
+#define LSM_HOOK_RET_int(x) x
+#define LSM_HOOK_RET_void(x)
+
+/*
+ * This macro defines the body of a LSM hook which runs the eBPF programs that
+ * are attached to the hook and returns the error code from the eBPF programs if
+ * the return type of the hook is int.
+ */
+#define DEFINE_LSM_HOOK(hook, ret, proto, args)				\
+typedef ret (*lsm_btf_##hook)(proto);					\
+static ret bpf_lsm_##hook(proto)					\
+{									\
+	return LSM_HOOK_RET(ret, LSM_RUN_PROGS(hook##_type, args));	\
 }
 
+/*
+ * Define the body of each of the LSM hooks defined in hooks.h.
+ */
+#define BPF_LSM_HOOK(hook, ret, args, proto) \
+	DEFINE_LSM_HOOK(hook, ret, BPF_LSM_ARGS(args), BPF_LSM_ARGS(proto))
+#include "hooks.h"
+#undef BPF_LSM_HOOK
+#undef DEFINE_LSM_HOOK
+
+/*
+ * Initialize the bpf_lsm_hooks_list for each of the hooks defined in hooks.h.
+ * The list contains information for each of the hook and can be indexed by the
+ * its type to initialize security FS, attach, detach and execute eBPF programs
+ * for the hook.
+ */
+struct bpf_lsm_hook bpf_lsm_hooks_list[] = {
+	#define BPF_LSM_HOOK(h, ...)					\
+		[h##_type] = {						\
+			.h_type = h##_type,				\
+			.mutex = __MUTEX_INITIALIZER(			\
+				bpf_lsm_hooks_list[h##_type].mutex),	\
+			.name = #h,					\
+			.btf_hook_func =				\
+				(void *)(lsm_btf_##h)(bpf_lsm_##h),	\
+		},
+	#include "hooks.h"
+	#undef BPF_LSM_HOOK
+};
+
+/*
+ * Initialize the bpf_lsm_hooks_list for each of the hooks defined in hooks.h.
+ */
 static struct security_hook_list lsm_hooks[] __lsm_ro_after_init = {
-	LSM_HOOK_INIT(bprm_check_security, process_execution),
+	#define BPF_LSM_HOOK(h, ...) LSM_HOOK_INIT(h, bpf_lsm_##h),
+	#include "hooks.h"
+	#undef BPF_LSM_HOOK
 };
 
 static int __init lsm_init(void)
diff --git a/security/bpf/lsm_fs.c b/security/bpf/lsm_fs.c
new file mode 100644
index 000000000000..49165394ef7d
--- /dev/null
+++ b/security/bpf/lsm_fs.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2019 Google LLC.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/security.h>
+#include <linux/bpf_lsm.h>
+
+#include "fs.h"
+#include "bpf_lsm.h"
+
+static struct dentry *bpf_lsm_dir;
+
+static const struct file_operations hook_ops = {};
+
+int bpf_lsm_fs_initialized;
+
+bool is_bpf_lsm_hook_file(struct file *f)
+{
+	return f->f_op == &hook_ops;
+}
+
+static void __init free_hook(struct bpf_lsm_hook *h)
+{
+	securityfs_remove(h->h_dentry);
+	h->h_dentry = NULL;
+}
+
+static int __init init_hook(struct bpf_lsm_hook *h, struct dentry *parent)
+{
+	struct dentry *h_dentry;
+
+	h_dentry = securityfs_create_file(h->name, 0600, parent,
+			NULL, &hook_ops);
+	if (IS_ERR(h_dentry))
+		return PTR_ERR(h_dentry);
+
+	h_dentry->d_fsdata = h;
+	h->h_dentry = h_dentry;
+	return 0;
+}
+
+static int __init bpf_lsm_fs_init(void)
+{
+	struct bpf_lsm_hook *hook;
+	int ret;
+
+	bpf_lsm_dir = securityfs_create_dir(BPF_LSM_SFS_NAME, NULL);
+	if (IS_ERR(bpf_lsm_dir)) {
+		ret = PTR_ERR(bpf_lsm_dir);
+		pr_err("BPF LSM: Unable to create sysfs dir: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * If there is an error in initializing a hook, the initialization
+	 * logic makes sure that it has been freed, but this means that
+	 * cleanup should be called for all the other hooks. The cleanup
+	 * logic handles uninitialized data.
+	 */
+	lsm_for_each_hook(hook) {
+		ret = init_hook(hook, bpf_lsm_dir);
+		if (ret < 0)
+			goto error;
+	}
+
+	bpf_lsm_fs_initialized = 1;
+	return 0;
+error:
+	lsm_for_each_hook(hook)
+		free_hook(hook);
+	securityfs_remove(bpf_lsm_dir);
+	return ret;
+}
+
+late_initcall(bpf_lsm_fs_init);
-- 
2.20.1


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

* [PATCH bpf-next v1 07/13] bpf: lsm: Implement attach, detach and execution.
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (5 preceding siblings ...)
  2019-12-20 15:42 ` [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs KP Singh
@ 2019-12-20 15:42 ` KP Singh
  2019-12-24  5:48   ` Andrii Nakryiko
  2020-01-07 21:27   ` James Morris
  2019-12-20 15:42 ` [PATCH bpf-next v1 08/13] bpf: lsm: Show attached program names in hook read handler KP Singh
                   ` (9 subsequent siblings)
  16 siblings, 2 replies; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:42 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

A user space program can attach an eBPF program by:

  hook_fd = open("/sys/kernel/security/bpf/bprm_check_security",
		 O_RDWR|O_CLOEXEC)
  prog_fd = bpf(BPF_PROG_LOAD, ...)
  bpf(BPF_PROG_ATTACH, hook_fd, prog_fd)

The following permissions are required to attach a program to a hook:

- CAP_SYS_ADMIN to load eBPF programs
- CAP_MAC_ADMIN (to update the policy of an LSM)
- The securityfs file being a valid hook and writable (O_RDWR)

When such an attach call is received, the attachment logic looks up the
dentry and appends the program to the bpf_prog_array.

The BPF programs are stored in a bpf_prog_array and writes to the array
are guarded by a mutex. The eBPF programs are executed as a part of the
LSM hook they are attached to. If any of the eBPF programs return
an error (-ENOPERM) the action represented by the hook is denied.

Signed-off-by: KP Singh <kpsingh@google.com>
---
 MAINTAINERS             |   1 +
 include/linux/bpf_lsm.h |  13 ++++
 kernel/bpf/syscall.c    |   5 +-
 security/bpf/lsm_fs.c   |  19 +++++-
 security/bpf/ops.c      | 134 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 169 insertions(+), 3 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 3b82d8ff21fb..681ae39bb2f0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3181,6 +3181,7 @@ L:	linux-security-module@vger.kernel.org
 L:	bpf@vger.kernel.org
 S:	Maintained
 F:	security/bpf/
+F:	include/linux/bpf_lsm.h
 
 BROADCOM B44 10/100 ETHERNET DRIVER
 M:	Michael Chan <michael.chan@broadcom.com>
diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h
index 76f81e642dc2..c029f2b8d6fd 100644
--- a/include/linux/bpf_lsm.h
+++ b/include/linux/bpf_lsm.h
@@ -7,6 +7,19 @@
 
 #ifdef CONFIG_SECURITY_BPF
 extern int bpf_lsm_fs_initialized;
+int bpf_lsm_attach(const union bpf_attr *attr, struct bpf_prog *prog);
+int bpf_lsm_detach(const union bpf_attr *attr);
+#else
+static inline int bpf_lsm_attach(const union bpf_attr *attr,
+				 struct bpf_prog *prog)
+{
+	return -EINVAL;
+}
+
+static inline int bpf_lsm_detach(const union bpf_attr *attr)
+{
+	return -EINVAL;
+}
 #endif /* CONFIG_SECURITY_BPF */
 
 #endif /* _LINUX_BPF_LSM_H */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 4fcaf6042c07..8897b774973f 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -4,6 +4,7 @@
 #include <linux/bpf.h>
 #include <linux/bpf_trace.h>
 #include <linux/bpf_lirc.h>
+#include <linux/bpf_lsm.h>
 #include <linux/btf.h>
 #include <linux/syscalls.h>
 #include <linux/slab.h>
@@ -2132,7 +2133,7 @@ static int bpf_prog_attach(const union bpf_attr *attr)
 		ret = lirc_prog_attach(attr, prog);
 		break;
 	case BPF_PROG_TYPE_LSM:
-		ret = -EINVAL;
+		ret = bpf_lsm_attach(attr, prog);
 		break;
 	case BPF_PROG_TYPE_FLOW_DISSECTOR:
 		ret = skb_flow_dissector_bpf_prog_attach(attr, prog);
@@ -2200,6 +2201,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
 	case BPF_CGROUP_SETSOCKOPT:
 		ptype = BPF_PROG_TYPE_CGROUP_SOCKOPT;
 		break;
+	case BPF_LSM_MAC:
+		return bpf_lsm_detach(attr);
 	default:
 		return -EINVAL;
 	}
diff --git a/security/bpf/lsm_fs.c b/security/bpf/lsm_fs.c
index 49165394ef7d..b271e9582d0f 100644
--- a/security/bpf/lsm_fs.c
+++ b/security/bpf/lsm_fs.c
@@ -9,6 +9,8 @@
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/types.h>
+#include <linux/filter.h>
+#include <linux/bpf.h>
 #include <linux/security.h>
 #include <linux/bpf_lsm.h>
 
@@ -28,6 +30,19 @@ bool is_bpf_lsm_hook_file(struct file *f)
 
 static void __init free_hook(struct bpf_lsm_hook *h)
 {
+	struct bpf_prog_array_item *item;
+	/*
+	 * This function is __init so we are guaranteed that there will be
+	 * no concurrent access.
+	 */
+	struct bpf_prog_array *progs = rcu_dereference_raw(h->progs);
+
+	if (progs) {
+		for (item = progs->items; item->prog; item++)
+			bpf_prog_put(item->prog);
+		bpf_prog_array_free(progs);
+	}
+
 	securityfs_remove(h->h_dentry);
 	h->h_dentry = NULL;
 }
@@ -36,8 +51,8 @@ static int __init init_hook(struct bpf_lsm_hook *h, struct dentry *parent)
 {
 	struct dentry *h_dentry;
 
-	h_dentry = securityfs_create_file(h->name, 0600, parent,
-			NULL, &hook_ops);
+	h_dentry = securityfs_create_file(h->name, 0600,
+					  parent, NULL, &hook_ops);
 	if (IS_ERR(h_dentry))
 		return PTR_ERR(h_dentry);
 
diff --git a/security/bpf/ops.c b/security/bpf/ops.c
index 2fa3ebdf598d..eb8a8db28109 100644
--- a/security/bpf/ops.c
+++ b/security/bpf/ops.c
@@ -4,11 +4,145 @@
  * Copyright 2019 Google LLC.
  */
 
+#include <linux/err.h>
+#include <linux/types.h>
 #include <linux/filter.h>
 #include <linux/bpf.h>
+#include <linux/security.h>
+#include <linux/bpf_lsm.h>
+
+#include "bpf_lsm.h"
+#include "fs.h"
+
+static struct bpf_lsm_hook *get_hook_from_fd(int fd)
+{
+	struct bpf_lsm_hook *h;
+	struct fd f;
+	int ret;
+
+	/*
+	 * Only CAP_MAC_ADMIN users are allowed to make changes to LSM hooks
+	 */
+	if (!capable(CAP_MAC_ADMIN))
+		return ERR_PTR(-EPERM);
+
+
+	f = fdget(fd);
+	if (!f.file)
+		return ERR_PTR(-EBADF);
+
+
+	if (!is_bpf_lsm_hook_file(f.file)) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/*
+	 * It's wrong to attach the program to the hook if the file is not
+	 * opened for a writing. Note that, this is an EBADF and not an EPERM
+	 * because the file has been opened with an incorrect mode.
+	 */
+	if (!(f.file->f_mode & FMODE_WRITE)) {
+		ret = -EBADF;
+		goto error;
+	}
+
+	/*
+	 * The securityfs dentry never disappears, so we don't need to take a
+	 * reference to it.
+	 */
+	h = file_dentry(f.file)->d_fsdata;
+	if (WARN_ON(!h)) {
+		ret = -EINVAL;
+		goto error;
+	}
+	fdput(f);
+	return h;
+
+error:
+	fdput(f);
+	return ERR_PTR(ret);
+}
+
+int bpf_lsm_attach(const union bpf_attr *attr, struct bpf_prog *prog)
+{
+	struct bpf_prog_array *old_array;
+	struct bpf_prog_array *new_array;
+	struct bpf_lsm_hook *h;
+	int ret = 0;
+
+	h = get_hook_from_fd(attr->target_fd);
+	if (IS_ERR(h))
+		return PTR_ERR(h);
+
+	mutex_lock(&h->mutex);
+	old_array = rcu_dereference_protected(h->progs,
+					      lockdep_is_held(&h->mutex));
+
+	ret = bpf_prog_array_copy(old_array, NULL, prog, &new_array);
+	if (ret < 0)
+		goto unlock;
+
+	rcu_assign_pointer(h->progs, new_array);
+	bpf_prog_array_free(old_array);
+
+unlock:
+	mutex_unlock(&h->mutex);
+	return ret;
+}
+
+int bpf_lsm_detach(const union bpf_attr *attr)
+{
+	struct bpf_prog_array *old_array, *new_array;
+	struct bpf_prog *prog;
+	struct bpf_lsm_hook *h;
+	int ret = 0;
+
+	if (attr->attach_flags)
+		return -EINVAL;
+
+	h = get_hook_from_fd(attr->target_fd);
+	if (IS_ERR(h))
+		return PTR_ERR(h);
+
+	prog = bpf_prog_get_type(attr->attach_bpf_fd,
+				 BPF_PROG_TYPE_LSM);
+	if (IS_ERR(prog))
+		return PTR_ERR(prog);
+
+	mutex_lock(&h->mutex);
+	old_array = rcu_dereference_protected(h->progs,
+					      lockdep_is_held(&h->mutex));
+
+	ret = bpf_prog_array_copy(old_array, prog, NULL, &new_array);
+	if (ret)
+		goto unlock;
+
+	rcu_assign_pointer(h->progs, new_array);
+	bpf_prog_array_free(old_array);
+unlock:
+	bpf_prog_put(prog);
+	mutex_unlock(&h->mutex);
+	return ret;
+}
 
 const struct bpf_prog_ops lsm_prog_ops = {
 };
 
+static const struct bpf_func_proto *get_bpf_func_proto(enum bpf_func_id
+		func_id, const struct bpf_prog *prog)
+{
+	switch (func_id) {
+	case BPF_FUNC_map_lookup_elem:
+		return &bpf_map_lookup_elem_proto;
+	case BPF_FUNC_get_current_pid_tgid:
+		return &bpf_get_current_pid_tgid_proto;
+	default:
+		return NULL;
+	}
+}
+
 const struct bpf_verifier_ops lsm_verifier_ops = {
+	.get_func_proto = get_bpf_func_proto,
+	.is_valid_access = btf_ctx_access,
 };
-- 
2.20.1


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

* [PATCH bpf-next v1 08/13] bpf: lsm: Show attached program names in hook read handler.
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (6 preceding siblings ...)
  2019-12-20 15:42 ` [PATCH bpf-next v1 07/13] bpf: lsm: Implement attach, detach and execution KP Singh
@ 2019-12-20 15:42 ` KP Singh
  2020-01-07 21:28   ` James Morris
  2019-12-20 15:42 ` [PATCH bpf-next v1 09/13] bpf: lsm: Add a helper function bpf_lsm_event_output KP Singh
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:42 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

For inspectability the system administrator should be able to view the
list of active KRSI programs:

   bash # cat /sys/kernel/security/bpf/bprm_check_security
   bpf_prog1

Signed-off-by: KP Singh <kpsingh@google.com>
---
 security/bpf/lsm_fs.c | 81 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 80 insertions(+), 1 deletion(-)

diff --git a/security/bpf/lsm_fs.c b/security/bpf/lsm_fs.c
index b271e9582d0f..01a89bce1347 100644
--- a/security/bpf/lsm_fs.c
+++ b/security/bpf/lsm_fs.c
@@ -10,6 +10,7 @@
 #include <linux/fs.h>
 #include <linux/types.h>
 #include <linux/filter.h>
+#include <linux/seq_file.h>
 #include <linux/bpf.h>
 #include <linux/security.h>
 #include <linux/bpf_lsm.h>
@@ -19,7 +20,85 @@
 
 static struct dentry *bpf_lsm_dir;
 
-static const struct file_operations hook_ops = {};
+static void *seq_start(struct seq_file *m, loff_t *pos)
+	__acquires(RCU)
+{
+	struct bpf_prog_array_item *item;
+	struct bpf_prog_array *progs;
+	struct bpf_lsm_hook *h;
+	struct dentry *dentry;
+
+	/*
+	 * rcu_read_lock() must be held before any return statement because the
+	 * stop() will always be called and thus call rcu_read_unlock()
+	 */
+	rcu_read_lock();
+
+	dentry = file_dentry(m->file);
+	h = dentry->d_fsdata;
+	if (WARN_ON(!h))
+		return ERR_PTR(-EFAULT);
+
+	progs = rcu_dereference(h->progs);
+	if (!progs)
+		return NULL;
+
+	/* Assumes that no &dummy_bpf_prog entries exist */
+	if ((*pos) >= bpf_prog_array_length(progs))
+		return NULL;
+
+	item = progs->items + *pos;
+	if (!item->prog)
+		return NULL;
+
+	return item;
+}
+
+static void *seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	struct bpf_prog_array_item *item = v;
+
+	item++;
+	++*pos;
+
+	if (!item->prog)
+		return NULL;
+
+	return item;
+}
+
+static void seq_stop(struct seq_file *m, void *v)
+	__releases(RCU)
+{
+	rcu_read_unlock();
+}
+
+static int show_prog(struct seq_file *m, void *v)
+{
+	struct bpf_prog_array_item *item = v;
+
+	seq_printf(m, "%s\n", item->prog->aux->name);
+	return 0;
+}
+
+static const struct seq_operations hook_seq_ops = {
+	.show	= show_prog,
+	.start	= seq_start,
+	.next	= seq_next,
+	.stop	= seq_stop,
+};
+
+static int hook_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &hook_seq_ops);
+}
+
+static const struct file_operations hook_ops = {
+	.open		= hook_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 
 int bpf_lsm_fs_initialized;
 
-- 
2.20.1


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

* [PATCH bpf-next v1 09/13] bpf: lsm: Add a helper function bpf_lsm_event_output
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (7 preceding siblings ...)
  2019-12-20 15:42 ` [PATCH bpf-next v1 08/13] bpf: lsm: Show attached program names in hook read handler KP Singh
@ 2019-12-20 15:42 ` KP Singh
  2019-12-24  6:36   ` Andrii Nakryiko
  2019-12-20 15:42 ` [PATCH bpf-next v1 10/13] bpf: lsm: Handle attachment of the same program KP Singh
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:42 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

This helper is similar to bpf_perf_event_output except that
it does need a ctx argument which is more usable in the
BTF based LSM programs where the context is converted to
the signature of the attacthed BTF type.

An example usage of this function would be:

struct {
         __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
         __uint(key_size, sizeof(int));
         __uint(value_size, sizeof(u32));
} perf_map SEC(".maps");

BPF_TRACE_1(bpf_prog1, "lsm/bprm_check_security,
	    struct linux_binprm *, bprm)
{
	char buf[BUF_SIZE];
	int len;
	u64 flags = BPF_F_CURRENT_CPU;

	/* some logic that fills up buf with len data */
	len = fill_up_buf(buf);
	if (len < 0)
		return len;
	if (len > BU)
		return 0;

	bpf_lsm_event_output(&perf_map, flags, buf, len);
	return 0;
}

Signed-off-by: KP Singh <kpsingh@google.com>
---
 include/uapi/linux/bpf.h       | 10 +++++++++-
 kernel/bpf/verifier.c          |  1 +
 security/bpf/ops.c             | 21 +++++++++++++++++++++
 tools/include/uapi/linux/bpf.h | 10 +++++++++-
 4 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index fc64ae865526..3511fa271c9b 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -2823,6 +2823,13 @@ union bpf_attr {
  * 	Return
  * 		On success, the strictly positive length of the string,	including
  * 		the trailing NUL character. On error, a negative value.
+ *
+ * int bpf_lsm_event_output(struct bpf_map *map, u64 flags, void *data, u64 size)
+ *	Description
+ *		This helper is similar to bpf_perf_event_output except that it
+ *		it does not need a context argument.
+ *	Return
+ *		0 on success, or a negative error in case of failure.
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -2940,7 +2947,8 @@ union bpf_attr {
 	FN(probe_read_user),		\
 	FN(probe_read_kernel),		\
 	FN(probe_read_user_str),	\
-	FN(probe_read_kernel_str),
+	FN(probe_read_kernel_str),	\
+	FN(lsm_event_output),		\
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 0d1231d9c1ef..ff050fd71e9f 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3641,6 +3641,7 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
 		if (func_id != BPF_FUNC_perf_event_read &&
 		    func_id != BPF_FUNC_perf_event_output &&
 		    func_id != BPF_FUNC_skb_output &&
+		    func_id != BPF_FUNC_lsm_event_output &&
 		    func_id != BPF_FUNC_perf_event_read_value)
 			goto error;
 		break;
diff --git a/security/bpf/ops.c b/security/bpf/ops.c
index eb8a8db28109..e9aae2ce718c 100644
--- a/security/bpf/ops.c
+++ b/security/bpf/ops.c
@@ -129,6 +129,25 @@ int bpf_lsm_detach(const union bpf_attr *attr)
 const struct bpf_prog_ops lsm_prog_ops = {
 };
 
+BPF_CALL_4(bpf_lsm_event_output,
+	   struct bpf_map *, map, u64, flags, void *, data, u64, size)
+{
+	if (unlikely(flags & ~(BPF_F_INDEX_MASK)))
+		return -EINVAL;
+
+	return bpf_event_output(map, flags, data, size, NULL, 0, NULL);
+}
+
+static const struct bpf_func_proto bpf_lsm_event_output_proto =  {
+	.func		= bpf_lsm_event_output,
+	.gpl_only       = true,
+	.ret_type       = RET_INTEGER,
+	.arg1_type      = ARG_CONST_MAP_PTR,
+	.arg2_type      = ARG_ANYTHING,
+	.arg3_type      = ARG_PTR_TO_MEM,
+	.arg4_type      = ARG_CONST_SIZE_OR_ZERO,
+};
+
 static const struct bpf_func_proto *get_bpf_func_proto(enum bpf_func_id
 		func_id, const struct bpf_prog *prog)
 {
@@ -137,6 +156,8 @@ static const struct bpf_func_proto *get_bpf_func_proto(enum bpf_func_id
 		return &bpf_map_lookup_elem_proto;
 	case BPF_FUNC_get_current_pid_tgid:
 		return &bpf_get_current_pid_tgid_proto;
+	case BPF_FUNC_lsm_event_output:
+		return &bpf_lsm_event_output_proto;
 	default:
 		return NULL;
 	}
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index fc64ae865526..3511fa271c9b 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -2823,6 +2823,13 @@ union bpf_attr {
  * 	Return
  * 		On success, the strictly positive length of the string,	including
  * 		the trailing NUL character. On error, a negative value.
+ *
+ * int bpf_lsm_event_output(struct bpf_map *map, u64 flags, void *data, u64 size)
+ *	Description
+ *		This helper is similar to bpf_perf_event_output except that it
+ *		it does not need a context argument.
+ *	Return
+ *		0 on success, or a negative error in case of failure.
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -2940,7 +2947,8 @@ union bpf_attr {
 	FN(probe_read_user),		\
 	FN(probe_read_kernel),		\
 	FN(probe_read_user_str),	\
-	FN(probe_read_kernel_str),
+	FN(probe_read_kernel_str),	\
+	FN(lsm_event_output),		\
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
-- 
2.20.1


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

* [PATCH bpf-next v1 10/13] bpf: lsm: Handle attachment of the same program
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (8 preceding siblings ...)
  2019-12-20 15:42 ` [PATCH bpf-next v1 09/13] bpf: lsm: Add a helper function bpf_lsm_event_output KP Singh
@ 2019-12-20 15:42 ` KP Singh
  2019-12-24  6:38   ` Andrii Nakryiko
  2020-01-08 18:21   ` James Morris
  2019-12-20 15:42 ` [PATCH bpf-next v1 11/13] tools/libbpf: Add bpf_program__attach_lsm KP Singh
                   ` (6 subsequent siblings)
  16 siblings, 2 replies; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:42 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

Allow userspace to attach a newer version of a program without having
duplicates of the same program.

If BPF_F_ALLOW_OVERRIDE is passed, the attachment logic compares the
name of the new program to the names of existing attached programs. The
names are only compared till a "__" (or '\0', if there is no "__"). If
a successful match is found, the existing program is replaced with the
newer attachment.

./loader Attaches "env_dumper__v1" followed by "env_dumper__v2"
to the bprm_check_security hook..

./loader
./loader

Before:

  cat /sys/kernel/security/bpf/process_execution
  env_dumper__v1
  env_dumper__v2

After:

  cat /sys/kernel/security/bpf/process_execution
  env_dumper__v2

Signed-off-by: KP Singh <kpsingh@google.com>
---
 security/bpf/ops.c | 57 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/security/bpf/ops.c b/security/bpf/ops.c
index e9aae2ce718c..481e6ee75f27 100644
--- a/security/bpf/ops.c
+++ b/security/bpf/ops.c
@@ -64,11 +64,52 @@ static struct bpf_lsm_hook *get_hook_from_fd(int fd)
 	return ERR_PTR(ret);
 }
 
+/*
+ * match_prog_name matches the name of the program till "__"
+ * or the end of the string is encountered. This allows
+ * the matched program to be replaced by a newer version.
+ *
+ * For example:
+ *
+ *	env_dumper__v1 is matched with env_dumper__v2
+ *
+ */
+static bool match_prog_name(const char *a, const char *b)
+{
+	size_t m, n;
+	char *end;
+
+	end = strstr(a, "__");
+	n = end ? end - a : strlen(a);
+
+	end = strstr(b, "__");
+	m = end ? end - b : strlen(b);
+
+	if (m != n)
+		return false;
+
+	return strncmp(a, b, n) == 0;
+}
+
+static struct bpf_prog *find_attached_prog(struct bpf_prog_array *array,
+					   struct bpf_prog *prog)
+{
+	struct bpf_prog_array_item *item = array->items;
+
+	for (; item->prog; item++) {
+		if (match_prog_name(item->prog->aux->name, prog->aux->name))
+			return item->prog;
+	}
+
+	return NULL;
+}
+
 int bpf_lsm_attach(const union bpf_attr *attr, struct bpf_prog *prog)
 {
 	struct bpf_prog_array *old_array;
 	struct bpf_prog_array *new_array;
 	struct bpf_lsm_hook *h;
+	struct bpf_prog *old_prog = NULL;
 	int ret = 0;
 
 	h = get_hook_from_fd(attr->target_fd);
@@ -78,13 +119,27 @@ int bpf_lsm_attach(const union bpf_attr *attr, struct bpf_prog *prog)
 	mutex_lock(&h->mutex);
 	old_array = rcu_dereference_protected(h->progs,
 					      lockdep_is_held(&h->mutex));
+	/*
+	 * Check if a matching program already exists and replace
+	 * the existing program if BPF_F_ALLOW_OVERRIDE is specified in
+	 * the attach flags.
+	 */
+	if (old_array) {
+		old_prog = find_attached_prog(old_array, prog);
+		if (old_prog && !(attr->attach_flags & BPF_F_ALLOW_OVERRIDE)) {
+			ret = -EEXIST;
+			goto unlock;
+		}
+	}
 
-	ret = bpf_prog_array_copy(old_array, NULL, prog, &new_array);
+	ret = bpf_prog_array_copy(old_array, old_prog, prog, &new_array);
 	if (ret < 0)
 		goto unlock;
 
 	rcu_assign_pointer(h->progs, new_array);
 	bpf_prog_array_free(old_array);
+	if (old_prog)
+		bpf_prog_put(old_prog);
 
 unlock:
 	mutex_unlock(&h->mutex);
-- 
2.20.1


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

* [PATCH bpf-next v1 11/13] tools/libbpf: Add bpf_program__attach_lsm
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (9 preceding siblings ...)
  2019-12-20 15:42 ` [PATCH bpf-next v1 10/13] bpf: lsm: Handle attachment of the same program KP Singh
@ 2019-12-20 15:42 ` KP Singh
  2019-12-24  6:44   ` Andrii Nakryiko
  2020-01-08 18:24   ` James Morris
  2019-12-20 15:42 ` [PATCH bpf-next v1 12/13] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM KP Singh
                   ` (5 subsequent siblings)
  16 siblings, 2 replies; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:42 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

Add functionality in libbpf to attach eBPF program to LSM hooks.

Signed-off-by: KP Singh <kpsingh@google.com>
---
 tools/lib/bpf/libbpf.c   | 127 +++++++++++++++++++++++++++++++++++++--
 tools/lib/bpf/libbpf.h   |   2 +
 tools/lib/bpf/libbpf.map |   1 +
 3 files changed, 126 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index b0b27d8e5a37..ab2b23b4f21f 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -5122,8 +5122,8 @@ int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
 	return -ESRCH;
 }
 
-static inline int __btf__typdef_with_prefix(struct btf *btf, const char *name,
-					    const char *prefix)
+static inline int __btf__type_with_prefix(struct btf *btf, const char *name,
+					  const char *prefix)
 {
 
 	size_t prefix_len = strlen(prefix);
@@ -5149,9 +5149,9 @@ int libbpf_find_vmlinux_btf_id(const char *name,
 	}
 
 	if (attach_type == BPF_TRACE_RAW_TP)
-		err = __btf__typdef_with_prefix(btf, name, BTF_TRACE_PREFIX);
+		err = __btf__type_with_prefix(btf, name, BTF_TRACE_PREFIX);
 	else if (attach_type == BPF_LSM_MAC)
-		err = __btf__typdef_with_prefix(btf, name, BTF_LSM_PREFIX);
+		err = __btf__type_with_prefix(btf, name, BTF_LSM_PREFIX);
 	else
 		err = btf__find_by_name_kind(btf, name, BTF_KIND_FUNC);
 
@@ -5502,6 +5502,18 @@ struct bpf_link_fd {
 	int fd; /* hook FD */
 };
 
+/*
+ * The other attach types allow the link to be destroyed by using an ioctl or
+ * an operation on some file descriptor that describes the attachment. An LSM
+ * hook can have multiple programs attached to each hook, so the link needs to
+ * specify the program that must be detached when the link is destroyed.
+ */
+struct bpf_link_lsm {
+	struct bpf_link link;
+	int hook_fd;
+	int prog_fd;
+};
+
 static int bpf_link__destroy_perf_event(struct bpf_link *link)
 {
 	struct bpf_link_fd *l = (void *)link;
@@ -5876,6 +5888,113 @@ struct bpf_link *bpf_program__attach_trace(struct bpf_program *prog)
 	return (struct bpf_link *)link;
 }
 
+
+static int bpf_link__destroy_lsm(struct bpf_link *link)
+{
+	struct bpf_link_lsm *ll = container_of(link, struct bpf_link_lsm, link);
+	char errmsg[STRERR_BUFSIZE];
+	int ret;
+
+	ret = bpf_prog_detach2(ll->prog_fd, ll->hook_fd, BPF_LSM_MAC);
+	if (ret < 0) {
+		ret = -errno;
+		pr_warn("failed to detach from hook: %s\n",
+			libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
+		return ret;
+	}
+	close(ll->hook_fd);
+	return 0;
+}
+
+static const char *__lsm_hook_name(const char *title)
+{
+
+	int i;
+
+	if (!title)
+		return ERR_PTR(-EINVAL);
+
+	for (i = 0; i < ARRAY_SIZE(section_names); i++) {
+		if (section_names[i].prog_type != BPF_PROG_TYPE_LSM)
+			continue;
+
+		if (strncmp(title, section_names[i].sec,
+			    section_names[i].len)) {
+			pr_warn("title for a LSM prog must begin with '%s'\n",
+				section_names[i].sec);
+			return ERR_PTR(-EINVAL);
+		}
+
+		return title + section_names[i].len;
+	}
+
+	pr_warn("could not find section information for BPF_PROG_TYPE_LSM\n");
+	return ERR_PTR(-ESRCH);
+}
+
+struct bpf_link *bpf_program__attach_lsm(struct bpf_program *prog)
+{
+	char hook_path[PATH_MAX] = "/sys/kernel/security/bpf/";
+	const char *title, *hook_name;
+	char errmsg[STRERR_BUFSIZE];
+	int prog_fd, target_fd, ret;
+	struct bpf_link_lsm *link;
+
+	title = bpf_program__title(prog, false);
+	if (IS_ERR(title)) {
+		pr_warn("could not determine title of the program\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	hook_name = __lsm_hook_name(title);
+	if (IS_ERR(hook_name)) {
+		pr_warn("could not determine LSM hook name from title '%s'\n",
+			title);
+		return ERR_PTR(-EINVAL);
+	}
+
+	prog_fd = bpf_program__fd(prog);
+	if (prog_fd < 0) {
+		pr_warn("program '%s': can't attach before loaded\n", title);
+		return ERR_PTR(-EINVAL);
+	}
+
+	link = malloc(sizeof(*link));
+	if (!link)
+		return ERR_PTR(-ENOMEM);
+	link->link.destroy = &bpf_link__destroy_lsm;
+
+	/* Attach the BPF program to the given hook */
+	strncat(hook_path, hook_name,
+		sizeof(hook_path) - (strlen(hook_path) + 1));
+	target_fd = open(hook_path, O_RDWR);
+	if (target_fd < 0) {
+		ret = -errno;
+		pr_warn("program '%s': failed to open to hook '%s': %s\n",
+			title, hook_path,
+			libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
+		return ERR_PTR(ret);
+	}
+
+	ret = bpf_prog_attach(prog_fd, target_fd, BPF_LSM_MAC,
+			      BPF_F_ALLOW_OVERRIDE);
+	if (ret < 0) {
+		ret = -errno;
+		pr_warn("program '%s': failed to attach to hook '%s': %s\n",
+			title, hook_name,
+			libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
+		goto error;
+	}
+
+	link->hook_fd = target_fd;
+	link->prog_fd = prog_fd;
+	return &link->link;
+
+error:
+	close(target_fd);
+	return ERR_PTR(ret);
+}
+
 enum bpf_perf_event_ret
 bpf_perf_event_read_simple(void *mmap_mem, size_t mmap_size, size_t page_size,
 			   void **copy_mem, size_t *copy_size,
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 9cd69d602c82..655f27ad6ece 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -256,6 +256,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_insn;
 
 /*
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 3d396149755d..5d64ba9b2a43 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -213,4 +213,5 @@ LIBBPF_0.0.7 {
 	global:
 		bpf_program__is_lsm;
 		bpf_program__set_lsm;
+		bpf_program__attach_lsm;
 } LIBBPF_0.0.6;
-- 
2.20.1


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

* [PATCH bpf-next v1 12/13] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (10 preceding siblings ...)
  2019-12-20 15:42 ` [PATCH bpf-next v1 11/13] tools/libbpf: Add bpf_program__attach_lsm KP Singh
@ 2019-12-20 15:42 ` KP Singh
  2019-12-24  6:49   ` Andrii Nakryiko
  2020-01-08 18:25   ` James Morris
  2019-12-20 15:42 ` [PATCH bpf-next v1 13/13] bpf: lsm: Add Documentation KP Singh
                   ` (4 subsequent siblings)
  16 siblings, 2 replies; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:42 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

From: KP Singh <kpsingh@google.com>

* Load a BPF program that audits mprotect calls
* Attach the program to the "file_mprotect" LSM hook
* Verify if the program is actually loading by reading
  securityfs
* Initialize the perf events buffer and poll for audit events
* Do an mprotect on some memory allocated on the heap
* Verify if the audit event was received

Signed-off-by: KP Singh <kpsingh@google.com>
---
 MAINTAINERS                                   |   2 +
 .../bpf/prog_tests/lsm_mprotect_audit.c       | 129 ++++++++++++++++++
 .../selftests/bpf/progs/lsm_mprotect_audit.c  |  58 ++++++++
 3 files changed, 189 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
 create mode 100644 tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 681ae39bb2f0..652c93292ae9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3182,6 +3182,8 @@ L:	bpf@vger.kernel.org
 S:	Maintained
 F:	security/bpf/
 F:	include/linux/bpf_lsm.h
+F:	tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c
+F:	tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
 
 BROADCOM B44 10/100 ETHERNET DRIVER
 M:	Michael Chan <michael.chan@broadcom.com>
diff --git a/tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c b/tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
new file mode 100644
index 000000000000..953531cec9fd
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2019 Google LLC.
+ */
+
+#include <test_progs.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <malloc.h>
+
+#define EXPECTED_PROG_NAME "mprotect_audit"
+#define MPROTECT_AUDIT_MAGIC 0xDEAD
+
+struct mprotect_audit_log {
+	int is_heap, magic;
+};
+
+static void on_sample(void *ctx, int cpu, void *data, __u32 size)
+{
+	struct mprotect_audit_log *audit_log = data;
+	int duration = 0;
+
+	if (audit_log->magic != MPROTECT_AUDIT_MAGIC)
+		return;
+
+	if (CHECK(audit_log->is_heap != 1, "mprotect on heap",
+		  "is_heap = %d\n", audit_log->is_heap))
+		return;
+
+	*(bool *)ctx = true;
+}
+
+int heap_mprotect(void)
+{
+	void *buf;
+	long sz;
+
+	sz = sysconf(_SC_PAGESIZE);
+	if (sz < 0)
+		return sz;
+
+	buf = memalign(sz, 2 * sz);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	return mprotect(buf, sz, PROT_READ | PROT_EXEC);
+}
+
+void test_lsm_mprotect_audit(void)
+{
+	struct bpf_prog_load_attr attr = {
+		.file = "./lsm_mprotect_audit.o",
+	};
+
+	struct perf_buffer_opts pb_opts = {};
+	struct perf_buffer *pb = NULL;
+	struct bpf_link *link = NULL;
+	struct bpf_map *perf_buf_map;
+	struct bpf_object *prog_obj;
+	struct bpf_program *prog;
+	int err, prog_fd, sfs_fd;
+	char sfs_buf[1024];
+	int duration = 0;
+	bool passed = false;
+
+	err = bpf_prog_load_xattr(&attr, &prog_obj, &prog_fd);
+	if (CHECK(err, "prog_load lsm/file_mprotect",
+		  "err %d errno %d\n", err, errno))
+		goto close_prog;
+
+	prog = bpf_object__find_program_by_title(prog_obj, "lsm/file_mprotect");
+	if (CHECK(!prog, "find_prog", "lsm/file_mprotect not found\n"))
+		goto close_prog;
+
+	link = bpf_program__attach_lsm(prog);
+	if (CHECK(IS_ERR(link), "attach_lsm file_mprotect",
+				 "err %ld\n", PTR_ERR(link)))
+		goto close_prog;
+
+	sfs_fd = open("/sys/kernel/security/bpf/file_mprotect", O_RDONLY);
+	if (CHECK(sfs_fd < 0, "sfs_open file_mprotect",
+		  "err %d errno %d\n", sfs_fd, errno))
+		goto close_prog;
+
+	err = read(sfs_fd, sfs_buf, sizeof(sfs_buf));
+	if (CHECK(err < 0, "sfs_read file_mprotect",
+		  "err %d errno %d\n", sfs_fd, errno))
+		goto close_prog;
+
+	err = strncmp(sfs_buf, EXPECTED_PROG_NAME, strlen(EXPECTED_PROG_NAME));
+	if (CHECK(err != 0,
+		  "sfs_read value", "want = %s, got = %s\n",
+		  EXPECTED_PROG_NAME, sfs_buf))
+		goto close_prog;
+
+	perf_buf_map = bpf_object__find_map_by_name(prog_obj, "perf_buf_map");
+	if (CHECK(!perf_buf_map, "find_perf_buf_map", "not found\n"))
+		goto close_prog;
+
+	/* set up perf buffer */
+	pb_opts.sample_cb = on_sample;
+	pb_opts.ctx = &passed;
+	pb = perf_buffer__new(bpf_map__fd(perf_buf_map), 1, &pb_opts);
+	if (CHECK(IS_ERR(pb), "perf_buf__new", "err %ld\n", PTR_ERR(pb)))
+		goto close_prog;
+
+	err = heap_mprotect();
+	if (CHECK(err < 0, "heap_mprotect",
+		  "err %d errno %d\n", err, errno))
+		goto close_prog;
+
+	/* read perf buffer */
+	err = perf_buffer__poll(pb, 100);
+	if (CHECK(err < 0, "perf_buffer__poll", "err %d\n", err))
+		goto close_prog;
+
+	/*
+	 * make sure mprotect_audit program was triggered
+	 * and detected an mprotect on the heap
+	 */
+	CHECK_FAIL(!passed);
+
+close_prog:
+	perf_buffer__free(pb);
+	if (!IS_ERR_OR_NULL(link))
+		bpf_link__destroy(link);
+	bpf_object__close(prog_obj);
+}
diff --git a/tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c b/tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c
new file mode 100644
index 000000000000..85048315baae
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2019 Google LLC.
+ */
+
+#include <linux/bpf.h>
+#include <stdbool.h>
+#include "bpf_helpers.h"
+#include "bpf_trace_helpers.h"
+
+char _license[] SEC("license") = "GPL";
+struct {
+	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
+	__uint(key_size, sizeof(int));
+	__uint(value_size, sizeof(int));
+} perf_buf_map SEC(".maps");
+
+#define MPROTECT_AUDIT_MAGIC 0xDEAD
+
+struct mprotect_audit_log {
+	int is_heap, magic;
+};
+
+/*
+ * Define some of the structs used in the BPF program.
+ * Only the field names and their sizes need to be the
+ * same as the kernel type, the order is irrelevant.
+ */
+struct mm_struct {
+	unsigned long start_brk, brk, start_stack;
+};
+
+struct vm_area_struct {
+	unsigned long start_brk, brk, start_stack;
+	unsigned long vm_start, vm_end;
+	struct mm_struct *vm_mm;
+	unsigned long vm_flags;
+};
+
+BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
+	    struct vm_area_struct *, vma,
+	    unsigned long, reqprot, unsigned long, prot)
+{
+	struct mprotect_audit_log audit_log = {};
+	int is_heap = 0;
+
+	__builtin_preserve_access_index(({
+		is_heap = (vma->vm_start >= vma->vm_mm->start_brk &&
+				     vma->vm_end <= vma->vm_mm->brk);
+	}));
+
+	audit_log.magic = MPROTECT_AUDIT_MAGIC;
+	audit_log.is_heap = is_heap;
+	bpf_lsm_event_output(&perf_buf_map, BPF_F_CURRENT_CPU, &audit_log,
+			     sizeof(audit_log));
+	return 0;
+}
-- 
2.20.1


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

* [PATCH bpf-next v1 13/13] bpf: lsm: Add Documentation
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (11 preceding siblings ...)
  2019-12-20 15:42 ` [PATCH bpf-next v1 12/13] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM KP Singh
@ 2019-12-20 15:42 ` KP Singh
  2019-12-20 17:17 ` [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) Casey Schaufler
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 74+ messages in thread
From: KP Singh @ 2019-12-20 15:42 UTC (permalink / raw)
  To: linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

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>
---
 Documentation/security/bpf.rst   | 164 +++++++++++++++++++++++++++++++
 Documentation/security/index.rst |   1 +
 MAINTAINERS                      |   1 +
 3 files changed, 166 insertions(+)
 create mode 100644 Documentation/security/bpf.rst

diff --git a/Documentation/security/bpf.rst b/Documentation/security/bpf.rst
new file mode 100644
index 000000000000..898b7de148a0
--- /dev/null
+++ b/Documentation/security/bpf.rst
@@ -0,0 +1,164 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2019 Google LLC.
+
+==========================
+eBPF Linux Security Module
+==========================
+
+This LSM allows runtime instrumentation of the LSM hooks by privileged users to
+implement system-wide MAC (Mandatory Access Control) and Audit policies using
+eBPF. The LSM is priveleged and stackable and requires both ``CAP_SYS_ADMIN``
+and ``CAP_MAC_ADMIN`` for the loading of BPF programs and modification of MAC
+policies respectively.
+
+eBPF Programs
+==============
+
+`eBPF (extended BPF) <https://cilium.readthedocs.io/en/latest/bpf>`_ is a
+virtual machine-like construct in the Linux Kernel allowing the execution of
+verifiable, just-in-time compiled byte code at various points in the Kernel.
+
+The eBPF LSM adds a new type, ``BPF_PROG_TYPE_LSM``, of eBPF programs which
+have the following characteristics:
+
+	* Multiple eBPF programs can be attached to the same LSM hook.
+	* LSM hooks can return an ``-EPERM`` to indicate the decision of the
+	  MAC policy being enforced or simply be used for auditing.
+	* Allowing the eBPF programs to be attached to all the LSM hooks by
+	  making :doc:`/bpf/btf` type information available for all LSM hooks
+	  and allowing the BPF verifier to perform runtime relocations and
+	  validation on the programs.
+
+Structure
+---------
+
+The example shows an eBPF program that can be attached to the ``file_mprotect``
+LSM hook:
+
+.. c:function:: int file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot);
+
+eBPF programs that use :doc:`/bpf/btf` do not need to include kernel headers
+for accessing information from the attached eBPF program's context. They can
+simply declare the structures in the eBPF program and only specify the fields
+that need to be accessed.
+
+.. code-block:: c
+
+	struct mm_struct {
+		unsigned long start_brk, brk, start_stack;
+	};
+
+	struct vm_area_struct {
+		unsigned long start_brk, brk, start_stack;
+		unsigned long vm_start, vm_end;
+		struct mm_struct *vm_mm;
+	};
+
+
+.. 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.
+
+The eBPF programs can be declared using macros similar to the ``BPF_TRACE_<N>``
+macros defined in `tools/testing/selftests/bpf/bpf_trace_helpers.h`_. In this
+example:
+
+	* The LSM hook takes 3 args so we use ``BPF_TRACE_3``.
+	* ``"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
+
+	BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
+		    struct vm_area_struct *, vma,
+		    unsigned long, reqprot, unsigned long, prot)
+	{
+		int is_heap = 0;
+
+		__builtin_preserve_access_index(({
+			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 ``__builtin_preserve_access_index`` is a clang primitive that allows the
+BPF verifier to update the offsets for the access at runtime using the
+:doc:`/bpf/btf` information. Since the BPF verifier is aware of the types, it
+also validates all the accesses made to the various types in the eBPF program.
+
+Loading
+-------
+
+eBPP programs can be loaded with the :manpage:`bpf(2)` syscall's
+``BPF_PROG_LOAD`` operation or more simply by using the the libbpf helper
+``bpf_prog_load_xattr``:
+
+
+.. code-block:: c
+
+	struct bpf_prog_load_attr attr = {
+		.file = "./prog.o",
+	};
+	struct bpf_object *prog_obj;
+	struct bpf_program *prog;
+	int prog_fd;
+
+	bpf_prog_load_xattr(&attr, &prog_obj, &prog_fd);
+
+Attachment to LSM Hooks
+-----------------------
+
+The LSM creates a file in securityfs for each LSM hook to which eBPF programs
+can be attached 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 attachment can be verified by:
+
+.. code-block:: console
+
+	# cat /sys/kernel/security/bpf/file_mprotect
+	mprotect_audit
+
+If, when a program is attached, another program by the same name is already attached to the hook, that program is replaced.
+
+
+.. note:: This requires that the ``BPF_F_ALLOW_OVERRIDE`` flag be passed to
+	  the :manpage:`bpf(2)` syscall. If not, an ``-EEXIST`` error is returned instead.
+
+For conveniently versioning updating programs, program names are only compared up to the first ``"__"``. Thus if a program ``mprotect_audit__v1`` is attached and then ``mprotect_audit__v2`` is attached to the same hook, the latter will *replace* the former.
+
+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 program can be found in
+`tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c`_ and the corresponding
+userspace code in
+`tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c`_
+
+.. Links
+.. _tools/testing/selftests/bpf/bpf_trace_helpers.h:
+   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/selftests/bpf/bpf_trace_helpers.h
+.. _tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c:
+   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c
+.. _tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c:
+   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst
index fc503dd689a7..844463df4547 100644
--- a/Documentation/security/index.rst
+++ b/Documentation/security/index.rst
@@ -5,6 +5,7 @@ Security Documentation
 .. toctree::
    :maxdepth: 1
 
+   bpf
    credentials
    IMA-templates
    keys/index
diff --git a/MAINTAINERS b/MAINTAINERS
index 652c93292ae9..6f34c24519ca 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3184,6 +3184,7 @@ F:	security/bpf/
 F:	include/linux/bpf_lsm.h
 F:	tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c
 F:	tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
+F:	Documentation/security/bpf.rst
 
 BROADCOM B44 10/100 ETHERNET DRIVER
 M:	Michael Chan <michael.chan@broadcom.com>
-- 
2.20.1


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (12 preceding siblings ...)
  2019-12-20 15:42 ` [PATCH bpf-next v1 13/13] bpf: lsm: Add Documentation KP Singh
@ 2019-12-20 17:17 ` Casey Schaufler
  2019-12-20 17:38   ` KP Singh
  2019-12-20 22:46 ` Mickaël Salaün
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 74+ messages in thread
From: Casey Schaufler @ 2019-12-20 17:17 UTC (permalink / raw)
  To: KP Singh, linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

On 12/20/2019 7:41 AM, KP Singh wrote:
> From: KP Singh <kpsingh@google.com>
>
> This patch series is a continuation of the KRSI RFC
> (https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/)
>
> # Motivation
>
> Google does rich analysis of runtime security data collected from
> internal Linux deployments (corporate devices and servers) 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 proposes a new stackable and privileged LSM which allows
> the LSM hooks to be implemented using eBPF. 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 LSM introduces a new eBPF (https://docs.cilium.io/en/v1.6/bpf/)
> program type, BPF_PROG_TYPE_LSM, which can only be attached to a LSM
> hook.  All LSM hooks are exposed as files in securityfs. Attachment
> requires CAP_SYS_ADMIN for loading eBPF programs and CAP_MAC_ADMIN for
> modifying MAC policies.
>
> The eBPF programs are passed the same arguments as the LSM hooks and
> executed in the body of the hook.

This effectively exposes the LSM hooks as external APIs.
It would mean that we can't change or delete them. That
would be bad.


>  If any of the eBPF programs returns an
> error (like ENOPERM), the behaviour represented by the hook is denied.
>
> Audit logs can be written using a format chosen by the eBPF program to
> the perf events buffer and can be further processed in user-space.
>
> # Limitations of RFC v1
>
> In the previous design
> (https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/),
> the BPF programs received a context which could be queried to retrieve
> specific pieces of information using specific helpers.
>
> For example, a program that attaches to the file_mprotect LSM hook and
> queries the VMA region could have had the following context:
>
> // Special context for the hook.
> struct bpf_mprotect_ctx {
> 	struct vm_area_struct *vma;
> };
>
> and accessed the fields using a hypothetical helper
> "bpf_mprotect_vma_get_start:
>
> SEC("lsm/file_mprotect")
> int mprotect_audit(bpf_mprotect_ctx *ctx)
> {
> 	unsigned long vm_start = bpf_mprotect_vma_get_start(ctx);
> 	return 0;
> }
>
> or directly read them from the context by updating the verifier to allow
> accessing the fields:
>
> int mprotect_audit(bpf_mprotect_ctx *ctx)
> {
> 	unsigned long vm_start = ctx->vma->vm_start;
> 	return 0;
> }
>
> As we prototyped policies based on this design, we realized that this
> approach is not general enough. Adding helpers or verifier code for all
> usages would imply a high maintenance cost while severely restricting
> the instrumentation capabilities which is the key value add of our
> eBPF-based LSM.
>
> Feedback from the BPF maintainers at Linux Plumbers also pushed us
> towards the following, more general, approach.
>
> # 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:
>
> /* Clang builtin to handle field accesses. */
> #define _(P) (__builtin_preserve_access_index(P))
>
> // Only declare the structure and fields intended to be used
> // in the program
> struct vm_area_struct {
> 	unsigned long vm_start;
> };
>
> // Declare the eBPF program mprotect_audit which attaches to
> // to the file_mprotect LSM hook and accepts three arguments.
> BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
> 	    struct vm_area_struct *, vma,
> 	    unsigned long, reqprot, unsigned long, prot
> {
> 	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 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 previous design
> (https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/).
>
> # Distinction from Landlock
>
> We believe there exist two distinct use-cases with distinct set of users:
>
> * Unprivileged processes voluntarily relinquishing privileges with the
>   primary users being software developers.
>
> * Flexible privileged (CAP_MAC_ADMIN, CAP_SYS_ADMIN) MAC and Audit with
>   the primary users being system policy admins.
>
> These use-cases imply different APIs and trade-offs:
>
> * The unprivileged use case requires defining more stable and custom APIs
>   (through opaque contexts and precise helpers).
>
> * Privileged Audit and MAC requires deeper introspection of the kernel
>   data structures to maximise the flexibility that can be achieved without
>   kernel modification.
>
> Landlock has demonstrated filesystem sandboxes and now Ptrace access
> control in its patches which are excellent use cases for an unprivileged
> process voluntarily relinquishing privileges.
>
> However, Landlock has expanded its original goal, "towards unprivileged
> sandboxing", to being a "low-level framework to build
> access-control/audit systems" (https://landlock.io). We feel that the
> design and implementation are still driven by the constraints and
> trade-offs of the former use-case, and do not provide a satisfactory
> solution to the latter.
>
> We also believe that our approach, direct access to common kernel data
> structures as with BTF, is inappropriate for unprivileged processes and
> probably not a good option for Landlock.
>
> In conclusion, we feel that the design for a privileged LSM and
> unprivileged LSM are mutually exclusive and that one cannot be built
> "on-top-of" the other. Doing so would limit the capabilities of what can
> be done for an LSM that provides flexible audit and MAC capabilities or
> provide in-appropriate access to kernel internals to an unprivileged
> process.
>
> Furthermore, the Landlock design supports its historical use-case only
> when unprivileged eBPF is allowed. This is something that warrants
> discussion before an unprivileged LSM that uses eBPF is upstreamed.
>
> # Why not tracepoints or kprobes?
>
> In order to do MAC with tracepoints or kprobes, we would need to
> override the return value of the security hook. This is not possible
> with tracepoints or call-site kprobes.
>
> Attaching to the return boundary (kretprobe) implies that BPF programs
> would always get called after all the other LSM hooks are called and
> clobber the pre-existing LSM semantics.
>
> Enforcing MAC policy with an actual LSM helps leverage the verified
> semantics of the framework.
>
> # 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 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 (13):
>   bpf: Refactor BPF_EVENT context macros to its own header.
>   bpf: lsm: Add a skeleton and config options
>   bpf: lsm: Introduce types for eBPF based LSM
>   bpf: lsm: Allow btf_id based attachment for LSM hooks
>   tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM
>   bpf: lsm: Init Hooks and create files in securityfs
>   bpf: lsm: Implement attach, detach and execution.
>   bpf: lsm: Show attached program names in hook read handler.
>   bpf: lsm: Add a helper function bpf_lsm_event_output
>   bpf: lsm: Handle attachment of the same program
>   tools/libbpf: Add bpf_program__attach_lsm
>   bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
>   bpf: lsm: Add Documentation
>
>  Documentation/security/bpf.rst                |  164 +++
>  Documentation/security/index.rst              |    1 +
>  MAINTAINERS                                   |   11 +
>  include/linux/bpf_event.h                     |   78 ++
>  include/linux/bpf_lsm.h                       |   25 +
>  include/linux/bpf_types.h                     |    4 +
>  include/trace/bpf_probe.h                     |   30 +-
>  include/uapi/linux/bpf.h                      |   12 +-
>  kernel/bpf/syscall.c                          |   10 +
>  kernel/bpf/verifier.c                         |   84 +-
>  kernel/trace/bpf_trace.c                      |   24 +-
>  security/Kconfig                              |   11 +-
>  security/Makefile                             |    2 +
>  security/bpf/Kconfig                          |   25 +
>  security/bpf/Makefile                         |    7 +
>  security/bpf/include/bpf_lsm.h                |   63 +
>  security/bpf/include/fs.h                     |   23 +
>  security/bpf/include/hooks.h                  | 1015 +++++++++++++++++
>  security/bpf/lsm.c                            |  160 +++
>  security/bpf/lsm_fs.c                         |  176 +++
>  security/bpf/ops.c                            |  224 ++++
>  tools/include/uapi/linux/bpf.h                |   12 +-
>  tools/lib/bpf/bpf.c                           |    2 +-
>  tools/lib/bpf/bpf.h                           |    6 +
>  tools/lib/bpf/libbpf.c                        |  163 ++-
>  tools/lib/bpf/libbpf.h                        |    4 +
>  tools/lib/bpf/libbpf.map                      |    7 +
>  tools/lib/bpf/libbpf_probes.c                 |    1 +
>  .../bpf/prog_tests/lsm_mprotect_audit.c       |  129 +++
>  .../selftests/bpf/progs/lsm_mprotect_audit.c  |   58 +
>  30 files changed, 2451 insertions(+), 80 deletions(-)
>  create mode 100644 Documentation/security/bpf.rst
>  create mode 100644 include/linux/bpf_event.h
>  create mode 100644 include/linux/bpf_lsm.h
>  create mode 100644 security/bpf/Kconfig
>  create mode 100644 security/bpf/Makefile
>  create mode 100644 security/bpf/include/bpf_lsm.h
>  create mode 100644 security/bpf/include/fs.h
>  create mode 100644 security/bpf/include/hooks.h
>  create mode 100644 security/bpf/lsm.c
>  create mode 100644 security/bpf/lsm_fs.c
>  create mode 100644 security/bpf/ops.c
>  create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
>  create mode 100644 tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c
>


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-20 17:17 ` [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) Casey Schaufler
@ 2019-12-20 17:38   ` KP Singh
  2019-12-30 19:15     ` Kees Cook
  0 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2019-12-20 17:38 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

Hi Casey,

Thanks for taking a look!

On Fri, Dec 20, 2019 at 6:17 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
>
> On 12/20/2019 7:41 AM, KP Singh wrote:
> > From: KP Singh <kpsingh@google.com>
> >
> > This patch series is a continuation of the KRSI RFC
> > (https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/)
> >
> > # Motivation
> >
> > Google does rich analysis of runtime security data collected from
> > internal Linux deployments (corporate devices and servers) 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 proposes a new stackable and privileged LSM which allows
> > the LSM hooks to be implemented using eBPF. 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 LSM introduces a new eBPF (https://docs.cilium.io/en/v1.6/bpf/)
> > program type, BPF_PROG_TYPE_LSM, which can only be attached to a LSM
> > hook.  All LSM hooks are exposed as files in securityfs. Attachment
> > requires CAP_SYS_ADMIN for loading eBPF programs and CAP_MAC_ADMIN for
> > modifying MAC policies.
> >
> > The eBPF programs are passed the same arguments as the LSM hooks and
> > executed in the body of the hook.
>
> This effectively exposes the LSM hooks as external APIs.
> It would mean that we can't change or delete them. That
> would be bad.

Perhaps this should have been clearer, we *do not* want to make LSM hooks
a stable API and expect the eBPF programs to adapt when such changes occur.

Based on our comparison with the previous approach, this still ends up
being a better trade-off (w.r.t. maintenance) when compared to adding
specific helpers or verifier logic for  each new hook or field that
needs to be exposed.

- KP

>
>
> >  If any of the eBPF programs returns an
> > error (like ENOPERM), the behaviour represented by the hook is denied.
> >
> > Audit logs can be written using a format chosen by the eBPF program to
> > the perf events buffer and can be further processed in user-space.
> >
> > # Limitations of RFC v1
> >
> > In the previous design
> > (https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/),
> > the BPF programs received a context which could be queried to retrieve
> > specific pieces of information using specific helpers.
> >
> > For example, a program that attaches to the file_mprotect LSM hook and
> > queries the VMA region could have had the following context:
> >
> > // Special context for the hook.
> > struct bpf_mprotect_ctx {
> >       struct vm_area_struct *vma;
> > };
> >
> > and accessed the fields using a hypothetical helper
> > "bpf_mprotect_vma_get_start:
> >
> > SEC("lsm/file_mprotect")
> > int mprotect_audit(bpf_mprotect_ctx *ctx)
> > {
> >       unsigned long vm_start = bpf_mprotect_vma_get_start(ctx);
> >       return 0;
> > }
> >
> > or directly read them from the context by updating the verifier to allow
> > accessing the fields:
> >
> > int mprotect_audit(bpf_mprotect_ctx *ctx)
> > {
> >       unsigned long vm_start = ctx->vma->vm_start;
> >       return 0;
> > }
> >
> > As we prototyped policies based on this design, we realized that this
> > approach is not general enough. Adding helpers or verifier code for all
> > usages would imply a high maintenance cost while severely restricting
> > the instrumentation capabilities which is the key value add of our
> > eBPF-based LSM.
> >
> > Feedback from the BPF maintainers at Linux Plumbers also pushed us
> > towards the following, more general, approach.
> >
> > # 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:
> >
> > /* Clang builtin to handle field accesses. */
> > #define _(P) (__builtin_preserve_access_index(P))
> >
> > // Only declare the structure and fields intended to be used
> > // in the program
> > struct vm_area_struct {
> >       unsigned long vm_start;
> > };
> >
> > // Declare the eBPF program mprotect_audit which attaches to
> > // to the file_mprotect LSM hook and accepts three arguments.
> > BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
> >           struct vm_area_struct *, vma,
> >           unsigned long, reqprot, unsigned long, prot
> > {
> >       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 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 previous design
> > (https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/).
> >
> > # Distinction from Landlock
> >
> > We believe there exist two distinct use-cases with distinct set of users:
> >
> > * Unprivileged processes voluntarily relinquishing privileges with the
> >   primary users being software developers.
> >
> > * Flexible privileged (CAP_MAC_ADMIN, CAP_SYS_ADMIN) MAC and Audit with
> >   the primary users being system policy admins.
> >
> > These use-cases imply different APIs and trade-offs:
> >
> > * The unprivileged use case requires defining more stable and custom APIs
> >   (through opaque contexts and precise helpers).
> >
> > * Privileged Audit and MAC requires deeper introspection of the kernel
> >   data structures to maximise the flexibility that can be achieved without
> >   kernel modification.
> >
> > Landlock has demonstrated filesystem sandboxes and now Ptrace access
> > control in its patches which are excellent use cases for an unprivileged
> > process voluntarily relinquishing privileges.
> >
> > However, Landlock has expanded its original goal, "towards unprivileged
> > sandboxing", to being a "low-level framework to build
> > access-control/audit systems" (https://landlock.io). We feel that the
> > design and implementation are still driven by the constraints and
> > trade-offs of the former use-case, and do not provide a satisfactory
> > solution to the latter.
> >
> > We also believe that our approach, direct access to common kernel data
> > structures as with BTF, is inappropriate for unprivileged processes and
> > probably not a good option for Landlock.
> >
> > In conclusion, we feel that the design for a privileged LSM and
> > unprivileged LSM are mutually exclusive and that one cannot be built
> > "on-top-of" the other. Doing so would limit the capabilities of what can
> > be done for an LSM that provides flexible audit and MAC capabilities or
> > provide in-appropriate access to kernel internals to an unprivileged
> > process.
> >
> > Furthermore, the Landlock design supports its historical use-case only
> > when unprivileged eBPF is allowed. This is something that warrants
> > discussion before an unprivileged LSM that uses eBPF is upstreamed.
> >
> > # Why not tracepoints or kprobes?
> >
> > In order to do MAC with tracepoints or kprobes, we would need to
> > override the return value of the security hook. This is not possible
> > with tracepoints or call-site kprobes.
> >
> > Attaching to the return boundary (kretprobe) implies that BPF programs
> > would always get called after all the other LSM hooks are called and
> > clobber the pre-existing LSM semantics.
> >
> > Enforcing MAC policy with an actual LSM helps leverage the verified
> > semantics of the framework.
> >
> > # 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 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 (13):
> >   bpf: Refactor BPF_EVENT context macros to its own header.
> >   bpf: lsm: Add a skeleton and config options
> >   bpf: lsm: Introduce types for eBPF based LSM
> >   bpf: lsm: Allow btf_id based attachment for LSM hooks
> >   tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM
> >   bpf: lsm: Init Hooks and create files in securityfs
> >   bpf: lsm: Implement attach, detach and execution.
> >   bpf: lsm: Show attached program names in hook read handler.
> >   bpf: lsm: Add a helper function bpf_lsm_event_output
> >   bpf: lsm: Handle attachment of the same program
> >   tools/libbpf: Add bpf_program__attach_lsm
> >   bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
> >   bpf: lsm: Add Documentation
> >
> >  Documentation/security/bpf.rst                |  164 +++
> >  Documentation/security/index.rst              |    1 +
> >  MAINTAINERS                                   |   11 +
> >  include/linux/bpf_event.h                     |   78 ++
> >  include/linux/bpf_lsm.h                       |   25 +
> >  include/linux/bpf_types.h                     |    4 +
> >  include/trace/bpf_probe.h                     |   30 +-
> >  include/uapi/linux/bpf.h                      |   12 +-
> >  kernel/bpf/syscall.c                          |   10 +
> >  kernel/bpf/verifier.c                         |   84 +-
> >  kernel/trace/bpf_trace.c                      |   24 +-
> >  security/Kconfig                              |   11 +-
> >  security/Makefile                             |    2 +
> >  security/bpf/Kconfig                          |   25 +
> >  security/bpf/Makefile                         |    7 +
> >  security/bpf/include/bpf_lsm.h                |   63 +
> >  security/bpf/include/fs.h                     |   23 +
> >  security/bpf/include/hooks.h                  | 1015 +++++++++++++++++
> >  security/bpf/lsm.c                            |  160 +++
> >  security/bpf/lsm_fs.c                         |  176 +++
> >  security/bpf/ops.c                            |  224 ++++
> >  tools/include/uapi/linux/bpf.h                |   12 +-
> >  tools/lib/bpf/bpf.c                           |    2 +-
> >  tools/lib/bpf/bpf.h                           |    6 +
> >  tools/lib/bpf/libbpf.c                        |  163 ++-
> >  tools/lib/bpf/libbpf.h                        |    4 +
> >  tools/lib/bpf/libbpf.map                      |    7 +
> >  tools/lib/bpf/libbpf_probes.c                 |    1 +
> >  .../bpf/prog_tests/lsm_mprotect_audit.c       |  129 +++
> >  .../selftests/bpf/progs/lsm_mprotect_audit.c  |   58 +
> >  30 files changed, 2451 insertions(+), 80 deletions(-)
> >  create mode 100644 Documentation/security/bpf.rst
> >  create mode 100644 include/linux/bpf_event.h
> >  create mode 100644 include/linux/bpf_lsm.h
> >  create mode 100644 security/bpf/Kconfig
> >  create mode 100644 security/bpf/Makefile
> >  create mode 100644 security/bpf/include/bpf_lsm.h
> >  create mode 100644 security/bpf/include/fs.h
> >  create mode 100644 security/bpf/include/hooks.h
> >  create mode 100644 security/bpf/lsm.c
> >  create mode 100644 security/bpf/lsm_fs.c
> >  create mode 100644 security/bpf/ops.c
> >  create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
> >  create mode 100644 tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c
> >
>

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

* Re: [PATCH bpf-next v1 01/13] bpf: Refactor BPF_EVENT context macros to its own header.
  2019-12-20 15:41 ` [PATCH bpf-next v1 01/13] bpf: Refactor BPF_EVENT context macros to its own header KP Singh
@ 2019-12-20 20:10   ` Andrii Nakryiko
  2019-12-20 20:26     ` KP Singh
  0 siblings, 1 reply; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-20 20:10 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> These macros are useful for other program types than tracing.
> i.e. KRSI (an upccoming BPF based LSM) which does not use
> BPF_PROG_TYPE_TRACE but uses verifiable BTF accesses similar
> to raw tracepoints.
>
> Signed-off-by: KP Singh <kpsingh@google.com>
> ---
>  include/linux/bpf_event.h | 78 +++++++++++++++++++++++++++++++++++++++
>  include/trace/bpf_probe.h | 30 +--------------
>  kernel/trace/bpf_trace.c  | 24 +-----------
>  3 files changed, 81 insertions(+), 51 deletions(-)
>  create mode 100644 include/linux/bpf_event.h
>
> diff --git a/include/linux/bpf_event.h b/include/linux/bpf_event.h
> new file mode 100644
> index 000000000000..353eb1f5a3d0
> --- /dev/null
> +++ b/include/linux/bpf_event.h
> @@ -0,0 +1,78 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +
> +/*
> + * Copyright (c) 2018 Facebook
> + * Copyright 2019 Google LLC.
> + */
> +
> +#ifndef _LINUX_BPF_EVENT_H
> +#define _LINUX_BPF_EVENT_H
> +
> +#ifdef CONFIG_BPF_EVENTS
> +
> +/* cast any integer, pointer, or small struct to u64 */
> +#define UINTTYPE(size) \
> +       __typeof__(__builtin_choose_expr(size == 1,  (u8)1, \
> +                  __builtin_choose_expr(size == 2, (u16)2, \
> +                  __builtin_choose_expr(size == 4, (u32)3, \
> +                  __builtin_choose_expr(size == 8, (u64)4, \
> +                                        (void)5)))))
> +#define __CAST_TO_U64(x) ({ \
> +       typeof(x) __src = (x); \
> +       UINTTYPE(sizeof(x)) __dst; \
> +       memcpy(&__dst, &__src, sizeof(__dst)); \
> +       (u64)__dst; })
> +
> +#define __CAST0(...) 0
> +#define __CAST1(a, ...) __CAST_TO_U64(a)
> +#define __CAST2(a, ...) __CAST_TO_U64(a), __CAST1(__VA_ARGS__)
> +#define __CAST3(a, ...) __CAST_TO_U64(a), __CAST2(__VA_ARGS__)
> +#define __CAST4(a, ...) __CAST_TO_U64(a), __CAST3(__VA_ARGS__)
> +#define __CAST5(a, ...) __CAST_TO_U64(a), __CAST4(__VA_ARGS__)
> +#define __CAST6(a, ...) __CAST_TO_U64(a), __CAST5(__VA_ARGS__)
> +#define __CAST7(a, ...) __CAST_TO_U64(a), __CAST6(__VA_ARGS__)
> +#define __CAST8(a, ...) __CAST_TO_U64(a), __CAST7(__VA_ARGS__)
> +#define __CAST9(a, ...) __CAST_TO_U64(a), __CAST8(__VA_ARGS__)
> +#define __CAST10(a ,...) __CAST_TO_U64(a), __CAST9(__VA_ARGS__)
> +#define __CAST11(a, ...) __CAST_TO_U64(a), __CAST10(__VA_ARGS__)
> +#define __CAST12(a, ...) __CAST_TO_U64(a), __CAST11(__VA_ARGS__)
> +/* tracepoints with more than 12 arguments will hit build error */
> +#define CAST_TO_U64(...) CONCATENATE(__CAST, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
> +
> +#define UINTTYPE(size) \
> +       __typeof__(__builtin_choose_expr(size == 1,  (u8)1, \
> +                  __builtin_choose_expr(size == 2, (u16)2, \
> +                  __builtin_choose_expr(size == 4, (u32)3, \
> +                  __builtin_choose_expr(size == 8, (u64)4, \
> +                                        (void)5)))))

Is it the same macro as above?

> +

[...]

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

* Re: [PATCH bpf-next v1 01/13] bpf: Refactor BPF_EVENT context macros to its own header.
  2019-12-20 20:10   ` Andrii Nakryiko
@ 2019-12-20 20:26     ` KP Singh
  0 siblings, 0 replies; 74+ messages in thread
From: KP Singh @ 2019-12-20 20:26 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On 20-Dez 12:10, Andrii Nakryiko wrote:
> On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
> >
> > From: KP Singh <kpsingh@google.com>
> >
> > These macros are useful for other program types than tracing.
> > i.e. KRSI (an upccoming BPF based LSM) which does not use
> > BPF_PROG_TYPE_TRACE but uses verifiable BTF accesses similar
> > to raw tracepoints.
> >
> > Signed-off-by: KP Singh <kpsingh@google.com>
> > ---
> >  include/linux/bpf_event.h | 78 +++++++++++++++++++++++++++++++++++++++
> >  include/trace/bpf_probe.h | 30 +--------------
> >  kernel/trace/bpf_trace.c  | 24 +-----------
> >  3 files changed, 81 insertions(+), 51 deletions(-)
> >  create mode 100644 include/linux/bpf_event.h
> >
> > diff --git a/include/linux/bpf_event.h b/include/linux/bpf_event.h
> > new file mode 100644
> > index 000000000000..353eb1f5a3d0
> > --- /dev/null
> > +++ b/include/linux/bpf_event.h
> > @@ -0,0 +1,78 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +
> > +
> > +/*
> > + * Copyright (c) 2018 Facebook
> > + * Copyright 2019 Google LLC.
> > + */
> > +
> > +#ifndef _LINUX_BPF_EVENT_H
> > +#define _LINUX_BPF_EVENT_H
> > +
> > +#ifdef CONFIG_BPF_EVENTS
> > +
> > +/* cast any integer, pointer, or small struct to u64 */
> > +#define UINTTYPE(size) \
> > +       __typeof__(__builtin_choose_expr(size == 1,  (u8)1, \
> > +                  __builtin_choose_expr(size == 2, (u16)2, \
> > +                  __builtin_choose_expr(size == 4, (u32)3, \
> > +                  __builtin_choose_expr(size == 8, (u64)4, \
> > +                                        (void)5)))))
> > +#define __CAST_TO_U64(x) ({ \
> > +       typeof(x) __src = (x); \
> > +       UINTTYPE(sizeof(x)) __dst; \
> > +       memcpy(&__dst, &__src, sizeof(__dst)); \
> > +       (u64)__dst; })
> > +
> > +#define __CAST0(...) 0
> > +#define __CAST1(a, ...) __CAST_TO_U64(a)
> > +#define __CAST2(a, ...) __CAST_TO_U64(a), __CAST1(__VA_ARGS__)
> > +#define __CAST3(a, ...) __CAST_TO_U64(a), __CAST2(__VA_ARGS__)
> > +#define __CAST4(a, ...) __CAST_TO_U64(a), __CAST3(__VA_ARGS__)
> > +#define __CAST5(a, ...) __CAST_TO_U64(a), __CAST4(__VA_ARGS__)
> > +#define __CAST6(a, ...) __CAST_TO_U64(a), __CAST5(__VA_ARGS__)
> > +#define __CAST7(a, ...) __CAST_TO_U64(a), __CAST6(__VA_ARGS__)
> > +#define __CAST8(a, ...) __CAST_TO_U64(a), __CAST7(__VA_ARGS__)
> > +#define __CAST9(a, ...) __CAST_TO_U64(a), __CAST8(__VA_ARGS__)
> > +#define __CAST10(a ,...) __CAST_TO_U64(a), __CAST9(__VA_ARGS__)
> > +#define __CAST11(a, ...) __CAST_TO_U64(a), __CAST10(__VA_ARGS__)
> > +#define __CAST12(a, ...) __CAST_TO_U64(a), __CAST11(__VA_ARGS__)
> > +/* tracepoints with more than 12 arguments will hit build error */
> > +#define CAST_TO_U64(...) CONCATENATE(__CAST, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
> > +
> > +#define UINTTYPE(size) \
> > +       __typeof__(__builtin_choose_expr(size == 1,  (u8)1, \
> > +                  __builtin_choose_expr(size == 2, (u16)2, \
> > +                  __builtin_choose_expr(size == 4, (u32)3, \
> > +                  __builtin_choose_expr(size == 8, (u64)4, \
> > +                                        (void)5)))))
> 
> Is it the same macro as above?

Yes, sorry did not notice this. Will fix it in the next revision.

- KP

> 
> > +
> 
> [...]

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (13 preceding siblings ...)
  2019-12-20 17:17 ` [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) Casey Schaufler
@ 2019-12-20 22:46 ` Mickaël Salaün
  2019-12-30 19:30   ` Kees Cook
  2019-12-22  1:27 ` Alexei Starovoitov
  2019-12-24  6:51 ` Andrii Nakryiko
  16 siblings, 1 reply; 74+ messages in thread
From: Mickaël Salaün @ 2019-12-20 22:46 UTC (permalink / raw)
  To: KP Singh, linux-kernel, bpf, linux-security-module
  Cc: Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner, Florent Revest,
	Brendan Jackman, Martin KaFai Lau, Song Liu, Yonghong Song,
	Serge E. Hallyn, Mauro Carvalho Chehab, David S. Miller,
	Greg Kroah-Hartman, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer,
	Mickaël Salaün


On 20/12/2019 16:41, KP Singh wrote:
> From: KP Singh <kpsingh@google.com>
> 
> This patch series is a continuation of the KRSI RFC
> (https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/)
> 
> # Motivation
> 
> Google does rich analysis of runtime security data collected from
> internal Linux deployments (corporate devices and servers) 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 proposes a new stackable and privileged LSM which allows
> the LSM hooks to be implemented using eBPF. 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 LSM introduces a new eBPF (https://docs.cilium.io/en/v1.6/bpf/)
> program type, BPF_PROG_TYPE_LSM, which can only be attached to a LSM
> hook.  All LSM hooks are exposed as files in securityfs. Attachment
> requires CAP_SYS_ADMIN for loading eBPF programs and CAP_MAC_ADMIN for
> modifying MAC policies.
> 
> The eBPF programs are passed the same arguments as the LSM hooks and
> executed in the body of the hook. If any of the eBPF programs returns an
> error (like ENOPERM), the behaviour represented by the hook is denied.
> 
> Audit logs can be written using a format chosen by the eBPF program to
> the perf events buffer and can be further processed in user-space.
> 
> # Limitations of RFC v1
> 
> In the previous design
> (https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/),
> the BPF programs received a context which could be queried to retrieve
> specific pieces of information using specific helpers.
> 
> For example, a program that attaches to the file_mprotect LSM hook and
> queries the VMA region could have had the following context:
> 
> // Special context for the hook.
> struct bpf_mprotect_ctx {
> 	struct vm_area_struct *vma;
> };
> 
> and accessed the fields using a hypothetical helper
> "bpf_mprotect_vma_get_start:
> 
> SEC("lsm/file_mprotect")
> int mprotect_audit(bpf_mprotect_ctx *ctx)
> {
> 	unsigned long vm_start = bpf_mprotect_vma_get_start(ctx);
> 	return 0;
> }
> 
> or directly read them from the context by updating the verifier to allow
> accessing the fields:
> 
> int mprotect_audit(bpf_mprotect_ctx *ctx)
> {
> 	unsigned long vm_start = ctx->vma->vm_start;
> 	return 0;
> }
> 
> As we prototyped policies based on this design, we realized that this
> approach is not general enough. Adding helpers or verifier code for all
> usages would imply a high maintenance cost while severely restricting
> the instrumentation capabilities which is the key value add of our
> eBPF-based LSM.
> 
> Feedback from the BPF maintainers at Linux Plumbers also pushed us
> towards the following, more general, approach.
> 
> # 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:
> 
> /* Clang builtin to handle field accesses. */
> #define _(P) (__builtin_preserve_access_index(P))
> 
> // Only declare the structure and fields intended to be used
> // in the program
> struct vm_area_struct {
> 	unsigned long vm_start;
> };
> 
> // Declare the eBPF program mprotect_audit which attaches to
> // to the file_mprotect LSM hook and accepts three arguments.
> BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
> 	    struct vm_area_struct *, vma,
> 	    unsigned long, reqprot, unsigned long, prot
> {
> 	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 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 previous design
> (https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/).
> 
> # Distinction from Landlock
> 
> We believe there exist two distinct use-cases with distinct set of users:
> 
> * Unprivileged processes voluntarily relinquishing privileges with the
>    primary users being software developers.
> 
> * Flexible privileged (CAP_MAC_ADMIN, CAP_SYS_ADMIN) MAC and Audit with
>    the primary users being system policy admins.
> 
> These use-cases imply different APIs and trade-offs:
> 
> * The unprivileged use case requires defining more stable and custom APIs
>    (through opaque contexts and precise helpers).
> 
> * Privileged Audit and MAC requires deeper introspection of the kernel
>    data structures to maximise the flexibility that can be achieved without
>    kernel modification.
> 
> Landlock has demonstrated filesystem sandboxes and now Ptrace access
> control in its patches which are excellent use cases for an unprivileged
> process voluntarily relinquishing privileges.
> 
> However, Landlock has expanded its original goal, "towards unprivileged
> sandboxing", to being a "low-level framework to build
> access-control/audit systems" (https://landlock.io). We feel that the
> design and implementation are still driven by the constraints and
> trade-offs of the former use-case, and do not provide a satisfactory
> solution to the latter.
> 
> We also believe that our approach, direct access to common kernel data
> structures as with BTF, is inappropriate for unprivileged processes and
> probably not a good option for Landlock.
> 
> In conclusion, we feel that the design for a privileged LSM and
> unprivileged LSM are mutually exclusive and that one cannot be built
> "on-top-of" the other. Doing so would limit the capabilities of what can
> be done for an LSM that provides flexible audit and MAC capabilities or
> provide in-appropriate access to kernel internals to an unprivileged
> process.

I don't think that the design for a privileged LSM and an unprivileged 
LSM are necessarily mutually exclusive, however I do agree that the 
design of an *introspection* LSM like this version of KRSI, and an 
unprivileged LSM are mutually exclusive.

> 
> Furthermore, the Landlock design supports its historical use-case only
> when unprivileged eBPF is allowed. This is something that warrants
> discussion before an unprivileged LSM that uses eBPF is upstreamed.

Because of seccomp-bpf, on which the first version of Landlock was based 
on, I then used eBPF as a way to define a security policy which could be 
updated on the fly (thanks to eBPF maps) and evolves over time. The main 
goal of Landlock was and still is to bring sandboxing features to all 
users, which means to have an unprivileged access-control. However, I've 
reach a similar conclusion about eBPF for unprivileged access-control, 
but for slightly different reasons.

eBPF is very powerful and I proved with Landlock that it is possible to 
implement an access-control with it. However, a programmatic 
access-control does not fit well with unprivileged principles (i.e. 
innocuous composability). First, it can be used for side-channel attacks 
against (other) access-controls. Second, composability of eBPF programs 
imply to execute a stack of programs, which does not scale well. Third, 
as shown by multiple attacks, it is quite challenging to safely expose 
eBPF to malicious processes.

I'm working on a version of Landlock without eBPF, but still with the 
initial sought properties: safe unprivileged composability, modularity, 
and dynamic update. I'll send this version soon.

I hope that the work and experience from Landlock to bring eBPF to LSM 
will continue to be used through KRSI. Landlock will now focus on the 
unprivileged sandboxing part, without eBPF. Stay tuned!


> 
> # Why not tracepoints or kprobes?
> 
> In order to do MAC with tracepoints or kprobes, we would need to
> override the return value of the security hook. This is not possible
> with tracepoints or call-site kprobes.
> 
> Attaching to the return boundary (kretprobe) implies that BPF programs
> would always get called after all the other LSM hooks are called and
> clobber the pre-existing LSM semantics.
> 
> Enforcing MAC policy with an actual LSM helps leverage the verified
> semantics of the framework.
> 
> # 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 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 (13):
>    bpf: Refactor BPF_EVENT context macros to its own header.
>    bpf: lsm: Add a skeleton and config options
>    bpf: lsm: Introduce types for eBPF based LSM
>    bpf: lsm: Allow btf_id based attachment for LSM hooks
>    tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM
>    bpf: lsm: Init Hooks and create files in securityfs
>    bpf: lsm: Implement attach, detach and execution.
>    bpf: lsm: Show attached program names in hook read handler.
>    bpf: lsm: Add a helper function bpf_lsm_event_output
>    bpf: lsm: Handle attachment of the same program
>    tools/libbpf: Add bpf_program__attach_lsm
>    bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
>    bpf: lsm: Add Documentation
> 
>   Documentation/security/bpf.rst                |  164 +++
>   Documentation/security/index.rst              |    1 +
>   MAINTAINERS                                   |   11 +
>   include/linux/bpf_event.h                     |   78 ++
>   include/linux/bpf_lsm.h                       |   25 +
>   include/linux/bpf_types.h                     |    4 +
>   include/trace/bpf_probe.h                     |   30 +-
>   include/uapi/linux/bpf.h                      |   12 +-
>   kernel/bpf/syscall.c                          |   10 +
>   kernel/bpf/verifier.c                         |   84 +-
>   kernel/trace/bpf_trace.c                      |   24 +-
>   security/Kconfig                              |   11 +-
>   security/Makefile                             |    2 +
>   security/bpf/Kconfig                          |   25 +
>   security/bpf/Makefile                         |    7 +
>   security/bpf/include/bpf_lsm.h                |   63 +
>   security/bpf/include/fs.h                     |   23 +
>   security/bpf/include/hooks.h                  | 1015 +++++++++++++++++
>   security/bpf/lsm.c                            |  160 +++
>   security/bpf/lsm_fs.c                         |  176 +++
>   security/bpf/ops.c                            |  224 ++++
>   tools/include/uapi/linux/bpf.h                |   12 +-
>   tools/lib/bpf/bpf.c                           |    2 +-
>   tools/lib/bpf/bpf.h                           |    6 +
>   tools/lib/bpf/libbpf.c                        |  163 ++-
>   tools/lib/bpf/libbpf.h                        |    4 +
>   tools/lib/bpf/libbpf.map                      |    7 +
>   tools/lib/bpf/libbpf_probes.c                 |    1 +
>   .../bpf/prog_tests/lsm_mprotect_audit.c       |  129 +++
>   .../selftests/bpf/progs/lsm_mprotect_audit.c  |   58 +
>   30 files changed, 2451 insertions(+), 80 deletions(-)
>   create mode 100644 Documentation/security/bpf.rst
>   create mode 100644 include/linux/bpf_event.h
>   create mode 100644 include/linux/bpf_lsm.h
>   create mode 100644 security/bpf/Kconfig
>   create mode 100644 security/bpf/Makefile
>   create mode 100644 security/bpf/include/bpf_lsm.h
>   create mode 100644 security/bpf/include/fs.h
>   create mode 100644 security/bpf/include/hooks.h
>   create mode 100644 security/bpf/lsm.c
>   create mode 100644 security/bpf/lsm_fs.c
>   create mode 100644 security/bpf/ops.c
>   create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
>   create mode 100644 tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c
> 

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (14 preceding siblings ...)
  2019-12-20 22:46 ` Mickaël Salaün
@ 2019-12-22  1:27 ` Alexei Starovoitov
  2019-12-30 14:58   ` KP Singh
  2019-12-24  6:51 ` Andrii Nakryiko
  16 siblings, 1 reply; 74+ messages in thread
From: Alexei Starovoitov @ 2019-12-22  1:27 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 04:41:55PM +0100, KP Singh wrote:
> // Declare the eBPF program mprotect_audit which attaches to
> // to the file_mprotect LSM hook and accepts three arguments.
> BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
> 	    struct vm_area_struct *, vma,
> 	    unsigned long, reqprot, unsigned long, prot
> {
> 	unsigned long vm_start = _(vma->vm_start);
> 	return 0;
> }

I think the only sore point of the patchset is:
security/bpf/include/hooks.h   | 1015 ++++++++++++++++++++++++++++++++
With bpf trampoline this type of 'kernel types -> bpf types' converters
are no longer necessary. Please take a look at tcp-congestion-control patchset:
https://patchwork.ozlabs.org/cover/1214417/
Instead of doing similar thing (like your patch 1 plus patch 6) it's using
trampoline to provide bpf based congestion control callbacks into tcp stack.
The same trampoline-based mechanism can be reused by bpf_lsm.
Then all manual work of doing BPF_LSM_HOOK(...) for every hook won't be
necessary. It will also prove the point that attaching BPF to raw LSM hooks
doesn't freeze them into stable abi.
The programs can keep the same syntax as in your examples:
BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
libbpf will find file_mprotect's btf_id in kernel vmlinux and pass it to
the kernel for attaching. Just like fentry/fexit bpf progs are doing
and just like bpf-based cc is doing as well.

> In order to better illustrate the capabilities of the framework some
> more advanced prototype 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

Thank you for sharing these examples. That definitely helps to see more
complete picture. I noticed that the examples are using the pattern:
  u32 map_id = 0;
  env = bpf_map_lookup_elem(&env_map, &map_id);
Essentially they're global variables. libbpf already supports them.
bpf prog can use them as:
  struct env_value env;
  int bpf_prog(..)
  {
    env.name... env.value..
  }
That will make progs a bit easier to read and faster too.
Accesing global vars from user space is also trivial with skeleton work:
  lsm_audit_env_skel->bss->env.name... env.value.
Both bpf side and user side can access globals as normal C variables.

There is a small issue in the patches 8 and 10.
bpf program names are not unique and bpf-lsm should not require them to be different.
bpf_attr->prog_name is also short at 16 bytes. It's for introspection only.
Longer program names are supplied via btf's func_info.
It feels that:
cat /sys/kernel/security/bpf/process_execution
env_dumper__v2
is reinventing the wheel. bpftool is the main introspection tool.
It can print progs attached to perf, cgroup, networking. I think it's better to
stay consistent and do the same with bpf-lsm.

Another issue is in proposed attaching method:
hook_fd = open("/sys/kernel/security/bpf/process_execution");
sys_bpf(attach, prog_fd, hook_fd);
With bpf tracing we moved to FD-based attaching, because permanent attaching is
problematic in production. We're going to provide FD-based api to attach to
networking as well, because xdp/tc/cgroup prog attaching suffers from the same
production issues. Mainly with permanent attaching there is no ownership of
attachment. Everything is global and permanent. It's not clear what
process/script suppose to detach/cleanup. I suggest bpf-lsm use FD-based
attaching from the beginning. Take a look at raw_tp/tp_btf/fentry/fexit style
of attaching. All of them return FD which represents what libbpf calls
'bpf_link' concept. Once refcnt of that FD goes to zero that link (attachment)
is destroyed and program is detached _by the kernel_. To make such links
permanent the application can pin them in bpffs. The pinning patches haven't
landed yet, but the concept of the link is quite powerful and much more
production friendly than permanent attaching.
bpf-lsm will still be able to attach multiple progs to the same hook and
see what is attached via bpftool.

The rest looks good. Thank you for working on it.

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

* Re: [PATCH bpf-next v1 04/13] bpf: lsm: Allow btf_id based attachment for LSM hooks
  2019-12-20 15:41 ` [PATCH bpf-next v1 04/13] bpf: lsm: Allow btf_id based attachment for LSM hooks KP Singh
@ 2019-12-23 23:54   ` Andrii Nakryiko
  2019-12-30 19:22     ` KP Singh
  0 siblings, 1 reply; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-23 23:54 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 7:42 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> Refactor and re-use most of the logic for BPF_PROG_TYPE_TRACING with a few
> changes.
>
> - The LSM hook BTF types are prefixed with "lsm_btf_"

btf_trace_ and btf_struct_ops all have btf_ first, let's keep this consistent.

> - These types do not need the first (void *) pointer argument. The verifier
>   only looks for this argument if prod->aux->attach_btf_trace is set.
>
> Signed-off-by: KP Singh <kpsingh@google.com>
> ---
>  kernel/bpf/syscall.c  |  1 +
>  kernel/bpf/verifier.c | 83 ++++++++++++++++++++++++++++++++++++++++---
>  2 files changed, 80 insertions(+), 4 deletions(-)
>

[...]

> +
> +       t = btf_type_by_id(btf_vmlinux, btf_id);
> +       if (!t) {
> +               verbose(env, "attach_btf_id %u is invalid\n", btf_id);
> +               return -EINVAL;
> +       }
> +
> +       tname = btf_name_by_offset(btf_vmlinux, t->name_off);
> +       if (!tname) {

it can be empty, so better: !tname || !tname[0]

> +               verbose(env, "attach_btf_id %u doesn't have a name\n", btf_id);
> +               return -EINVAL;
> +       }
> +

[...]

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

* Re: [PATCH bpf-next v1 05/13] tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM
  2019-12-20 15:42 ` [PATCH bpf-next v1 05/13] tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM KP Singh
@ 2019-12-24  0:07   ` Andrii Nakryiko
  2019-12-24  0:09     ` Andrii Nakryiko
  2020-01-03 23:59     ` KP Singh
  0 siblings, 2 replies; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-24  0:07 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> Update the libbpf library with functionality to load and
> attach a program type BPF_PROG_TYPE_LSM, currently with
> only one expected attach type BPF_LSM_MAC.
>
> Signed-off-by: KP Singh <kpsingh@google.com>
> ---
>  tools/lib/bpf/bpf.c           |  2 +-
>  tools/lib/bpf/bpf.h           |  6 +++++
>  tools/lib/bpf/libbpf.c        | 44 +++++++++++++++++++++--------------
>  tools/lib/bpf/libbpf.h        |  2 ++
>  tools/lib/bpf/libbpf.map      |  6 +++++
>  tools/lib/bpf/libbpf_probes.c |  1 +
>  6 files changed, 43 insertions(+), 18 deletions(-)
>
> diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
> index 98596e15390f..9c6fb083f7de 100644
> --- a/tools/lib/bpf/bpf.c
> +++ b/tools/lib/bpf/bpf.c
> @@ -228,7 +228,7 @@ 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_TRACING) {
> +       if (needs_btf_attach(attr.prog_type)) {
>                 attr.attach_btf_id = load_attr->attach_btf_id;
>                 attr.attach_prog_fd = load_attr->attach_prog_fd;
>         } else {
> diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
> index 3c791fa8e68e..df2a00ff349f 100644
> --- a/tools/lib/bpf/bpf.h
> +++ b/tools/lib/bpf/bpf.h
> @@ -177,6 +177,12 @@ LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
>                                  __u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
>                                  __u64 *probe_offset, __u64 *probe_addr);
>
> +static inline bool needs_btf_attach(enum bpf_prog_type prog_type)
> +{
> +       return (prog_type == BPF_PROG_TYPE_TRACING ||
> +               prog_type == BPF_PROG_TYPE_LSM);
> +}
> +

This doesn't have to be a public API, right? It also doesn't follow
naming conventions of libbpf APIs. Let's just move it into
libbpf_internal.h, given it's used in few files.

Also, Martin's patches add STRUCT_OPS, which do need btf_attach, but
don't set attach_prog_fd. So maybe something like
libbpf_need_attach_prog_btf() for a name to be a bit more specific?


>  #ifdef __cplusplus
>  } /* extern "C" */
>  #endif
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index b20f82e58989..b0b27d8e5a37 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -3738,7 +3738,7 @@ 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_TRACING) {
> +       if (needs_btf_attach(prog->type)) {
>                 load_attr.attach_prog_fd = prog->attach_prog_fd;
>                 load_attr.attach_btf_id = prog->attach_btf_id;
>         } else {
> @@ -3983,7 +3983,7 @@ __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
>
>                 bpf_program__set_type(prog, prog_type);
>                 bpf_program__set_expected_attach_type(prog, attach_type);
> -               if (prog_type == BPF_PROG_TYPE_TRACING) {
> +               if (needs_btf_attach(prog_type)) {
>                         err = libbpf_find_attach_btf_id(prog->section_name,
>                                                         attach_type,
>                                                         attach_prog_fd);
> @@ -4933,6 +4933,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);
> @@ -5009,6 +5010,8 @@ static const struct {
>         BPF_PROG_SEC("lwt_out",                 BPF_PROG_TYPE_LWT_OUT),
>         BPF_PROG_SEC("lwt_xmit",                BPF_PROG_TYPE_LWT_XMIT),
>         BPF_PROG_SEC("lwt_seg6local",           BPF_PROG_TYPE_LWT_SEG6LOCAL),
> +       BPF_PROG_BTF("lsm/",                    BPF_PROG_TYPE_LSM,
> +                                               BPF_LSM_MAC),

Is is supposed to be attachable same as BPF_PROG_TYPE_TRACING
programs? If yes, please define auto-attaching function, similar to
SEC_DEF("raw_tp") few lines below this one.

>         BPF_APROG_SEC("cgroup_skb/ingress",     BPF_PROG_TYPE_CGROUP_SKB,
>                                                 BPF_CGROUP_INET_INGRESS),
>         BPF_APROG_SEC("cgroup_skb/egress",      BPF_PROG_TYPE_CGROUP_SKB,
> @@ -5119,32 +5122,39 @@ int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
>         return -ESRCH;
>  }
>
> -#define BTF_PREFIX "btf_trace_"
> +static inline int __btf__typdef_with_prefix(struct btf *btf, const char *name,

typo: typdef -> typedef

But actually let's generalize it to pass BTF_KIND as another param, I
think I have a need for this (we might want to do that for structs,
not just typedef->func_proto).
Following btf__find_by_name_kind() naming, it probably should be
called btf__find_by_prefix_kind()?

> +                                           const char *prefix)
> +{
> +
> +       size_t prefix_len = strlen(prefix);
> +       char btf_type_name[128];
> +
> +       strcpy(btf_type_name, prefix);
> +       strncat(btf_type_name, name, sizeof(btf_type_name) - (prefix_len + 1));

at this point snprintf(btf_type_name, "%s%.*%s", prefix,
sizeof(btf_type_name) - prefix_len - 1, name) looks like a better and
cleaner alternative.

> +       return btf__find_by_name_kind(btf, btf_type_name, BTF_KIND_TYPEDEF);
> +}
> +
> +#define BTF_TRACE_PREFIX "btf_trace_"
> +#define BTF_LSM_PREFIX "lsm_btf_"
> +

[...]

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

* Re: [PATCH bpf-next v1 05/13] tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM
  2019-12-24  0:07   ` Andrii Nakryiko
@ 2019-12-24  0:09     ` Andrii Nakryiko
  2020-01-03 23:59     ` KP Singh
  1 sibling, 0 replies; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-24  0:09 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Mon, Dec 23, 2019 at 4:07 PM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
> >
> > From: KP Singh <kpsingh@google.com>
> >
> > Update the libbpf library with functionality to load and
> > attach a program type BPF_PROG_TYPE_LSM, currently with
> > only one expected attach type BPF_LSM_MAC.
> >
> > Signed-off-by: KP Singh <kpsingh@google.com>
> > ---
> >  tools/lib/bpf/bpf.c           |  2 +-
> >  tools/lib/bpf/bpf.h           |  6 +++++
> >  tools/lib/bpf/libbpf.c        | 44 +++++++++++++++++++++--------------
> >  tools/lib/bpf/libbpf.h        |  2 ++
> >  tools/lib/bpf/libbpf.map      |  6 +++++
> >  tools/lib/bpf/libbpf_probes.c |  1 +
> >  6 files changed, 43 insertions(+), 18 deletions(-)
> >
> > diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
> > index 98596e15390f..9c6fb083f7de 100644
> > --- a/tools/lib/bpf/bpf.c
> > +++ b/tools/lib/bpf/bpf.c
> > @@ -228,7 +228,7 @@ 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_TRACING) {
> > +       if (needs_btf_attach(attr.prog_type)) {
> >                 attr.attach_btf_id = load_attr->attach_btf_id;
> >                 attr.attach_prog_fd = load_attr->attach_prog_fd;
> >         } else {
> > diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
> > index 3c791fa8e68e..df2a00ff349f 100644
> > --- a/tools/lib/bpf/bpf.h
> > +++ b/tools/lib/bpf/bpf.h
> > @@ -177,6 +177,12 @@ LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
> >                                  __u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
> >                                  __u64 *probe_offset, __u64 *probe_addr);
> >
> > +static inline bool needs_btf_attach(enum bpf_prog_type prog_type)
> > +{
> > +       return (prog_type == BPF_PROG_TYPE_TRACING ||
> > +               prog_type == BPF_PROG_TYPE_LSM);
> > +}
> > +
>
> This doesn't have to be a public API, right? It also doesn't follow
> naming conventions of libbpf APIs. Let's just move it into
> libbpf_internal.h, given it's used in few files.
>
> Also, Martin's patches add STRUCT_OPS, which do need btf_attach, but
> don't set attach_prog_fd. So maybe something like
> libbpf_need_attach_prog_btf() for a name to be a bit more specific?
>
>
> >  #ifdef __cplusplus
> >  } /* extern "C" */
> >  #endif
> > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > index b20f82e58989..b0b27d8e5a37 100644
> > --- a/tools/lib/bpf/libbpf.c
> > +++ b/tools/lib/bpf/libbpf.c
> > @@ -3738,7 +3738,7 @@ 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_TRACING) {
> > +       if (needs_btf_attach(prog->type)) {
> >                 load_attr.attach_prog_fd = prog->attach_prog_fd;
> >                 load_attr.attach_btf_id = prog->attach_btf_id;
> >         } else {
> > @@ -3983,7 +3983,7 @@ __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
> >
> >                 bpf_program__set_type(prog, prog_type);
> >                 bpf_program__set_expected_attach_type(prog, attach_type);
> > -               if (prog_type == BPF_PROG_TYPE_TRACING) {
> > +               if (needs_btf_attach(prog_type)) {
> >                         err = libbpf_find_attach_btf_id(prog->section_name,
> >                                                         attach_type,
> >                                                         attach_prog_fd);
> > @@ -4933,6 +4933,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);
> > @@ -5009,6 +5010,8 @@ static const struct {
> >         BPF_PROG_SEC("lwt_out",                 BPF_PROG_TYPE_LWT_OUT),
> >         BPF_PROG_SEC("lwt_xmit",                BPF_PROG_TYPE_LWT_XMIT),
> >         BPF_PROG_SEC("lwt_seg6local",           BPF_PROG_TYPE_LWT_SEG6LOCAL),
> > +       BPF_PROG_BTF("lsm/",                    BPF_PROG_TYPE_LSM,
> > +                                               BPF_LSM_MAC),
>
> Is is supposed to be attachable same as BPF_PROG_TYPE_TRACING
> programs? If yes, please define auto-attaching function, similar to
> SEC_DEF("raw_tp") few lines below this one.
>

ah, haven't gotten to patch 11 yet, disregard this.

> >         BPF_APROG_SEC("cgroup_skb/ingress",     BPF_PROG_TYPE_CGROUP_SKB,
> >                                                 BPF_CGROUP_INET_INGRESS),
> >         BPF_APROG_SEC("cgroup_skb/egress",      BPF_PROG_TYPE_CGROUP_SKB,
> > @@ -5119,32 +5122,39 @@ int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
> >         return -ESRCH;
> >  }
> >
> > -#define BTF_PREFIX "btf_trace_"
> > +static inline int __btf__typdef_with_prefix(struct btf *btf, const char *name,
>
> typo: typdef -> typedef
>
> But actually let's generalize it to pass BTF_KIND as another param, I
> think I have a need for this (we might want to do that for structs,
> not just typedef->func_proto).
> Following btf__find_by_name_kind() naming, it probably should be
> called btf__find_by_prefix_kind()?
>
> > +                                           const char *prefix)
> > +{
> > +
> > +       size_t prefix_len = strlen(prefix);
> > +       char btf_type_name[128];
> > +
> > +       strcpy(btf_type_name, prefix);
> > +       strncat(btf_type_name, name, sizeof(btf_type_name) - (prefix_len + 1));
>
> at this point snprintf(btf_type_name, "%s%.*%s", prefix,
> sizeof(btf_type_name) - prefix_len - 1, name) looks like a better and
> cleaner alternative.
>
> > +       return btf__find_by_name_kind(btf, btf_type_name, BTF_KIND_TYPEDEF);
> > +}
> > +
> > +#define BTF_TRACE_PREFIX "btf_trace_"
> > +#define BTF_LSM_PREFIX "lsm_btf_"
> > +
>
> [...]

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

* Re: [PATCH bpf-next v1 07/13] bpf: lsm: Implement attach, detach and execution.
  2019-12-20 15:42 ` [PATCH bpf-next v1 07/13] bpf: lsm: Implement attach, detach and execution KP Singh
@ 2019-12-24  5:48   ` Andrii Nakryiko
  2020-01-07 21:27   ` James Morris
  1 sibling, 0 replies; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-24  5:48 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> A user space program can attach an eBPF program by:
>
>   hook_fd = open("/sys/kernel/security/bpf/bprm_check_security",
>                  O_RDWR|O_CLOEXEC)
>   prog_fd = bpf(BPF_PROG_LOAD, ...)
>   bpf(BPF_PROG_ATTACH, hook_fd, prog_fd)
>
> The following permissions are required to attach a program to a hook:
>
> - CAP_SYS_ADMIN to load eBPF programs
> - CAP_MAC_ADMIN (to update the policy of an LSM)
> - The securityfs file being a valid hook and writable (O_RDWR)
>
> When such an attach call is received, the attachment logic looks up the
> dentry and appends the program to the bpf_prog_array.
>
> The BPF programs are stored in a bpf_prog_array and writes to the array
> are guarded by a mutex. The eBPF programs are executed as a part of the
> LSM hook they are attached to. If any of the eBPF programs return
> an error (-ENOPERM) the action represented by the hook is denied.
>
> Signed-off-by: KP Singh <kpsingh@google.com>
> ---

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

>  MAINTAINERS             |   1 +
>  include/linux/bpf_lsm.h |  13 ++++
>  kernel/bpf/syscall.c    |   5 +-
>  security/bpf/lsm_fs.c   |  19 +++++-
>  security/bpf/ops.c      | 134 ++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 169 insertions(+), 3 deletions(-)
>

[...]

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

* Re: [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs
  2019-12-20 15:42 ` [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs KP Singh
@ 2019-12-24  6:28   ` Andrii Nakryiko
  2019-12-30 15:37     ` KP Singh
  2020-01-07 21:22   ` James Morris
  1 sibling, 1 reply; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-24  6:28 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> The LSM creates files in securityfs for each hook registered with the
> LSM.
>
>     /sys/kernel/security/bpf/<h_name>
>
> The list of LSM hooks are maintained in an internal header "hooks.h"
> Eventually, this list should either be defined collectively in
> include/linux/lsm_hooks.h or auto-generated from it.
>
> * Creation of a file for the hook in the securityfs.
> * Allocation of a bpf_lsm_hook data structure which stores
>   a pointer to the dentry of the newly created file in securityfs.
> * Creation of a typedef for the hook so that BTF information
>   can be generated for the LSM hooks to:
>
>   - Make them "Compile Once, Run Everywhere".
>   - Pass the right arguments when the attached programs are run.
>   - Verify the accesses made by the program by using the BTF
>     information.
>
> Signed-off-by: KP Singh <kpsingh@google.com>
> ---
>  include/linux/bpf_lsm.h        |   12 +
>  security/bpf/Makefile          |    4 +-
>  security/bpf/include/bpf_lsm.h |   63 ++
>  security/bpf/include/fs.h      |   23 +
>  security/bpf/include/hooks.h   | 1015 ++++++++++++++++++++++++++++++++
>  security/bpf/lsm.c             |  138 ++++-
>  security/bpf/lsm_fs.c          |   82 +++
>  7 files changed, 1333 insertions(+), 4 deletions(-)
>  create mode 100644 include/linux/bpf_lsm.h
>  create mode 100644 security/bpf/include/bpf_lsm.h
>  create mode 100644 security/bpf/include/fs.h
>  create mode 100644 security/bpf/include/hooks.h
>  create mode 100644 security/bpf/lsm_fs.c
>

[...]

> +
> +/*
> + * The hooks can have an int or void return type, these macros allow having a
> + * single implementation of DEFINE_LSM_HOOK irrespective of the return type.
> + */
> +#define LSM_HOOK_RET(ret, x) LSM_HOOK_RET_##ret(x)
> +#define LSM_HOOK_RET_int(x) x
> +#define LSM_HOOK_RET_void(x)
> +
> +/*
> + * This macro defines the body of a LSM hook which runs the eBPF programs that
> + * are attached to the hook and returns the error code from the eBPF programs if
> + * the return type of the hook is int.
> + */
> +#define DEFINE_LSM_HOOK(hook, ret, proto, args)                                \
> +typedef ret (*lsm_btf_##hook)(proto);                                  \
> +static ret bpf_lsm_##hook(proto)                                       \
> +{                                                                      \
> +       return LSM_HOOK_RET(ret, LSM_RUN_PROGS(hook##_type, args));     \
>  }

I'm probably missing something, but according to LSM_HOOK_RET
definition for when ret==void, bpf_lsm_##hook will be a noop and won't
call any BPF program. Did I miss some additional macro magic?

>
> +/*
> + * Define the body of each of the LSM hooks defined in hooks.h.
> + */
> +#define BPF_LSM_HOOK(hook, ret, args, proto) \
> +       DEFINE_LSM_HOOK(hook, ret, BPF_LSM_ARGS(args), BPF_LSM_ARGS(proto))
> +#include "hooks.h"
> +#undef BPF_LSM_HOOK
> +#undef DEFINE_LSM_HOOK
> +
> +/*
> + * Initialize the bpf_lsm_hooks_list for each of the hooks defined in hooks.h.
> + * The list contains information for each of the hook and can be indexed by the
> + * its type to initialize security FS, attach, detach and execute eBPF programs
> + * for the hook.
> + */
> +struct bpf_lsm_hook bpf_lsm_hooks_list[] = {
> +       #define BPF_LSM_HOOK(h, ...)                                    \
> +               [h##_type] = {                                          \
> +                       .h_type = h##_type,                             \
> +                       .mutex = __MUTEX_INITIALIZER(                   \
> +                               bpf_lsm_hooks_list[h##_type].mutex),    \
> +                       .name = #h,                                     \
> +                       .btf_hook_func =                                \
> +                               (void *)(lsm_btf_##h)(bpf_lsm_##h),     \

this btf_hook_func, is it assigned just so that type information for
bpf_lsm_xxx typedefs are preserved, is that right? It doesn't seem to
be ever called or read. If I'm not missing anything, check out
Martin's latest STRUCT_OPS patch set. He defines EMIT_TYPE_INFO(type)
macro, which will ensure that BTF for specified type is emitted into
vmlinux BTF, without actually using any extra space, defining extra
fields or static variables, etc. I suggest using the same for the
cleanest result.

One more thing regarding lsm_bpf_ typedefs. Currently you are defining
them as a pointer to func_proto, matching LSM hook. There is an
alternative approach, which has few benefits over using func_proto. If
instead you define a struct, where each argument of func prototype is
represented as 8-byte aligned field, this will contain all the
necessary information for BPF verifier to do its job (just like
func_proto). But in addition to that, when vmlinux.h is generated, it
will contain a nice struct bpf_lsm_<hook_name> with correct structure
to be used **directly** in BPF program, as a single context argument.
So with vmlinux.h, users won't have to re-define all the argument
types and names in their BPF_TRACE_x definition. Let me provide
concrete example from your cover letter. This is what you provide as
an example:

BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
            struct vm_area_struct *, vma,
            unsigned long, reqprot, unsigned long, prot) {...}

on kernel side, you'll have:

typedef int (*bpf_lsm_file_mprotect)(struct vm_area_struct *vma,
                                     unsigned long reqprot,
                                     unsigned long prot);

So you can see that user has to go and copy/paste all the arguments
and their types and paste them in this verbose BPF_TRACE_3 macro to
define correct BPF program.

Now, imagine that instead of typedef above, we define equivalent struct:

struct bpf_lsm_file_mprotect {
    struct vm_area_struct *vma;
    unsigned long reqprot;
    unsigned long prot;
};

This type will get dumped into vmlinux.h, which can be used from BPF
user code as such:

SEC("lsm/file_mprotect")
int mprotect_audito(struct bpf_lsm_file_mprotect *ctx)
{
    ... here you can use ctx->vma, ctx->reqprot, ctx->prot ...
}


Meanwhile, there will be just minimal changes to BPF verifier to use
such struct instead of func_proto for verification of LSM programs.

We currently have similar issue with raw_tp programs and I've been
thinking about switching that to structs instead of func_proto, so we
might as well coordinate that and reuse the same logic in BPF
verifier.

Thoughts?



> +               },
> +       #include "hooks.h"
> +       #undef BPF_LSM_HOOK
> +};
> +

[...]

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

* Re: [PATCH bpf-next v1 09/13] bpf: lsm: Add a helper function bpf_lsm_event_output
  2019-12-20 15:42 ` [PATCH bpf-next v1 09/13] bpf: lsm: Add a helper function bpf_lsm_event_output KP Singh
@ 2019-12-24  6:36   ` Andrii Nakryiko
  2019-12-30 15:11     ` KP Singh
  0 siblings, 1 reply; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-24  6:36 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> This helper is similar to bpf_perf_event_output except that
> it does need a ctx argument which is more usable in the
> BTF based LSM programs where the context is converted to
> the signature of the attacthed BTF type.
>
> An example usage of this function would be:
>
> struct {
>          __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
>          __uint(key_size, sizeof(int));
>          __uint(value_size, sizeof(u32));
> } perf_map SEC(".maps");
>
> BPF_TRACE_1(bpf_prog1, "lsm/bprm_check_security,
>             struct linux_binprm *, bprm)
> {
>         char buf[BUF_SIZE];
>         int len;
>         u64 flags = BPF_F_CURRENT_CPU;
>
>         /* some logic that fills up buf with len data */
>         len = fill_up_buf(buf);
>         if (len < 0)
>                 return len;
>         if (len > BU)
>                 return 0;
>
>         bpf_lsm_event_output(&perf_map, flags, buf, len);

This seems to be generally useful and not LSM-specific, so maybe name
it more generically as bpf_event_output instead?

I'm also curious why we needed both bpf_perf_event_output and
bpf_perf_event_output_raw_tp, if it could be done as simply as you did
it here. What's different between those three and why your
bpf_lsm_event_output doesn't need pt_regs passed into them?

>         return 0;
> }
>
> Signed-off-by: KP Singh <kpsingh@google.com>
> ---
>  include/uapi/linux/bpf.h       | 10 +++++++++-
>  kernel/bpf/verifier.c          |  1 +
>  security/bpf/ops.c             | 21 +++++++++++++++++++++
>  tools/include/uapi/linux/bpf.h | 10 +++++++++-
>  4 files changed, 40 insertions(+), 2 deletions(-)
>

[...]

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

* Re: [PATCH bpf-next v1 10/13] bpf: lsm: Handle attachment of the same program
  2019-12-20 15:42 ` [PATCH bpf-next v1 10/13] bpf: lsm: Handle attachment of the same program KP Singh
@ 2019-12-24  6:38   ` Andrii Nakryiko
  2020-01-08 18:21   ` James Morris
  1 sibling, 0 replies; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-24  6:38 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 7:42 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> Allow userspace to attach a newer version of a program without having
> duplicates of the same program.
>
> If BPF_F_ALLOW_OVERRIDE is passed, the attachment logic compares the
> name of the new program to the names of existing attached programs. The
> names are only compared till a "__" (or '\0', if there is no "__"). If
> a successful match is found, the existing program is replaced with the
> newer attachment.
>
> ./loader Attaches "env_dumper__v1" followed by "env_dumper__v2"
> to the bprm_check_security hook..
>
> ./loader
> ./loader
>
> Before:
>
>   cat /sys/kernel/security/bpf/process_execution
>   env_dumper__v1
>   env_dumper__v2
>
> After:
>
>   cat /sys/kernel/security/bpf/process_execution
>   env_dumper__v2
>
> Signed-off-by: KP Singh <kpsingh@google.com>
> ---


Andrey Ignatov just posted patch set few days ago solving similar
problem for cgroup BPF programs. His approach was to actually also
specify FD of BPF program to be replaced. This seems like a more
reliable way than doing this based on name only. Please take a look at
that patch and see if same approach can work for your use case.

>  security/bpf/ops.c | 57 +++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 56 insertions(+), 1 deletion(-)
>

[...]

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

* Re: [PATCH bpf-next v1 11/13] tools/libbpf: Add bpf_program__attach_lsm
  2019-12-20 15:42 ` [PATCH bpf-next v1 11/13] tools/libbpf: Add bpf_program__attach_lsm KP Singh
@ 2019-12-24  6:44   ` Andrii Nakryiko
  2020-01-08 18:24   ` James Morris
  1 sibling, 0 replies; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-24  6:44 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 7:42 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> Add functionality in libbpf to attach eBPF program to LSM hooks.
>
> Signed-off-by: KP Singh <kpsingh@google.com>
> ---
>  tools/lib/bpf/libbpf.c   | 127 +++++++++++++++++++++++++++++++++++++--
>  tools/lib/bpf/libbpf.h   |   2 +
>  tools/lib/bpf/libbpf.map |   1 +
>  3 files changed, 126 insertions(+), 4 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index b0b27d8e5a37..ab2b23b4f21f 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -5122,8 +5122,8 @@ int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
>         return -ESRCH;
>  }
>
> -static inline int __btf__typdef_with_prefix(struct btf *btf, const char *name,
> -                                           const char *prefix)
> +static inline int __btf__type_with_prefix(struct btf *btf, const char *name,
> +                                         const char *prefix)

Please do this rename in a patch that introduced this function, there
is no need to split such changes between two patches. See also my
request to rename and generalize it a bit.

>  {
>
>         size_t prefix_len = strlen(prefix);
> @@ -5149,9 +5149,9 @@ int libbpf_find_vmlinux_btf_id(const char *name,
>         }
>

[...]

>
> +
> +static int bpf_link__destroy_lsm(struct bpf_link *link)
> +{
> +       struct bpf_link_lsm *ll = container_of(link, struct bpf_link_lsm, link);

struct bpf_link link being a first field is a requirement for
bpf_link, so you don't need container_of, just cast link to your type.

> +       char errmsg[STRERR_BUFSIZE];
> +       int ret;
> +
> +       ret = bpf_prog_detach2(ll->prog_fd, ll->hook_fd, BPF_LSM_MAC);
> +       if (ret < 0) {
> +               ret = -errno;
> +               pr_warn("failed to detach from hook: %s\n",
> +                       libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
> +               return ret;
> +       }
> +       close(ll->hook_fd);
> +       return 0;
> +}
> +
> +static const char *__lsm_hook_name(const char *title)
> +{
> +
> +       int i;
> +
> +       if (!title)
> +               return ERR_PTR(-EINVAL);
> +
> +       for (i = 0; i < ARRAY_SIZE(section_names); i++) {

section_names have been renamed to section_defs a while ago, please rebase

> +               if (section_names[i].prog_type != BPF_PROG_TYPE_LSM)
> +                       continue;
> +

[...]

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

* Re: [PATCH bpf-next v1 12/13] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
  2019-12-20 15:42 ` [PATCH bpf-next v1 12/13] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM KP Singh
@ 2019-12-24  6:49   ` Andrii Nakryiko
  2020-01-04  0:09     ` KP Singh
  2020-01-08 18:25   ` James Morris
  1 sibling, 1 reply; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-24  6:49 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 7:42 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> * Load a BPF program that audits mprotect calls
> * Attach the program to the "file_mprotect" LSM hook
> * Verify if the program is actually loading by reading
>   securityfs
> * Initialize the perf events buffer and poll for audit events
> * Do an mprotect on some memory allocated on the heap
> * Verify if the audit event was received
>
> Signed-off-by: KP Singh <kpsingh@google.com>
> ---
>  MAINTAINERS                                   |   2 +
>  .../bpf/prog_tests/lsm_mprotect_audit.c       | 129 ++++++++++++++++++
>  .../selftests/bpf/progs/lsm_mprotect_audit.c  |  58 ++++++++
>  3 files changed, 189 insertions(+)
>  create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
>  create mode 100644 tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c
>

[...]

> +/*
> + * Define some of the structs used in the BPF program.
> + * Only the field names and their sizes need to be the
> + * same as the kernel type, the order is irrelevant.
> + */
> +struct mm_struct {
> +       unsigned long start_brk, brk, start_stack;
> +};
> +
> +struct vm_area_struct {
> +       unsigned long start_brk, brk, start_stack;
> +       unsigned long vm_start, vm_end;
> +       struct mm_struct *vm_mm;
> +       unsigned long vm_flags;
> +};
> +
> +BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
> +           struct vm_area_struct *, vma,
> +           unsigned long, reqprot, unsigned long, prot)
> +{
> +       struct mprotect_audit_log audit_log = {};
> +       int is_heap = 0;
> +
> +       __builtin_preserve_access_index(({

you don't need __builtin_preserve_access_index, if you mark
vm_area_struct and mm_struct with
__attribute__((preserve_access_index)

> +               is_heap = (vma->vm_start >= vma->vm_mm->start_brk &&
> +                                    vma->vm_end <= vma->vm_mm->brk);
> +       }));
> +
> +       audit_log.magic = MPROTECT_AUDIT_MAGIC;
> +       audit_log.is_heap = is_heap;
> +       bpf_lsm_event_output(&perf_buf_map, BPF_F_CURRENT_CPU, &audit_log,
> +                            sizeof(audit_log));

You test would be much simpler if you use global variables to pass
data back to userspace, instead of using perf buffer.

Also please see fentry_fexit.c test for example of using BPF skeleton
to shorten and simpify userspace part of test.

> +       return 0;
> +}
> --
> 2.20.1
>

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
                   ` (15 preceding siblings ...)
  2019-12-22  1:27 ` Alexei Starovoitov
@ 2019-12-24  6:51 ` Andrii Nakryiko
  2019-12-30 15:04   ` KP Singh
  16 siblings, 1 reply; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-24  6:51 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 7:42 AM KP Singh <kpsingh@chromium.org> wrote:
>
> From: KP Singh <kpsingh@google.com>
>
> This patch series is a continuation of the KRSI 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 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

Are you planning on submitting these examples for inclusion into
samples/bpf or selftests/bpf? It would be great to have more examples
and we can review and suggest nicer ways to go about writing them
(e.g., BPF skeleton and global data Alexei mentioned earlier).

>
> 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 (13):
>   bpf: Refactor BPF_EVENT context macros to its own header.
>   bpf: lsm: Add a skeleton and config options
>   bpf: lsm: Introduce types for eBPF based LSM
>   bpf: lsm: Allow btf_id based attachment for LSM hooks
>   tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM
>   bpf: lsm: Init Hooks and create files in securityfs
>   bpf: lsm: Implement attach, detach and execution.
>   bpf: lsm: Show attached program names in hook read handler.
>   bpf: lsm: Add a helper function bpf_lsm_event_output
>   bpf: lsm: Handle attachment of the same program
>   tools/libbpf: Add bpf_program__attach_lsm
>   bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
>   bpf: lsm: Add Documentation
>

[...]

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-22  1:27 ` Alexei Starovoitov
@ 2019-12-30 14:58   ` KP Singh
  2019-12-30 19:14     ` Andrii Nakryiko
  0 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2019-12-30 14:58 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: linux-kernel, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On 21-Dez 17:27, Alexei Starovoitov wrote:
> On Fri, Dec 20, 2019 at 04:41:55PM +0100, KP Singh wrote:
> > // Declare the eBPF program mprotect_audit which attaches to
> > // to the file_mprotect LSM hook and accepts three arguments.
> > BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
> > 	    struct vm_area_struct *, vma,
> > 	    unsigned long, reqprot, unsigned long, prot
> > {
> > 	unsigned long vm_start = _(vma->vm_start);
> > 	return 0;
> > }
> 

Hi Alexei,

Thanks for the feedback. This is really helpful!

> I think the only sore point of the patchset is:
> security/bpf/include/hooks.h   | 1015 ++++++++++++++++++++++++++++++++
> With bpf trampoline this type of 'kernel types -> bpf types' converters
> are no longer necessary. Please take a look at tcp-congestion-control patchset:
> https://patchwork.ozlabs.org/cover/1214417/
> Instead of doing similar thing (like your patch 1 plus patch 6) it's using
> trampoline to provide bpf based congestion control callbacks into tcp stack.
> The same trampoline-based mechanism can be reused by bpf_lsm.
> Then all manual work of doing BPF_LSM_HOOK(...) for every hook won't be
> necessary. It will also prove the point that attaching BPF to raw LSM hooks
> doesn't freeze them into stable abi.

Really cool!

I looked into how BPF trampolines are being used in tracing and the
new STRUCT_OPS patchset and was able protoype
(https://github.com/sinkap/linux-krsi/tree/patch/v1/trampoline_prototype,
not ready for review yet) which:

* Gets rid of security/bpf/include/hooks.h and all of the static
  macro magic essentially making the LSM ~truly instrumentable~ at
  runtime.
* Gets rid of the generation of any new types as we already have
  all the BTF information in the kernel in the following two types:

struct security_hook_heads {
        .
        .
        struct hlist_head file_mprotect;   <- Append the callback at this offset
        .
        .
};

and

union security_list_options {
	int (*file_mprotect)(struct vm_area_struct *vma, unsigned long reqprot,
				unsigned long prot);
};

Which is the same type as the typedef that's currently being generated
, i.e. lsm_btf_file_mprotect

In the current prototype, libbpf converts the name of the hook into an
offset into the security_hook_heads and the verifier does the
following when a program is loaded:

* Verifies the offset and the type at the offset (struct hlist_head).
* Resolves the func_proto (by looking up the type in
  security_list_options) and updates prog->aux with the name and
  func_proto which are then verified similar to raw_tp programs with
  btf_ctx_access.

On attachment:

* A trampoline is created and appended to the security_hook_heads
  for the BPF LSM.
* An anonymous FD is returned and the attachment is conditional on the
  references to FD (as suggested and similar to fentry/fexit tracing
  programs).

This implies that the BPF programs are "the LSM hook" as opposed to
being executed inside a statically defined hook body which requires
mutable LSM hooks for which I was able to re-use some of ideas in
Sargun's patch:

https://lore.kernel.org/lkml/20180408065916.GA2832@ircssh-2.c.rugged-nimbus-611.internal/

to maintain a separate security_hook_heads struct for dynamically
added LSM hooks by the BPF LSM which are executed after all the
statically defined hooks.

> Longer program names are supplied via btf's func_info.
> It feels that:
> cat /sys/kernel/security/bpf/process_execution
> env_dumper__v2
> is reinventing the wheel. bpftool is the main introspection tool.
> It can print progs attached to perf, cgroup, networking. I think it's better to
> stay consistent and do the same with bpf-lsm.

I agree, based on the new feedback, I don't think we need securityFS
attachment points anymore. I was able to get rid of it completely.

> 
> Another issue is in proposed attaching method:
> hook_fd = open("/sys/kernel/security/bpf/process_execution");
> sys_bpf(attach, prog_fd, hook_fd);
> With bpf tracing we moved to FD-based attaching, because permanent attaching is
> problematic in production. We're going to provide FD-based api to attach to
> networking as well, because xdp/tc/cgroup prog attaching suffers from the same
> production issues. Mainly with permanent attaching there is no ownership of
> attachment. Everything is global and permanent. It's not clear what
> process/script suppose to detach/cleanup. I suggest bpf-lsm use FD-based
> attaching from the beginning. Take a look at raw_tp/tp_btf/fentry/fexit style
> of attaching. All of them return FD which represents what libbpf calls
> 'bpf_link' concept. Once refcnt of that FD goes to zero that link (attachment)
> is destroyed and program is detached _by the kernel_. To make such links
> permanent the application can pin them in bpffs. The pinning patches haven't
> landed yet, but the concept of the link is quite powerful and much more
> production friendly than permanent attaching.

I like this. This also means we don't immediately need the handling of
duplicate names so I dropped that bit of the patch as well and updated
the attachment to use this mechanism.

> bpf-lsm will still be able to attach multiple progs to the same hook and
> see what is attached via bpftool.
> 
> The rest looks good. Thank you for working on it.

There are some choices we need to make here from an API perspective:

* Should we "repurpose" attr->attach_btf_id and use it as an offset
  into security_hook_heads or add a new attribute
  (e.g lsm_hook_offset) for the offset or use name of the LSM hook
  (e.g. lsm_hook_name).
* Since we don't have the files in securityFS, the attachment does not
  have a target_fd. Should we add a new type of BPF command?
  e.g. LSM_HOOK_OPEN?

I will clean up the prototype, incorporate some of the other feedback
received, and send a v2.

Wishing everyone a very Happy New Year!

- KP


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-24  6:51 ` Andrii Nakryiko
@ 2019-12-30 15:04   ` KP Singh
  2019-12-30 18:58     ` Andrii Nakryiko
  0 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2019-12-30 15:04 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: KP Singh, open list, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

On 23-Dec 22:51, Andrii Nakryiko wrote:
> On Fri, Dec 20, 2019 at 7:42 AM KP Singh <kpsingh@chromium.org> wrote:
> >
> > From: KP Singh <kpsingh@google.com>
> >
> > This patch series is a continuation of the KRSI 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 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
> 
> Are you planning on submitting these examples for inclusion into
> samples/bpf or selftests/bpf? It would be great to have more examples
> and we can review and suggest nicer ways to go about writing them
> (e.g., BPF skeleton and global data Alexei mentioned earlier).

Eventually, yes and in selftest/bpf.

But these examples depend on using security blobs and some non-atomic
calls in the BPF helpers which are not handled as a part of the
initial patch-set.

Once we have the initial framework finalized, I will update the
examples and the helpers they are based on and send these separate
patch-sets on the list for review.

- KP

> 
> >
> > 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 (13):
> >   bpf: Refactor BPF_EVENT context macros to its own header.
> >   bpf: lsm: Add a skeleton and config options
> >   bpf: lsm: Introduce types for eBPF based LSM
> >   bpf: lsm: Allow btf_id based attachment for LSM hooks
> >   tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM
> >   bpf: lsm: Init Hooks and create files in securityfs
> >   bpf: lsm: Implement attach, detach and execution.
> >   bpf: lsm: Show attached program names in hook read handler.
> >   bpf: lsm: Add a helper function bpf_lsm_event_output
> >   bpf: lsm: Handle attachment of the same program
> >   tools/libbpf: Add bpf_program__attach_lsm
> >   bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
> >   bpf: lsm: Add Documentation
> >
> 
> [...]

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

* Re: [PATCH bpf-next v1 09/13] bpf: lsm: Add a helper function bpf_lsm_event_output
  2019-12-24  6:36   ` Andrii Nakryiko
@ 2019-12-30 15:11     ` KP Singh
  2019-12-30 18:56       ` Andrii Nakryiko
  0 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2019-12-30 15:11 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: KP Singh, open list, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

On 23-Dec 22:36, Andrii Nakryiko wrote:
> On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
> >
> > From: KP Singh <kpsingh@google.com>
> >
> > This helper is similar to bpf_perf_event_output except that
> > it does need a ctx argument which is more usable in the
> > BTF based LSM programs where the context is converted to
> > the signature of the attacthed BTF type.
> >
> > An example usage of this function would be:
> >
> > struct {
> >          __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
> >          __uint(key_size, sizeof(int));
> >          __uint(value_size, sizeof(u32));
> > } perf_map SEC(".maps");
> >
> > BPF_TRACE_1(bpf_prog1, "lsm/bprm_check_security,
> >             struct linux_binprm *, bprm)
> > {
> >         char buf[BUF_SIZE];
> >         int len;
> >         u64 flags = BPF_F_CURRENT_CPU;
> >
> >         /* some logic that fills up buf with len data */
> >         len = fill_up_buf(buf);
> >         if (len < 0)
> >                 return len;
> >         if (len > BU)
> >                 return 0;
> >
> >         bpf_lsm_event_output(&perf_map, flags, buf, len);
> 
> This seems to be generally useful and not LSM-specific, so maybe name
> it more generically as bpf_event_output instead?

Agreed, I am happy to rename this.

> 
> I'm also curious why we needed both bpf_perf_event_output and
> bpf_perf_event_output_raw_tp, if it could be done as simply as you did
> it here. What's different between those three and why your
> bpf_lsm_event_output doesn't need pt_regs passed into them?

That's because my implementation uses the following function from
bpf_trace.c:

u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
		     void *ctx, u64 ctx_size, bpf_ctx_copy_t ctx_copy)

This does not require a pt_regs argument and handles fetching them
internally:

	regs = this_cpu_ptr(&bpf_pt_regs.regs[nest_level - 1]);

	perf_fetch_caller_regs(regs);
	perf_sample_data_init(sd, 0, 0);
	sd->raw = &raw;

	ret = __bpf_perf_event_output(regs, map, flags, sd);

- KP

> 
> >         return 0;
> > }
> >
> > Signed-off-by: KP Singh <kpsingh@google.com>
> > ---
> >  include/uapi/linux/bpf.h       | 10 +++++++++-
> >  kernel/bpf/verifier.c          |  1 +
> >  security/bpf/ops.c             | 21 +++++++++++++++++++++
> >  tools/include/uapi/linux/bpf.h | 10 +++++++++-
> >  4 files changed, 40 insertions(+), 2 deletions(-)
> >
> 
> [...]

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

* Re: [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs
  2019-12-24  6:28   ` Andrii Nakryiko
@ 2019-12-30 15:37     ` KP Singh
  2019-12-30 18:52       ` Andrii Nakryiko
  2019-12-30 19:20       ` Kees Cook
  0 siblings, 2 replies; 74+ messages in thread
From: KP Singh @ 2019-12-30 15:37 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: KP Singh, open list, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

On 23-Dec 22:28, Andrii Nakryiko wrote:
> On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
> >
> > From: KP Singh <kpsingh@google.com>
> >
> > The LSM creates files in securityfs for each hook registered with the
> > LSM.
> >
> >     /sys/kernel/security/bpf/<h_name>
> >
> > The list of LSM hooks are maintained in an internal header "hooks.h"
> > Eventually, this list should either be defined collectively in
> > include/linux/lsm_hooks.h or auto-generated from it.
> >
> > * Creation of a file for the hook in the securityfs.
> > * Allocation of a bpf_lsm_hook data structure which stores
> >   a pointer to the dentry of the newly created file in securityfs.
> > * Creation of a typedef for the hook so that BTF information
> >   can be generated for the LSM hooks to:
> >
> >   - Make them "Compile Once, Run Everywhere".
> >   - Pass the right arguments when the attached programs are run.
> >   - Verify the accesses made by the program by using the BTF
> >     information.
> >
> > Signed-off-by: KP Singh <kpsingh@google.com>
> > ---
> >  include/linux/bpf_lsm.h        |   12 +
> >  security/bpf/Makefile          |    4 +-
> >  security/bpf/include/bpf_lsm.h |   63 ++
> >  security/bpf/include/fs.h      |   23 +
> >  security/bpf/include/hooks.h   | 1015 ++++++++++++++++++++++++++++++++
> >  security/bpf/lsm.c             |  138 ++++-
> >  security/bpf/lsm_fs.c          |   82 +++
> >  7 files changed, 1333 insertions(+), 4 deletions(-)
> >  create mode 100644 include/linux/bpf_lsm.h
> >  create mode 100644 security/bpf/include/bpf_lsm.h
> >  create mode 100644 security/bpf/include/fs.h
> >  create mode 100644 security/bpf/include/hooks.h
> >  create mode 100644 security/bpf/lsm_fs.c
> >
> 
> [...]
> 
> > +
> > +/*
> > + * The hooks can have an int or void return type, these macros allow having a
> > + * single implementation of DEFINE_LSM_HOOK irrespective of the return type.
> > + */
> > +#define LSM_HOOK_RET(ret, x) LSM_HOOK_RET_##ret(x)
> > +#define LSM_HOOK_RET_int(x) x
> > +#define LSM_HOOK_RET_void(x)
> > +
> > +/*
> > + * This macro defines the body of a LSM hook which runs the eBPF programs that
> > + * are attached to the hook and returns the error code from the eBPF programs if
> > + * the return type of the hook is int.
> > + */
> > +#define DEFINE_LSM_HOOK(hook, ret, proto, args)                                \
> > +typedef ret (*lsm_btf_##hook)(proto);                                  \
> > +static ret bpf_lsm_##hook(proto)                                       \
> > +{                                                                      \
> > +       return LSM_HOOK_RET(ret, LSM_RUN_PROGS(hook##_type, args));     \
> >  }
> 
> I'm probably missing something, but according to LSM_HOOK_RET
> definition for when ret==void, bpf_lsm_##hook will be a noop and won't
> call any BPF program. Did I miss some additional macro magic?
> 

Good catch! You're right. These macros will not be there in v2 as
we move to using trampolines based callbacks.

> >
> > +/*
> > + * Define the body of each of the LSM hooks defined in hooks.h.
> > + */
> > +#define BPF_LSM_HOOK(hook, ret, args, proto) \
> > +       DEFINE_LSM_HOOK(hook, ret, BPF_LSM_ARGS(args), BPF_LSM_ARGS(proto))
> > +#include "hooks.h"
> > +#undef BPF_LSM_HOOK
> > +#undef DEFINE_LSM_HOOK
> > +
> > +/*
> > + * Initialize the bpf_lsm_hooks_list for each of the hooks defined in hooks.h.
> > + * The list contains information for each of the hook and can be indexed by the
> > + * its type to initialize security FS, attach, detach and execute eBPF programs
> > + * for the hook.
> > + */
> > +struct bpf_lsm_hook bpf_lsm_hooks_list[] = {
> > +       #define BPF_LSM_HOOK(h, ...)                                    \
> > +               [h##_type] = {                                          \
> > +                       .h_type = h##_type,                             \
> > +                       .mutex = __MUTEX_INITIALIZER(                   \
> > +                               bpf_lsm_hooks_list[h##_type].mutex),    \
> > +                       .name = #h,                                     \
> > +                       .btf_hook_func =                                \
> > +                               (void *)(lsm_btf_##h)(bpf_lsm_##h),     \
> 
> this btf_hook_func, is it assigned just so that type information for
> bpf_lsm_xxx typedefs are preserved, is that right? It doesn't seem to
> be ever called or read. If I'm not missing anything, check out
> Martin's latest STRUCT_OPS patch set. He defines EMIT_TYPE_INFO(type)
> macro, which will ensure that BTF for specified type is emitted into
> vmlinux BTF, without actually using any extra space, defining extra
> fields or static variables, etc. I suggest using the same for the
> cleanest result.
> 
> One more thing regarding lsm_bpf_ typedefs. Currently you are defining
> them as a pointer to func_proto, matching LSM hook. There is an
> alternative approach, which has few benefits over using func_proto. If
> instead you define a struct, where each argument of func prototype is
> represented as 8-byte aligned field, this will contain all the
> necessary information for BPF verifier to do its job (just like
> func_proto). But in addition to that, when vmlinux.h is generated, it
> will contain a nice struct bpf_lsm_<hook_name> with correct structure
> to be used **directly** in BPF program, as a single context argument.
> So with vmlinux.h, users won't have to re-define all the argument
> types and names in their BPF_TRACE_x definition. Let me provide
> concrete example from your cover letter. This is what you provide as
> an example:

Is this also doable for the new approach suggsted by Alexei
and prototyped in?

https://lore.kernel.org/bpf/CAEf4BzYiUZtSJKh-UBL0jwyo6d=Cne2YtEyGU8ONykmSUSsuNA@mail.gmail.com/T/#m7c7ec0e7d8e803c6c357495d9eea59028a67cac6

which uses trampolines. The new approach gets rid of any type
generation and macros in security/bpf/lsm_hooks.h. Maybe the
btf_vmlinux can be augmented at runtime to generate context struct
upon attachment?

> 
> BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
>             struct vm_area_struct *, vma,
>             unsigned long, reqprot, unsigned long, prot) {...}
> 
> on kernel side, you'll have:
> 
> typedef int (*bpf_lsm_file_mprotect)(struct vm_area_struct *vma,
>                                      unsigned long reqprot,
>                                      unsigned long prot);
> 
> So you can see that user has to go and copy/paste all the arguments
> and their types and paste them in this verbose BPF_TRACE_3 macro to
> define correct BPF program.
> 
> Now, imagine that instead of typedef above, we define equivalent struct:
> 
> struct bpf_lsm_file_mprotect {
>     struct vm_area_struct *vma;
>     unsigned long reqprot;
>     unsigned long prot;
> };
> 
> This type will get dumped into vmlinux.h, which can be used from BPF
> user code as such:
> 
> SEC("lsm/file_mprotect")
> int mprotect_audito(struct bpf_lsm_file_mprotect *ctx)
> {
>     ... here you can use ctx->vma, ctx->reqprot, ctx->prot ...
> }
> 
> 
> Meanwhile, there will be just minimal changes to BPF verifier to use
> such struct instead of func_proto for verification of LSM programs.
> 
> We currently have similar issue with raw_tp programs and I've been
> thinking about switching that to structs instead of func_proto, so we
> might as well coordinate that and reuse the same logic in BPF
> verifier.
> 
> Thoughts?

Thanks for the explanation!

Using structs is definitely better if we chose to go with static type
generation.

- KP

> 
> 
> 
> > +               },
> > +       #include "hooks.h"
> > +       #undef BPF_LSM_HOOK
> > +};
> > +
> 
> [...]

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

* Re: [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs
  2019-12-30 15:37     ` KP Singh
@ 2019-12-30 18:52       ` Andrii Nakryiko
  2019-12-30 19:20       ` Kees Cook
  1 sibling, 0 replies; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-30 18:52 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Mon, Dec 30, 2019 at 7:37 AM KP Singh <kpsingh@chromium.org> wrote:
>
> On 23-Dec 22:28, Andrii Nakryiko wrote:
> > On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
> > >
> > > From: KP Singh <kpsingh@google.com>
> > >
> > > The LSM creates files in securityfs for each hook registered with the
> > > LSM.
> > >
> > >     /sys/kernel/security/bpf/<h_name>
> > >
> > > The list of LSM hooks are maintained in an internal header "hooks.h"
> > > Eventually, this list should either be defined collectively in
> > > include/linux/lsm_hooks.h or auto-generated from it.
> > >
> > > * Creation of a file for the hook in the securityfs.
> > > * Allocation of a bpf_lsm_hook data structure which stores
> > >   a pointer to the dentry of the newly created file in securityfs.
> > > * Creation of a typedef for the hook so that BTF information
> > >   can be generated for the LSM hooks to:
> > >
> > >   - Make them "Compile Once, Run Everywhere".
> > >   - Pass the right arguments when the attached programs are run.
> > >   - Verify the accesses made by the program by using the BTF
> > >     information.
> > >
> > > Signed-off-by: KP Singh <kpsingh@google.com>
> > > ---
> > >  include/linux/bpf_lsm.h        |   12 +
> > >  security/bpf/Makefile          |    4 +-
> > >  security/bpf/include/bpf_lsm.h |   63 ++
> > >  security/bpf/include/fs.h      |   23 +
> > >  security/bpf/include/hooks.h   | 1015 ++++++++++++++++++++++++++++++++
> > >  security/bpf/lsm.c             |  138 ++++-
> > >  security/bpf/lsm_fs.c          |   82 +++
> > >  7 files changed, 1333 insertions(+), 4 deletions(-)
> > >  create mode 100644 include/linux/bpf_lsm.h
> > >  create mode 100644 security/bpf/include/bpf_lsm.h
> > >  create mode 100644 security/bpf/include/fs.h
> > >  create mode 100644 security/bpf/include/hooks.h
> > >  create mode 100644 security/bpf/lsm_fs.c
> > >
> >
> > [...]
> >
> > > +
> > > +/*
> > > + * The hooks can have an int or void return type, these macros allow having a
> > > + * single implementation of DEFINE_LSM_HOOK irrespective of the return type.
> > > + */
> > > +#define LSM_HOOK_RET(ret, x) LSM_HOOK_RET_##ret(x)
> > > +#define LSM_HOOK_RET_int(x) x
> > > +#define LSM_HOOK_RET_void(x)
> > > +
> > > +/*
> > > + * This macro defines the body of a LSM hook which runs the eBPF programs that
> > > + * are attached to the hook and returns the error code from the eBPF programs if
> > > + * the return type of the hook is int.
> > > + */
> > > +#define DEFINE_LSM_HOOK(hook, ret, proto, args)                                \
> > > +typedef ret (*lsm_btf_##hook)(proto);                                  \
> > > +static ret bpf_lsm_##hook(proto)                                       \
> > > +{                                                                      \
> > > +       return LSM_HOOK_RET(ret, LSM_RUN_PROGS(hook##_type, args));     \
> > >  }
> >
> > I'm probably missing something, but according to LSM_HOOK_RET
> > definition for when ret==void, bpf_lsm_##hook will be a noop and won't
> > call any BPF program. Did I miss some additional macro magic?
> >
>
> Good catch! You're right. These macros will not be there in v2 as
> we move to using trampolines based callbacks.

Cool, no worries.

>
> > >
> > > +/*
> > > + * Define the body of each of the LSM hooks defined in hooks.h.
> > > + */
> > > +#define BPF_LSM_HOOK(hook, ret, args, proto) \
> > > +       DEFINE_LSM_HOOK(hook, ret, BPF_LSM_ARGS(args), BPF_LSM_ARGS(proto))
> > > +#include "hooks.h"
> > > +#undef BPF_LSM_HOOK
> > > +#undef DEFINE_LSM_HOOK
> > > +
> > > +/*
> > > + * Initialize the bpf_lsm_hooks_list for each of the hooks defined in hooks.h.
> > > + * The list contains information for each of the hook and can be indexed by the
> > > + * its type to initialize security FS, attach, detach and execute eBPF programs
> > > + * for the hook.
> > > + */
> > > +struct bpf_lsm_hook bpf_lsm_hooks_list[] = {
> > > +       #define BPF_LSM_HOOK(h, ...)                                    \
> > > +               [h##_type] = {                                          \
> > > +                       .h_type = h##_type,                             \
> > > +                       .mutex = __MUTEX_INITIALIZER(                   \
> > > +                               bpf_lsm_hooks_list[h##_type].mutex),    \
> > > +                       .name = #h,                                     \
> > > +                       .btf_hook_func =                                \
> > > +                               (void *)(lsm_btf_##h)(bpf_lsm_##h),     \
> >
> > this btf_hook_func, is it assigned just so that type information for
> > bpf_lsm_xxx typedefs are preserved, is that right? It doesn't seem to
> > be ever called or read. If I'm not missing anything, check out
> > Martin's latest STRUCT_OPS patch set. He defines EMIT_TYPE_INFO(type)
> > macro, which will ensure that BTF for specified type is emitted into
> > vmlinux BTF, without actually using any extra space, defining extra
> > fields or static variables, etc. I suggest using the same for the
> > cleanest result.
> >
> > One more thing regarding lsm_bpf_ typedefs. Currently you are defining
> > them as a pointer to func_proto, matching LSM hook. There is an
> > alternative approach, which has few benefits over using func_proto. If
> > instead you define a struct, where each argument of func prototype is
> > represented as 8-byte aligned field, this will contain all the
> > necessary information for BPF verifier to do its job (just like
> > func_proto). But in addition to that, when vmlinux.h is generated, it
> > will contain a nice struct bpf_lsm_<hook_name> with correct structure
> > to be used **directly** in BPF program, as a single context argument.
> > So with vmlinux.h, users won't have to re-define all the argument
> > types and names in their BPF_TRACE_x definition. Let me provide
> > concrete example from your cover letter. This is what you provide as
> > an example:
>
> Is this also doable for the new approach suggsted by Alexei
> and prototyped in?
>
> https://lore.kernel.org/bpf/CAEf4BzYiUZtSJKh-UBL0jwyo6d=Cne2YtEyGU8ONykmSUSsuNA@mail.gmail.com/T/#m7c7ec0e7d8e803c6c357495d9eea59028a67cac6
>
> which uses trampolines. The new approach gets rid of any type
> generation and macros in security/bpf/lsm_hooks.h. Maybe the
> btf_vmlinux can be augmented at runtime to generate context struct
> upon attachment?

If it doesn't generate "controllable" types (and seems like existing
types are not readily usable as well), then we can't use vmlinux's BTF
as is. But we can augment vmlinux.h header during generation time,
based on naming convention and extra post-processing of vmlinux BTF.
That's sort of a point of special `format core` mode in bpftool, which
we currently discuss on mailing list as well, see [0].

  [0] https://lore.kernel.org/bpf/CAEf4BzY4ffWaeFckPuqNGNAU1uBG3TmTK+CjY1LVa2G+RGz=cA@mail.gmail.com/T/#u


>
> >
> > BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
> >             struct vm_area_struct *, vma,
> >             unsigned long, reqprot, unsigned long, prot) {...}
> >
> > on kernel side, you'll have:
> >
> > typedef int (*bpf_lsm_file_mprotect)(struct vm_area_struct *vma,
> >                                      unsigned long reqprot,
> >                                      unsigned long prot);
> >
> > So you can see that user has to go and copy/paste all the arguments
> > and their types and paste them in this verbose BPF_TRACE_3 macro to
> > define correct BPF program.
> >
> > Now, imagine that instead of typedef above, we define equivalent struct:
> >
> > struct bpf_lsm_file_mprotect {
> >     struct vm_area_struct *vma;
> >     unsigned long reqprot;
> >     unsigned long prot;
> > };
> >
> > This type will get dumped into vmlinux.h, which can be used from BPF
> > user code as such:
> >
> > SEC("lsm/file_mprotect")
> > int mprotect_audito(struct bpf_lsm_file_mprotect *ctx)
> > {
> >     ... here you can use ctx->vma, ctx->reqprot, ctx->prot ...
> > }
> >
> >
> > Meanwhile, there will be just minimal changes to BPF verifier to use
> > such struct instead of func_proto for verification of LSM programs.
> >
> > We currently have similar issue with raw_tp programs and I've been
> > thinking about switching that to structs instead of func_proto, so we
> > might as well coordinate that and reuse the same logic in BPF
> > verifier.
> >
> > Thoughts?
>
> Thanks for the explanation!
>
> Using structs is definitely better if we chose to go with static type
> generation.
>

Yes, that's what I think is preferable for tp_btf programs as well.

> - KP
>
> >
> >
> >
> > > +               },
> > > +       #include "hooks.h"
> > > +       #undef BPF_LSM_HOOK
> > > +};
> > > +
> >
> > [...]

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

* Re: [PATCH bpf-next v1 09/13] bpf: lsm: Add a helper function bpf_lsm_event_output
  2019-12-30 15:11     ` KP Singh
@ 2019-12-30 18:56       ` Andrii Nakryiko
  0 siblings, 0 replies; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-30 18:56 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Mon, Dec 30, 2019 at 7:11 AM KP Singh <kpsingh@chromium.org> wrote:
>
> On 23-Dec 22:36, Andrii Nakryiko wrote:
> > On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
> > >
> > > From: KP Singh <kpsingh@google.com>
> > >
> > > This helper is similar to bpf_perf_event_output except that
> > > it does need a ctx argument which is more usable in the
> > > BTF based LSM programs where the context is converted to
> > > the signature of the attacthed BTF type.
> > >
> > > An example usage of this function would be:
> > >
> > > struct {
> > >          __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
> > >          __uint(key_size, sizeof(int));
> > >          __uint(value_size, sizeof(u32));
> > > } perf_map SEC(".maps");
> > >
> > > BPF_TRACE_1(bpf_prog1, "lsm/bprm_check_security,
> > >             struct linux_binprm *, bprm)
> > > {
> > >         char buf[BUF_SIZE];
> > >         int len;
> > >         u64 flags = BPF_F_CURRENT_CPU;
> > >
> > >         /* some logic that fills up buf with len data */
> > >         len = fill_up_buf(buf);
> > >         if (len < 0)
> > >                 return len;
> > >         if (len > BU)
> > >                 return 0;
> > >
> > >         bpf_lsm_event_output(&perf_map, flags, buf, len);
> >
> > This seems to be generally useful and not LSM-specific, so maybe name
> > it more generically as bpf_event_output instead?
>
> Agreed, I am happy to rename this.
>
> >
> > I'm also curious why we needed both bpf_perf_event_output and
> > bpf_perf_event_output_raw_tp, if it could be done as simply as you did
> > it here. What's different between those three and why your
> > bpf_lsm_event_output doesn't need pt_regs passed into them?
>
> That's because my implementation uses the following function from
> bpf_trace.c:
>
> u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
>                      void *ctx, u64 ctx_size, bpf_ctx_copy_t ctx_copy)
>
> This does not require a pt_regs argument and handles fetching them
> internally:
>
>         regs = this_cpu_ptr(&bpf_pt_regs.regs[nest_level - 1]);
>
>         perf_fetch_caller_regs(regs);
>         perf_sample_data_init(sd, 0, 0);
>         sd->raw = &raw;
>
>         ret = __bpf_perf_event_output(regs, map, flags, sd);
>
> - KP

Yeah, I saw that bit. I guess I'm confused why we couldn't do the same
for, say, raw_tracepoint case. Now Jiri Olsa is adding another similar
helper doing its own storage of pt_regs. If all of them can share the
same (even if with bigger nest_level) array of pt_regs, that would
great.

>
> >
> > >         return 0;
> > > }
> > >
> > > Signed-off-by: KP Singh <kpsingh@google.com>
> > > ---
> > >  include/uapi/linux/bpf.h       | 10 +++++++++-
> > >  kernel/bpf/verifier.c          |  1 +
> > >  security/bpf/ops.c             | 21 +++++++++++++++++++++
> > >  tools/include/uapi/linux/bpf.h | 10 +++++++++-
> > >  4 files changed, 40 insertions(+), 2 deletions(-)
> > >
> >
> > [...]

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-30 15:04   ` KP Singh
@ 2019-12-30 18:58     ` Andrii Nakryiko
  0 siblings, 0 replies; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-30 18:58 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Mon, Dec 30, 2019 at 7:04 AM KP Singh <kpsingh@chromium.org> wrote:
>
> On 23-Dec 22:51, Andrii Nakryiko wrote:
> > On Fri, Dec 20, 2019 at 7:42 AM KP Singh <kpsingh@chromium.org> wrote:
> > >
> > > From: KP Singh <kpsingh@google.com>
> > >
> > > This patch series is a continuation of the KRSI 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 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
> >
> > Are you planning on submitting these examples for inclusion into
> > samples/bpf or selftests/bpf? It would be great to have more examples
> > and we can review and suggest nicer ways to go about writing them
> > (e.g., BPF skeleton and global data Alexei mentioned earlier).
>
> Eventually, yes and in selftest/bpf.
>
> But these examples depend on using security blobs and some non-atomic
> calls in the BPF helpers which are not handled as a part of the
> initial patch-set.
>
> Once we have the initial framework finalized, I will update the
> examples and the helpers they are based on and send these separate
> patch-sets on the list for review.

Great! The reason I was asking is that once they are in selftests, it
would be nice to switch them to use all the latest BPF usability
improvements to make code cleaner and have it as another good example
of modern BPF program. Like use BTF-defined maps, BPF skeleton,
vmlinux.h, etc. We can go over this when the time comes, though :)


>
> - KP
>
> >
> > >
> > > 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 (13):
> > >   bpf: Refactor BPF_EVENT context macros to its own header.
> > >   bpf: lsm: Add a skeleton and config options
> > >   bpf: lsm: Introduce types for eBPF based LSM
> > >   bpf: lsm: Allow btf_id based attachment for LSM hooks
> > >   tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM
> > >   bpf: lsm: Init Hooks and create files in securityfs
> > >   bpf: lsm: Implement attach, detach and execution.
> > >   bpf: lsm: Show attached program names in hook read handler.
> > >   bpf: lsm: Add a helper function bpf_lsm_event_output
> > >   bpf: lsm: Handle attachment of the same program
> > >   tools/libbpf: Add bpf_program__attach_lsm
> > >   bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
> > >   bpf: lsm: Add Documentation
> > >
> >
> > [...]

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-30 14:58   ` KP Singh
@ 2019-12-30 19:14     ` Andrii Nakryiko
  0 siblings, 0 replies; 74+ messages in thread
From: Andrii Nakryiko @ 2019-12-30 19:14 UTC (permalink / raw)
  To: KP Singh
  Cc: Alexei Starovoitov, open list, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, James Morris, Kees Cook,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

On Mon, Dec 30, 2019 at 6:59 AM KP Singh <kpsingh@chromium.org> wrote:
>
> On 21-Dez 17:27, Alexei Starovoitov wrote:
> > On Fri, Dec 20, 2019 at 04:41:55PM +0100, KP Singh wrote:
> > > // Declare the eBPF program mprotect_audit which attaches to
> > > // to the file_mprotect LSM hook and accepts three arguments.
> > > BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
> > >         struct vm_area_struct *, vma,
> > >         unsigned long, reqprot, unsigned long, prot
> > > {
> > >     unsigned long vm_start = _(vma->vm_start);
> > >     return 0;
> > > }
> >
>
> Hi Alexei,
>
> Thanks for the feedback. This is really helpful!
>
> > I think the only sore point of the patchset is:
> > security/bpf/include/hooks.h   | 1015 ++++++++++++++++++++++++++++++++
> > With bpf trampoline this type of 'kernel types -> bpf types' converters
> > are no longer necessary. Please take a look at tcp-congestion-control patchset:
> > https://patchwork.ozlabs.org/cover/1214417/
> > Instead of doing similar thing (like your patch 1 plus patch 6) it's using
> > trampoline to provide bpf based congestion control callbacks into tcp stack.
> > The same trampoline-based mechanism can be reused by bpf_lsm.
> > Then all manual work of doing BPF_LSM_HOOK(...) for every hook won't be
> > necessary. It will also prove the point that attaching BPF to raw LSM hooks
> > doesn't freeze them into stable abi.
>
> Really cool!
>
> I looked into how BPF trampolines are being used in tracing and the
> new STRUCT_OPS patchset and was able protoype
> (https://github.com/sinkap/linux-krsi/tree/patch/v1/trampoline_prototype,
> not ready for review yet) which:
>
> * Gets rid of security/bpf/include/hooks.h and all of the static
>   macro magic essentially making the LSM ~truly instrumentable~ at
>   runtime.
> * Gets rid of the generation of any new types as we already have
>   all the BTF information in the kernel in the following two types:
>
> struct security_hook_heads {
>         .
>         .
>         struct hlist_head file_mprotect;   <- Append the callback at this offset
>         .
>         .
> };
>
> and
>
> union security_list_options {
>         int (*file_mprotect)(struct vm_area_struct *vma, unsigned long reqprot,
>                                 unsigned long prot);
> };
>
> Which is the same type as the typedef that's currently being generated
> , i.e. lsm_btf_file_mprotect
>
> In the current prototype, libbpf converts the name of the hook into an
> offset into the security_hook_heads and the verifier does the
> following when a program is loaded:
>
> * Verifies the offset and the type at the offset (struct hlist_head).
> * Resolves the func_proto (by looking up the type in
>   security_list_options) and updates prog->aux with the name and
>   func_proto which are then verified similar to raw_tp programs with
>   btf_ctx_access.
>
> On attachment:
>
> * A trampoline is created and appended to the security_hook_heads
>   for the BPF LSM.
> * An anonymous FD is returned and the attachment is conditional on the
>   references to FD (as suggested and similar to fentry/fexit tracing
>   programs).
>
> This implies that the BPF programs are "the LSM hook" as opposed to
> being executed inside a statically defined hook body which requires
> mutable LSM hooks for which I was able to re-use some of ideas in
> Sargun's patch:
>
> https://lore.kernel.org/lkml/20180408065916.GA2832@ircssh-2.c.rugged-nimbus-611.internal/
>
> to maintain a separate security_hook_heads struct for dynamically
> added LSM hooks by the BPF LSM which are executed after all the
> statically defined hooks.
>
> > Longer program names are supplied via btf's func_info.
> > It feels that:
> > cat /sys/kernel/security/bpf/process_execution
> > env_dumper__v2
> > is reinventing the wheel. bpftool is the main introspection tool.
> > It can print progs attached to perf, cgroup, networking. I think it's better to
> > stay consistent and do the same with bpf-lsm.
>
> I agree, based on the new feedback, I don't think we need securityFS
> attachment points anymore. I was able to get rid of it completely.
>
> >
> > Another issue is in proposed attaching method:
> > hook_fd = open("/sys/kernel/security/bpf/process_execution");
> > sys_bpf(attach, prog_fd, hook_fd);
> > With bpf tracing we moved to FD-based attaching, because permanent attaching is
> > problematic in production. We're going to provide FD-based api to attach to
> > networking as well, because xdp/tc/cgroup prog attaching suffers from the same
> > production issues. Mainly with permanent attaching there is no ownership of
> > attachment. Everything is global and permanent. It's not clear what
> > process/script suppose to detach/cleanup. I suggest bpf-lsm use FD-based
> > attaching from the beginning. Take a look at raw_tp/tp_btf/fentry/fexit style
> > of attaching. All of them return FD which represents what libbpf calls
> > 'bpf_link' concept. Once refcnt of that FD goes to zero that link (attachment)
> > is destroyed and program is detached _by the kernel_. To make such links
> > permanent the application can pin them in bpffs. The pinning patches haven't
> > landed yet, but the concept of the link is quite powerful and much more
> > production friendly than permanent attaching.
>
> I like this. This also means we don't immediately need the handling of
> duplicate names so I dropped that bit of the patch as well and updated
> the attachment to use this mechanism.
>
> > bpf-lsm will still be able to attach multiple progs to the same hook and
> > see what is attached via bpftool.
> >
> > The rest looks good. Thank you for working on it.
>
> There are some choices we need to make here from an API perspective:
>
> * Should we "repurpose" attr->attach_btf_id and use it as an offset
>   into security_hook_heads or add a new attribute
>   (e.g lsm_hook_offset) for the offset or use name of the LSM hook
>   (e.g. lsm_hook_name).

I think setting this to member index inside union
security_list_options will be better? Or member index inside struct
security_hook_heads. Seems like kernel will have to "join" those two
anyways, right (one for type info, another for trampoline)? Offset is
less convenient either way.

> * Since we don't have the files in securityFS, the attachment does not
>   have a target_fd. Should we add a new type of BPF command?
>   e.g. LSM_HOOK_OPEN?

Semantics of LSM program seems closer to fentry/fexit/raw_tp, so maybe
instead use BPF_RAW_TRACEPOINT_OPEN command? On libbpf side it's all
going to be abstracted behind bpf_program__attach() anyways.

>
> I will clean up the prototype, incorporate some of the other feedback
> received, and send a v2.
>
> Wishing everyone a very Happy New Year!

Thanks, you too!

>
> - KP
>

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-20 17:38   ` KP Singh
@ 2019-12-30 19:15     ` Kees Cook
  2020-01-08 15:25       ` Stephen Smalley
  2020-01-08 18:27       ` James Morris
  0 siblings, 2 replies; 74+ messages in thread
From: Kees Cook @ 2019-12-30 19:15 UTC (permalink / raw)
  To: KP Singh
  Cc: Casey Schaufler, open list, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, James Morris,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

On Fri, Dec 20, 2019 at 06:38:45PM +0100, KP Singh wrote:
> Hi Casey,
> 
> Thanks for taking a look!
> 
> On Fri, Dec 20, 2019 at 6:17 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
> >
> > On 12/20/2019 7:41 AM, KP Singh wrote:
> > > From: KP Singh <kpsingh@google.com>
> > >
> > > This patch series is a continuation of the KRSI RFC
> > > (https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/)
> > >
> > > # Motivation
> > >
> > > Google does rich analysis of runtime security data collected from
> > > internal Linux deployments (corporate devices and servers) 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 proposes a new stackable and privileged LSM which allows
> > > the LSM hooks to be implemented using eBPF. 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 LSM introduces a new eBPF (https://docs.cilium.io/en/v1.6/bpf/)
> > > program type, BPF_PROG_TYPE_LSM, which can only be attached to a LSM
> > > hook.  All LSM hooks are exposed as files in securityfs. Attachment
> > > requires CAP_SYS_ADMIN for loading eBPF programs and CAP_MAC_ADMIN for
> > > modifying MAC policies.
> > >
> > > The eBPF programs are passed the same arguments as the LSM hooks and
> > > executed in the body of the hook.
> >
> > This effectively exposes the LSM hooks as external APIs.
> > It would mean that we can't change or delete them. That
> > would be bad.
> 
> Perhaps this should have been clearer, we *do not* want to make LSM hooks
> a stable API and expect the eBPF programs to adapt when such changes occur.
> 
> Based on our comparison with the previous approach, this still ends up
> being a better trade-off (w.r.t. maintenance) when compared to adding
> specific helpers or verifier logic for  each new hook or field that
> needs to be exposed.

Given the discussion around tracing and stable ABI at the last kernel
summit, Linus's mandate is mainly around "every day users" and not
around these system-builder-sensitive cases where everyone has a strong
expectation to rebuild their policy when the kernel changes. i.e. it's
not "powertop", which was Linus's example of "and then everyone running
Fedora breaks".

So, while I know we've tried in the past to follow the letter of the
law, it seems Linus really expects this only to be followed when it will
have "real world" impact on unsuspecting end users.

Obviously James Morris has the final say here, but as I understand it,
it is fine to expose these here for the same reasons it's fine to expose
the (ever changing) tracepoints and BPF hooks.

-Kees

-- 
Kees Cook

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

* Re: [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs
  2019-12-30 15:37     ` KP Singh
  2019-12-30 18:52       ` Andrii Nakryiko
@ 2019-12-30 19:20       ` Kees Cook
  2020-01-03 23:53         ` KP Singh
  1 sibling, 1 reply; 74+ messages in thread
From: Kees Cook @ 2019-12-30 19:20 UTC (permalink / raw)
  To: KP Singh
  Cc: Andrii Nakryiko, open list, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, James Morris,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

On Mon, Dec 30, 2019 at 04:37:11PM +0100, KP Singh wrote:
> On 23-Dec 22:28, Andrii Nakryiko wrote:
> > On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
> > [...]
> 
> Good catch! You're right. These macros will not be there in v2 as
> we move to using trampolines based callbacks.

Speaking of which -- is the BPF trampoline code correctly designed to be
W^X?

-- 
Kees Cook

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

* Re: [PATCH bpf-next v1 04/13] bpf: lsm: Allow btf_id based attachment for LSM hooks
  2019-12-23 23:54   ` Andrii Nakryiko
@ 2019-12-30 19:22     ` KP Singh
  0 siblings, 0 replies; 74+ messages in thread
From: KP Singh @ 2019-12-30 19:22 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On 23-Dez 15:54, Andrii Nakryiko wrote:
> On Fri, Dec 20, 2019 at 7:42 AM KP Singh <kpsingh@chromium.org> wrote:
> >
> > From: KP Singh <kpsingh@google.com>
> >
> > Refactor and re-use most of the logic for BPF_PROG_TYPE_TRACING with a few
> > changes.
> >
> > - The LSM hook BTF types are prefixed with "lsm_btf_"

Got rid of this for v2 as we are using trampoline. Will keep this in
mind if we ever need to generate type information. Thanks!

> 
> btf_trace_ and btf_struct_ops all have btf_ first, let's keep this consistent.
> 
> > - These types do not need the first (void *) pointer argument. The verifier
> >   only looks for this argument if prod->aux->attach_btf_trace is set.
> >
> > Signed-off-by: KP Singh <kpsingh@google.com>
> > ---
> >  kernel/bpf/syscall.c  |  1 +
> >  kernel/bpf/verifier.c | 83 ++++++++++++++++++++++++++++++++++++++++---
> >  2 files changed, 80 insertions(+), 4 deletions(-)
> >
> 
> [...]
> 
> > +
> > +       t = btf_type_by_id(btf_vmlinux, btf_id);
> > +       if (!t) {
> > +               verbose(env, "attach_btf_id %u is invalid\n", btf_id);
> > +               return -EINVAL;
> > +       }
> > +
> > +       tname = btf_name_by_offset(btf_vmlinux, t->name_off);
> > +       if (!tname) {
> 
> it can be empty, so better: !tname || !tname[0]

Will fix the usages in v2. 

- KP
> 
> > +               verbose(env, "attach_btf_id %u doesn't have a name\n", btf_id);
> > +               return -EINVAL;
> > +       }
> > +
> 
> [...]

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-20 22:46 ` Mickaël Salaün
@ 2019-12-30 19:30   ` Kees Cook
  2019-12-31 12:11     ` Mickaël Salaün
  0 siblings, 1 reply; 74+ messages in thread
From: Kees Cook @ 2019-12-30 19:30 UTC (permalink / raw)
  To: Mickaël Salaün
  Cc: KP Singh, linux-kernel, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, James Morris,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner, Florent Revest,
	Brendan Jackman, Martin KaFai Lau, Song Liu, Yonghong Song,
	Serge E. Hallyn, Mauro Carvalho Chehab, David S. Miller,
	Greg Kroah-Hartman, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer,
	Mickaël Salaün

On Fri, Dec 20, 2019 at 11:46:47PM +0100, Mickaël Salaün wrote:
> I'm working on a version of Landlock without eBPF, but still with the
> initial sought properties: safe unprivileged composability, modularity, and
> dynamic update. I'll send this version soon.
> 
> I hope that the work and experience from Landlock to bring eBPF to LSM will
> continue to be used through KRSI. Landlock will now focus on the
> unprivileged sandboxing part, without eBPF. Stay tuned!

Will it end up looking at all like pledge? I'm still struggling to come
up with a sensible pledge-like design on top of seccomp, especially
given the need to have it very closely tied to the running libc...

-- 
Kees Cook

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-30 19:30   ` Kees Cook
@ 2019-12-31 12:11     ` Mickaël Salaün
  0 siblings, 0 replies; 74+ messages in thread
From: Mickaël Salaün @ 2019-12-31 12:11 UTC (permalink / raw)
  To: Kees Cook
  Cc: KP Singh, linux-kernel, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, James Morris,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner, Florent Revest,
	Brendan Jackman, Martin KaFai Lau, Song Liu, Yonghong Song,
	Serge E. Hallyn, Mauro Carvalho Chehab, David S. Miller,
	Greg Kroah-Hartman, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer,
	Mickaël Salaün


On 30/12/2019 20:30, Kees Cook wrote:
> On Fri, Dec 20, 2019 at 11:46:47PM +0100, Mickaël Salaün wrote:
>> I'm working on a version of Landlock without eBPF, but still with the
>> initial sought properties: safe unprivileged composability, modularity, and
>> dynamic update. I'll send this version soon.
>>
>> I hope that the work and experience from Landlock to bring eBPF to LSM will
>> continue to be used through KRSI. Landlock will now focus on the
>> unprivileged sandboxing part, without eBPF. Stay tuned!
> 
> Will it end up looking at all like pledge? I'm still struggling to come
> up with a sensible pledge-like design on top of seccomp, especially
> given the need to have it very closely tied to the running libc...
> 

Yes, it's similar to Pledge/Unveil but with fine-grained control (and a
more flexible design). And because it is not tied to syscall, there is
no similar issues than with seccomp and libc. In fact, there is no more
relationship with seccomp neither. The version I'm working on is similar
in principle to the patch series v10 [1], without the usage complexity
brought by eBPF, but with a more polished file-based access-control. The
demo from LSS 2018 [2] gives an overview of the possibilities.

[1] https://lore.kernel.org/lkml/20190721213116.23476-1-mic@digikod.net/
[2] https://landlock.io/talks/2018-08-27_landlock-lss_demo-1-web.mkv

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

* Re: [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs
  2019-12-30 19:20       ` Kees Cook
@ 2020-01-03 23:53         ` KP Singh
  0 siblings, 0 replies; 74+ messages in thread
From: KP Singh @ 2020-01-03 23:53 UTC (permalink / raw)
  To: Kees Cook
  Cc: Andrii Nakryiko, open list, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, James Morris,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer

On 30-Dez 11:20, Kees Cook wrote:
> On Mon, Dec 30, 2019 at 04:37:11PM +0100, KP Singh wrote:
> > On 23-Dec 22:28, Andrii Nakryiko wrote:
> > > On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
> > > [...]
> > 
> > Good catch! You're right. These macros will not be there in v2 as
> > we move to using trampolines based callbacks.
> 
> Speaking of which -- is the BPF trampoline code correctly designed to be
> W^X?

Thanks for pointing this out!

I don't think this is the case as of now.

The dispatcher logic and the tracing programs allocate one page where
one half of it is used for the active trampoline and the other half is
used as a staging area for a future replacement. I sent a patch as an
attempt to fix this:

   https://lore.kernel.org/bpf/20200103234725.22846-1-kpsingh@chromium.org/T/#u

- KP

> 
> -- 
> Kees Cook

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

* Re: [PATCH bpf-next v1 05/13] tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM
  2019-12-24  0:07   ` Andrii Nakryiko
  2019-12-24  0:09     ` Andrii Nakryiko
@ 2020-01-03 23:59     ` KP Singh
  1 sibling, 0 replies; 74+ messages in thread
From: KP Singh @ 2020-01-03 23:59 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On 23-Dez 16:07, Andrii Nakryiko wrote:
> On Fri, Dec 20, 2019 at 7:43 AM KP Singh <kpsingh@chromium.org> wrote:
> >
> > From: KP Singh <kpsingh@google.com>
> >
> > Update the libbpf library with functionality to load and
> > attach a program type BPF_PROG_TYPE_LSM, currently with
> > only one expected attach type BPF_LSM_MAC.
> >
> > Signed-off-by: KP Singh <kpsingh@google.com>
> > ---
> >  tools/lib/bpf/bpf.c           |  2 +-
> >  tools/lib/bpf/bpf.h           |  6 +++++
> >  tools/lib/bpf/libbpf.c        | 44 +++++++++++++++++++++--------------
> >  tools/lib/bpf/libbpf.h        |  2 ++
> >  tools/lib/bpf/libbpf.map      |  6 +++++
> >  tools/lib/bpf/libbpf_probes.c |  1 +
> >  6 files changed, 43 insertions(+), 18 deletions(-)
> >
> > diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
> > index 98596e15390f..9c6fb083f7de 100644
> > --- a/tools/lib/bpf/bpf.c
> > +++ b/tools/lib/bpf/bpf.c
> > @@ -228,7 +228,7 @@ 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_TRACING) {
> > +       if (needs_btf_attach(attr.prog_type)) {
> >                 attr.attach_btf_id = load_attr->attach_btf_id;
> >                 attr.attach_prog_fd = load_attr->attach_prog_fd;
> >         } else {
> > diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
> > index 3c791fa8e68e..df2a00ff349f 100644
> > --- a/tools/lib/bpf/bpf.h
> > +++ b/tools/lib/bpf/bpf.h
> > @@ -177,6 +177,12 @@ LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
> >                                  __u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
> >                                  __u64 *probe_offset, __u64 *probe_addr);
> >
> > +static inline bool needs_btf_attach(enum bpf_prog_type prog_type)
> > +{
> > +       return (prog_type == BPF_PROG_TYPE_TRACING ||
> > +               prog_type == BPF_PROG_TYPE_LSM);
> > +}
> > +
> 
> This doesn't have to be a public API, right? It also doesn't follow
> naming conventions of libbpf APIs. Let's just move it into
> libbpf_internal.h, given it's used in few files.
> 
> Also, Martin's patches add STRUCT_OPS, which do need btf_attach, but
> don't set attach_prog_fd. So maybe something like
> libbpf_need_attach_prog_btf() for a name to be a bit more specific?

Updated for the next revision. Thanks!

> 
> 
> >  #ifdef __cplusplus
> >  } /* extern "C" */
> >  #endif
> > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > index b20f82e58989..b0b27d8e5a37 100644
> > --- a/tools/lib/bpf/libbpf.c
> > +++ b/tools/lib/bpf/libbpf.c
> > @@ -3738,7 +3738,7 @@ 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_TRACING) {
> > +       if (needs_btf_attach(prog->type)) {
> >                 load_attr.attach_prog_fd = prog->attach_prog_fd;
> >                 load_attr.attach_btf_id = prog->attach_btf_id;
> >         } else {
> > @@ -3983,7 +3983,7 @@ __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
> >
> >                 bpf_program__set_type(prog, prog_type);
> >                 bpf_program__set_expected_attach_type(prog, attach_type);
> > -               if (prog_type == BPF_PROG_TYPE_TRACING) {
> > +               if (needs_btf_attach(prog_type)) {
> >                         err = libbpf_find_attach_btf_id(prog->section_name,
> >                                                         attach_type,
> >                                                         attach_prog_fd);
> > @@ -4933,6 +4933,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);
> > @@ -5009,6 +5010,8 @@ static const struct {
> >         BPF_PROG_SEC("lwt_out",                 BPF_PROG_TYPE_LWT_OUT),
> >         BPF_PROG_SEC("lwt_xmit",                BPF_PROG_TYPE_LWT_XMIT),
> >         BPF_PROG_SEC("lwt_seg6local",           BPF_PROG_TYPE_LWT_SEG6LOCAL),
> > +       BPF_PROG_BTF("lsm/",                    BPF_PROG_TYPE_LSM,
> > +                                               BPF_LSM_MAC),
> 
> Is is supposed to be attachable same as BPF_PROG_TYPE_TRACING
> programs? If yes, please define auto-attaching function, similar to
> SEC_DEF("raw_tp") few lines below this one.

Nice! rebased and updated. 

> 
> >         BPF_APROG_SEC("cgroup_skb/ingress",     BPF_PROG_TYPE_CGROUP_SKB,
> >                                                 BPF_CGROUP_INET_INGRESS),
> >         BPF_APROG_SEC("cgroup_skb/egress",      BPF_PROG_TYPE_CGROUP_SKB,
> > @@ -5119,32 +5122,39 @@ int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
> >         return -ESRCH;
> >  }
> >
> > -#define BTF_PREFIX "btf_trace_"
> > +static inline int __btf__typdef_with_prefix(struct btf *btf, const char *name,
> 
> typo: typdef -> typedef
> 
> But actually let's generalize it to pass BTF_KIND as another param, I
> think I have a need for this (we might want to do that for structs,
> not just typedef->func_proto).
> Following btf__find_by_name_kind() naming, it probably should be
> called btf__find_by_prefix_kind()?

Thanks! Good idea, updated. Should this be moved to btf.c?

> 
> > +                                           const char *prefix)
> > +{
> > +
> > +       size_t prefix_len = strlen(prefix);
> > +       char btf_type_name[128];
> > +
> > +       strcpy(btf_type_name, prefix);
> > +       strncat(btf_type_name, name, sizeof(btf_type_name) - (prefix_len + 1));
> 
> at this point snprintf(btf_type_name, "%s%.*%s", prefix,
> sizeof(btf_type_name) - prefix_len - 1, name) looks like a better and
> cleaner alternative.

I just changed it to:

  snprintf(btf_type_name, sizeof(btf_type_name), "%s%s", prefix, name);
 
- KP

> 
> > +       return btf__find_by_name_kind(btf, btf_type_name, BTF_KIND_TYPEDEF);
> > +}
> > +
> > +#define BTF_TRACE_PREFIX "btf_trace_"
> > +#define BTF_LSM_PREFIX "lsm_btf_"
> > +
> 
> [...]

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

* Re: [PATCH bpf-next v1 12/13] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
  2019-12-24  6:49   ` Andrii Nakryiko
@ 2020-01-04  0:09     ` KP Singh
  2020-01-09 17:59       ` Andrii Nakryiko
  0 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2020-01-04  0:09 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On 23-Dez 22:49, Andrii Nakryiko wrote:
> On Fri, Dec 20, 2019 at 7:42 AM KP Singh <kpsingh@chromium.org> wrote:
> >
> > From: KP Singh <kpsingh@google.com>
> >
> > * Load a BPF program that audits mprotect calls
> > * Attach the program to the "file_mprotect" LSM hook
> > * Verify if the program is actually loading by reading
> >   securityfs
> > * Initialize the perf events buffer and poll for audit events
> > * Do an mprotect on some memory allocated on the heap
> > * Verify if the audit event was received
> >
> > Signed-off-by: KP Singh <kpsingh@google.com>
> > ---
> >  MAINTAINERS                                   |   2 +
> >  .../bpf/prog_tests/lsm_mprotect_audit.c       | 129 ++++++++++++++++++
> >  .../selftests/bpf/progs/lsm_mprotect_audit.c  |  58 ++++++++
> >  3 files changed, 189 insertions(+)
> >  create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
> >  create mode 100644 tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c
> >
> 
> [...]
> 
> > +/*
> > + * Define some of the structs used in the BPF program.
> > + * Only the field names and their sizes need to be the
> > + * same as the kernel type, the order is irrelevant.
> > + */
> > +struct mm_struct {
> > +       unsigned long start_brk, brk, start_stack;
> > +};
> > +
> > +struct vm_area_struct {
> > +       unsigned long start_brk, brk, start_stack;
> > +       unsigned long vm_start, vm_end;
> > +       struct mm_struct *vm_mm;
> > +       unsigned long vm_flags;
> > +};
> > +
> > +BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
> > +           struct vm_area_struct *, vma,
> > +           unsigned long, reqprot, unsigned long, prot)
> > +{
> > +       struct mprotect_audit_log audit_log = {};
> > +       int is_heap = 0;
> > +
> > +       __builtin_preserve_access_index(({
> 
> you don't need __builtin_preserve_access_index, if you mark
> vm_area_struct and mm_struct with
> __attribute__((preserve_access_index)

Cool, updated!

> 
> > +               is_heap = (vma->vm_start >= vma->vm_mm->start_brk &&
> > +                                    vma->vm_end <= vma->vm_mm->brk);
> > +       }));
> > +
> > +       audit_log.magic = MPROTECT_AUDIT_MAGIC;
> > +       audit_log.is_heap = is_heap;
> > +       bpf_lsm_event_output(&perf_buf_map, BPF_F_CURRENT_CPU, &audit_log,
> > +                            sizeof(audit_log));
> 
> You test would be much simpler if you use global variables to pass
> data back to userspace, instead of using perf buffer.
> 
> Also please see fentry_fexit.c test for example of using BPF skeleton
> to shorten and simpify userspace part of test.

Thanks for the skeleton work!

This makes using global variables easier and the tests are indeed much
simpler, I have updated it for the next revision.

One follow up question regarding global variables, let's say I have
the following global variable defined in the BPF program:

struct result_info {
        __u32 count;
}; 

struct result_info result = {
        .count = 0,
};

The defintion of result_info needs to be included before the .skel.h
as it's not automatically generated or maybe I am missing a
trick here?

For now, I have defined this in a header which gets included both in
the program and the test.

- KP

> 
> > +       return 0;
> > +}
> > --
> > 2.20.1
> >

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

* Re: [PATCH bpf-next v1 02/13] bpf: lsm: Add a skeleton and config options
  2019-12-20 15:41 ` [PATCH bpf-next v1 02/13] bpf: lsm: Add a skeleton and config options KP Singh
@ 2020-01-07 21:13   ` James Morris
  0 siblings, 0 replies; 74+ messages in thread
From: James Morris @ 2020-01-07 21:13 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Thomas Garnier, Michael Halcrow,
	Paul Turner, Brendan Gregg, Jann Horn, Matthew Garrett,
	Christian Brauner, Mickaël Salaün, Florent Revest,
	Brendan Jackman, Martin KaFai Lau, Song Liu, Yonghong Song,
	Serge E. Hallyn, Mauro Carvalho Chehab, David S. Miller,
	Greg Kroah-Hartman, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, 20 Dec 2019, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> The LSM can be enabled by CONFIG_SECURITY_BPF.
> Without CONFIG_SECURITY_BPF_ENFORCE, the LSM will run the
> attached eBPF programs but not enforce MAC policy based
> on the return value of the attached programs.
> 
> Signed-off-by: KP Singh <kpsingh@google.com>


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


-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs
  2019-12-20 15:42 ` [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs KP Singh
  2019-12-24  6:28   ` Andrii Nakryiko
@ 2020-01-07 21:22   ` James Morris
  1 sibling, 0 replies; 74+ messages in thread
From: James Morris @ 2020-01-07 21:22 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Thomas Garnier, Michael Halcrow,
	Paul Turner, Brendan Gregg, Jann Horn, Matthew Garrett,
	Christian Brauner, Mickaël Salaün, Florent Revest,
	Brendan Jackman, Martin KaFai Lau, Song Liu, Yonghong Song,
	Serge E. Hallyn, Mauro Carvalho Chehab, David S. Miller,
	Greg Kroah-Hartman, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, 20 Dec 2019, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> The LSM creates files in securityfs for each hook registered with the
> LSM.
> 
>     /sys/kernel/security/bpf/<h_name>
> 
> The list of LSM hooks are maintained in an internal header "hooks.h"
> Eventually, this list should either be defined collectively in
> include/linux/lsm_hooks.h or auto-generated from it.
> 
> * Creation of a file for the hook in the securityfs.
> * Allocation of a bpf_lsm_hook data structure which stores
>   a pointer to the dentry of the newly created file in securityfs.
> * Creation of a typedef for the hook so that BTF information
>   can be generated for the LSM hooks to:
> 
>   - Make them "Compile Once, Run Everywhere".
>   - Pass the right arguments when the attached programs are run.
>   - Verify the accesses made by the program by using the BTF
>     information.
> 
> Signed-off-by: KP Singh <kpsingh@google.com>


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


-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 07/13] bpf: lsm: Implement attach, detach and execution.
  2019-12-20 15:42 ` [PATCH bpf-next v1 07/13] bpf: lsm: Implement attach, detach and execution KP Singh
  2019-12-24  5:48   ` Andrii Nakryiko
@ 2020-01-07 21:27   ` James Morris
  1 sibling, 0 replies; 74+ messages in thread
From: James Morris @ 2020-01-07 21:27 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Thomas Garnier, Michael Halcrow,
	Paul Turner, Brendan Gregg, Jann Horn, Matthew Garrett,
	Christian Brauner, Mickaël Salaün, Florent Revest,
	Brendan Jackman, Martin KaFai Lau, Song Liu, Yonghong Song,
	Serge E. Hallyn, Mauro Carvalho Chehab, David S. Miller,
	Greg Kroah-Hartman, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, 20 Dec 2019, KP Singh wrote:

>  
> -	h_dentry = securityfs_create_file(h->name, 0600, parent,
> -			NULL, &hook_ops);
> +	h_dentry = securityfs_create_file(h->name, 0600,
> +					  parent, NULL, &hook_ops);

Minor thing to fix for the next version.


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


-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 08/13] bpf: lsm: Show attached program names in hook read handler.
  2019-12-20 15:42 ` [PATCH bpf-next v1 08/13] bpf: lsm: Show attached program names in hook read handler KP Singh
@ 2020-01-07 21:28   ` James Morris
  0 siblings, 0 replies; 74+ messages in thread
From: James Morris @ 2020-01-07 21:28 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Thomas Garnier, Michael Halcrow,
	Paul Turner, Brendan Gregg, Jann Horn, Matthew Garrett,
	Christian Brauner, Mickaël Salaün, Florent Revest,
	Brendan Jackman, Martin KaFai Lau, Song Liu, Yonghong Song,
	Serge E. Hallyn, Mauro Carvalho Chehab, David S. Miller,
	Greg Kroah-Hartman, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, 20 Dec 2019, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> For inspectability the system administrator should be able to view the
> list of active KRSI programs:
> 
>    bash # cat /sys/kernel/security/bpf/bprm_check_security
>    bpf_prog1
> 
> Signed-off-by: KP Singh <kpsingh@google.com>


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


-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-30 19:15     ` Kees Cook
@ 2020-01-08 15:25       ` Stephen Smalley
  2020-01-08 18:58         ` James Morris
  2020-01-08 18:27       ` James Morris
  1 sibling, 1 reply; 74+ messages in thread
From: Stephen Smalley @ 2020-01-08 15:25 UTC (permalink / raw)
  To: Kees Cook, KP Singh
  Cc: Casey Schaufler, open list, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, James Morris,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On 12/30/19 2:15 PM, Kees Cook wrote:
> On Fri, Dec 20, 2019 at 06:38:45PM +0100, KP Singh wrote:
>> Hi Casey,
>>
>> Thanks for taking a look!
>>
>> On Fri, Dec 20, 2019 at 6:17 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
>>>
>>> On 12/20/2019 7:41 AM, KP Singh wrote:
>>>> From: KP Singh <kpsingh@google.com>
>>>>
>>>> This patch series is a continuation of the KRSI RFC
>>>> (https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@chromium.org/)
>>>>
>>>> # Motivation
>>>>
>>>> Google does rich analysis of runtime security data collected from
>>>> internal Linux deployments (corporate devices and servers) 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 proposes a new stackable and privileged LSM which allows
>>>> the LSM hooks to be implemented using eBPF. 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 LSM introduces a new eBPF (https://docs.cilium.io/en/v1.6/bpf/)
>>>> program type, BPF_PROG_TYPE_LSM, which can only be attached to a LSM
>>>> hook.  All LSM hooks are exposed as files in securityfs. Attachment
>>>> requires CAP_SYS_ADMIN for loading eBPF programs and CAP_MAC_ADMIN for
>>>> modifying MAC policies.
>>>>
>>>> The eBPF programs are passed the same arguments as the LSM hooks and
>>>> executed in the body of the hook.
>>>
>>> This effectively exposes the LSM hooks as external APIs.
>>> It would mean that we can't change or delete them. That
>>> would be bad.
>>
>> Perhaps this should have been clearer, we *do not* want to make LSM hooks
>> a stable API and expect the eBPF programs to adapt when such changes occur.
>>
>> Based on our comparison with the previous approach, this still ends up
>> being a better trade-off (w.r.t. maintenance) when compared to adding
>> specific helpers or verifier logic for  each new hook or field that
>> needs to be exposed.
> 
> Given the discussion around tracing and stable ABI at the last kernel
> summit, Linus's mandate is mainly around "every day users" and not
> around these system-builder-sensitive cases where everyone has a strong
> expectation to rebuild their policy when the kernel changes. i.e. it's
> not "powertop", which was Linus's example of "and then everyone running
> Fedora breaks".
> 
> So, while I know we've tried in the past to follow the letter of the
> law, it seems Linus really expects this only to be followed when it will
> have "real world" impact on unsuspecting end users.
> 
> Obviously James Morris has the final say here, but as I understand it,
> it is fine to expose these here for the same reasons it's fine to expose
> the (ever changing) tracepoints and BPF hooks.

This appears to impose a very different standard to this eBPF-based LSM 
than has been applied to the existing LSMs, e.g. we are required to 
preserve SELinux policy compatibility all the way back to Linux 2.6.0 
such that new kernel with old policy does not break userspace.  If that 
standard isn't being applied to the eBPF-based LSM, it seems to inhibit 
its use in major Linux distros, since otherwise users will in fact start 
experiencing breakage on the first such incompatible change.  Not 
arguing for or against, just trying to make sure I understand correctly...




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

* Re: [PATCH bpf-next v1 10/13] bpf: lsm: Handle attachment of the same program
  2019-12-20 15:42 ` [PATCH bpf-next v1 10/13] bpf: lsm: Handle attachment of the same program KP Singh
  2019-12-24  6:38   ` Andrii Nakryiko
@ 2020-01-08 18:21   ` James Morris
  1 sibling, 0 replies; 74+ messages in thread
From: James Morris @ 2020-01-08 18:21 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Thomas Garnier, Michael Halcrow,
	Paul Turner, Brendan Gregg, Jann Horn, Matthew Garrett,
	Christian Brauner, Mickaël Salaün, Florent Revest,
	Brendan Jackman, Martin KaFai Lau, Song Liu, Yonghong Song,
	Serge E. Hallyn, Mauro Carvalho Chehab, David S. Miller,
	Greg Kroah-Hartman, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, 20 Dec 2019, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> Allow userspace to attach a newer version of a program without having
> duplicates of the same program.
> 
> If BPF_F_ALLOW_OVERRIDE is passed, the attachment logic compares the
> name of the new program to the names of existing attached programs. The
> names are only compared till a "__" (or '\0', if there is no "__"). If
> a successful match is found, the existing program is replaced with the
> newer attachment.
> 
> ./loader Attaches "env_dumper__v1" followed by "env_dumper__v2"
> to the bprm_check_security hook..
> 
> ./loader
> ./loader
> 
> Before:
> 
>   cat /sys/kernel/security/bpf/process_execution
>   env_dumper__v1
>   env_dumper__v2
> 
> After:
> 
>   cat /sys/kernel/security/bpf/process_execution
>   env_dumper__v2
> 
> Signed-off-by: KP Singh <kpsingh@google.com>


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


-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 11/13] tools/libbpf: Add bpf_program__attach_lsm
  2019-12-20 15:42 ` [PATCH bpf-next v1 11/13] tools/libbpf: Add bpf_program__attach_lsm KP Singh
  2019-12-24  6:44   ` Andrii Nakryiko
@ 2020-01-08 18:24   ` James Morris
  1 sibling, 0 replies; 74+ messages in thread
From: James Morris @ 2020-01-08 18:24 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Thomas Garnier, Michael Halcrow,
	Paul Turner, Brendan Gregg, Jann Horn, Matthew Garrett,
	Christian Brauner, Mickaël Salaün, Florent Revest,
	Brendan Jackman, Martin KaFai Lau, Song Liu, Yonghong Song,
	Serge E. Hallyn, Mauro Carvalho Chehab, David S. Miller,
	Greg Kroah-Hartman, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, 20 Dec 2019, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> Add functionality in libbpf to attach eBPF program to LSM hooks.
> 
> Signed-off-by: KP Singh <kpsingh@google.com>


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


-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 12/13] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
  2019-12-20 15:42 ` [PATCH bpf-next v1 12/13] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM KP Singh
  2019-12-24  6:49   ` Andrii Nakryiko
@ 2020-01-08 18:25   ` James Morris
  1 sibling, 0 replies; 74+ messages in thread
From: James Morris @ 2020-01-08 18:25 UTC (permalink / raw)
  To: KP Singh
  Cc: linux-kernel, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, Kees Cook, Thomas Garnier, Michael Halcrow,
	Paul Turner, Brendan Gregg, Jann Horn, Matthew Garrett,
	Christian Brauner, Mickaël Salaün, Florent Revest,
	Brendan Jackman, Martin KaFai Lau, Song Liu, Yonghong Song,
	Serge E. Hallyn, Mauro Carvalho Chehab, David S. Miller,
	Greg Kroah-Hartman, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, 20 Dec 2019, KP Singh wrote:

> From: KP Singh <kpsingh@google.com>
> 
> * Load a BPF program that audits mprotect calls
> * Attach the program to the "file_mprotect" LSM hook
> * Verify if the program is actually loading by reading
>   securityfs
> * Initialize the perf events buffer and poll for audit events
> * Do an mprotect on some memory allocated on the heap
> * Verify if the audit event was received
> 
> Signed-off-by: KP Singh <kpsingh@google.com>

Good to see!


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


-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2019-12-30 19:15     ` Kees Cook
  2020-01-08 15:25       ` Stephen Smalley
@ 2020-01-08 18:27       ` James Morris
  1 sibling, 0 replies; 74+ messages in thread
From: James Morris @ 2020-01-08 18:27 UTC (permalink / raw)
  To: Kees Cook
  Cc: KP Singh, Casey Schaufler, open list, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Mon, 30 Dec 2019, Kees Cook wrote:

> 
> Given the discussion around tracing and stable ABI at the last kernel
> summit, Linus's mandate is mainly around "every day users" and not
> around these system-builder-sensitive cases where everyone has a strong
> expectation to rebuild their policy when the kernel changes. i.e. it's
> not "powertop", which was Linus's example of "and then everyone running
> Fedora breaks".
> 
> So, while I know we've tried in the past to follow the letter of the
> law, it seems Linus really expects this only to be followed when it will
> have "real world" impact on unsuspecting end users.
> 
> Obviously James Morris has the final say here, but as I understand it,
> it is fine to expose these here for the same reasons it's fine to expose
> the (ever changing) tracepoints and BPF hooks.

Agreed. This API should be seen in the same light as tracing / debugging, 
and it should not be exposed by users directly to general purpose 
applications.


-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-08 15:25       ` Stephen Smalley
@ 2020-01-08 18:58         ` James Morris
  2020-01-08 19:33           ` Stephen Smalley
  0 siblings, 1 reply; 74+ messages in thread
From: James Morris @ 2020-01-08 18:58 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Kees Cook, KP Singh, Casey Schaufler, open list, bpf,
	linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On Wed, 8 Jan 2020, Stephen Smalley wrote:

> This appears to impose a very different standard to this eBPF-based LSM than
> has been applied to the existing LSMs, e.g. we are required to preserve
> SELinux policy compatibility all the way back to Linux 2.6.0 such that new
> kernel with old policy does not break userspace.  If that standard isn't being
> applied to the eBPF-based LSM, it seems to inhibit its use in major Linux
> distros, since otherwise users will in fact start experiencing breakage on the
> first such incompatible change.  Not arguing for or against, just trying to
> make sure I understand correctly...

A different standard would be applied here vs. a standard LSM like 
SELinux, which are retrofitted access control systems.

I see KRSI as being more of a debugging / analytical API, rather than an 
access control system. You could of course build such a system with KRSI 
but it would need to provide a layer of abstraction for general purpose 
users.

So yes this would be a special case, as its real value is in being a 
special case, i.e. dynamic security telemetry.


-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-08 18:58         ` James Morris
@ 2020-01-08 19:33           ` Stephen Smalley
  2020-01-09 18:11             ` James Morris
  0 siblings, 1 reply; 74+ messages in thread
From: Stephen Smalley @ 2020-01-08 19:33 UTC (permalink / raw)
  To: James Morris
  Cc: Kees Cook, KP Singh, Casey Schaufler, open list, bpf,
	linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On 1/8/20 1:58 PM, James Morris wrote:
> On Wed, 8 Jan 2020, Stephen Smalley wrote:
> 
>> This appears to impose a very different standard to this eBPF-based LSM than
>> has been applied to the existing LSMs, e.g. we are required to preserve
>> SELinux policy compatibility all the way back to Linux 2.6.0 such that new
>> kernel with old policy does not break userspace.  If that standard isn't being
>> applied to the eBPF-based LSM, it seems to inhibit its use in major Linux
>> distros, since otherwise users will in fact start experiencing breakage on the
>> first such incompatible change.  Not arguing for or against, just trying to
>> make sure I understand correctly...
> 
> A different standard would be applied here vs. a standard LSM like
> SELinux, which are retrofitted access control systems.
> 
> I see KRSI as being more of a debugging / analytical API, rather than an
> access control system. You could of course build such a system with KRSI
> but it would need to provide a layer of abstraction for general purpose
> users.
> 
> So yes this would be a special case, as its real value is in being a
> special case, i.e. dynamic security telemetry.

The cover letter subject line and the Kconfig help text refer to it as a 
BPF-based "MAC and Audit policy".  It has an enforce config option that 
enables the bpf programs to deny access, providing access control. IIRC, 
in the earlier discussion threads, the BPF maintainers suggested that 
Smack and other LSMs could be entirely re-implemented via it in the 
future, and that such an implementation would be more optimal.

Again, not arguing for or against, but wondering if people fully 
understand the implications.  If it ends up being useful, people will 
build access control systems with it, and it directly exposes a lot of 
kernel internals to userspace.  There was a lot of concern originally 
about the LSM hook interface becoming a stable ABI and/or about it being 
misused.  Exposing that interface along with every kernel data structure 
exposed through it to userspace seems like a major leap.  Even if the 
mainline kernel doesn't worry about any kind of stable interface 
guarantees for it, the distros might be forced to provide some kABI 
guarantees for it to appease ISVs and users...

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

* Re: [PATCH bpf-next v1 12/13] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM
  2020-01-04  0:09     ` KP Singh
@ 2020-01-09 17:59       ` Andrii Nakryiko
  0 siblings, 0 replies; 74+ messages in thread
From: Andrii Nakryiko @ 2020-01-09 17:59 UTC (permalink / raw)
  To: KP Singh
  Cc: open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, James Morris, Kees Cook, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer

On Fri, Jan 3, 2020 at 4:09 PM KP Singh <kpsingh@chromium.org> wrote:
>
> On 23-Dez 22:49, Andrii Nakryiko wrote:
> > On Fri, Dec 20, 2019 at 7:42 AM KP Singh <kpsingh@chromium.org> wrote:
> > >
> > > From: KP Singh <kpsingh@google.com>
> > >
> > > * Load a BPF program that audits mprotect calls
> > > * Attach the program to the "file_mprotect" LSM hook
> > > * Verify if the program is actually loading by reading
> > >   securityfs
> > > * Initialize the perf events buffer and poll for audit events
> > > * Do an mprotect on some memory allocated on the heap
> > > * Verify if the audit event was received
> > >
> > > Signed-off-by: KP Singh <kpsingh@google.com>
> > > ---
> > >  MAINTAINERS                                   |   2 +
> > >  .../bpf/prog_tests/lsm_mprotect_audit.c       | 129 ++++++++++++++++++
> > >  .../selftests/bpf/progs/lsm_mprotect_audit.c  |  58 ++++++++
> > >  3 files changed, 189 insertions(+)
> > >  create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_mprotect_audit.c
> > >  create mode 100644 tools/testing/selftests/bpf/progs/lsm_mprotect_audit.c
> > >
> >
> > [...]
> >
> > > +/*
> > > + * Define some of the structs used in the BPF program.
> > > + * Only the field names and their sizes need to be the
> > > + * same as the kernel type, the order is irrelevant.
> > > + */
> > > +struct mm_struct {
> > > +       unsigned long start_brk, brk, start_stack;
> > > +};
> > > +
> > > +struct vm_area_struct {
> > > +       unsigned long start_brk, brk, start_stack;
> > > +       unsigned long vm_start, vm_end;
> > > +       struct mm_struct *vm_mm;
> > > +       unsigned long vm_flags;
> > > +};
> > > +
> > > +BPF_TRACE_3("lsm/file_mprotect", mprotect_audit,
> > > +           struct vm_area_struct *, vma,
> > > +           unsigned long, reqprot, unsigned long, prot)
> > > +{
> > > +       struct mprotect_audit_log audit_log = {};
> > > +       int is_heap = 0;
> > > +
> > > +       __builtin_preserve_access_index(({
> >
> > you don't need __builtin_preserve_access_index, if you mark
> > vm_area_struct and mm_struct with
> > __attribute__((preserve_access_index)
>
> Cool, updated!
>
> >
> > > +               is_heap = (vma->vm_start >= vma->vm_mm->start_brk &&
> > > +                                    vma->vm_end <= vma->vm_mm->brk);
> > > +       }));
> > > +
> > > +       audit_log.magic = MPROTECT_AUDIT_MAGIC;
> > > +       audit_log.is_heap = is_heap;
> > > +       bpf_lsm_event_output(&perf_buf_map, BPF_F_CURRENT_CPU, &audit_log,
> > > +                            sizeof(audit_log));
> >
> > You test would be much simpler if you use global variables to pass
> > data back to userspace, instead of using perf buffer.
> >
> > Also please see fentry_fexit.c test for example of using BPF skeleton
> > to shorten and simpify userspace part of test.
>
> Thanks for the skeleton work!
>
> This makes using global variables easier and the tests are indeed much
> simpler, I have updated it for the next revision.
>
> One follow up question regarding global variables, let's say I have
> the following global variable defined in the BPF program:
>
> struct result_info {
>         __u32 count;
> };
>
> struct result_info result = {
>         .count = 0,
> };
>
> The defintion of result_info needs to be included before the .skel.h
> as it's not automatically generated or maybe I am missing a
> trick here?
>
> For now, I have defined this in a header which gets included both in
> the program and the test.

Yes, ideally all common types should be shared in a common header. My
initial implementation actually supported dumping out all the types in
a generated skeleton, but that was inconvenient in a lot of cases, so
I dropped that.

>
> - KP
>
> >
> > > +       return 0;
> > > +}
> > > --
> > > 2.20.1
> > >

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-08 19:33           ` Stephen Smalley
@ 2020-01-09 18:11             ` James Morris
  2020-01-09 18:23               ` Greg Kroah-Hartman
                                 ` (2 more replies)
  0 siblings, 3 replies; 74+ messages in thread
From: James Morris @ 2020-01-09 18:11 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Kees Cook, KP Singh, Casey Schaufler, open list, bpf,
	linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On Wed, 8 Jan 2020, Stephen Smalley wrote:

> The cover letter subject line and the Kconfig help text refer to it as a
> BPF-based "MAC and Audit policy".  It has an enforce config option that
> enables the bpf programs to deny access, providing access control. IIRC, in
> the earlier discussion threads, the BPF maintainers suggested that Smack and
> other LSMs could be entirely re-implemented via it in the future, and that
> such an implementation would be more optimal.

In this case, the eBPF code is similar to a kernel module, rather than a 
loadable policy file.  It's a loadable mechanism, rather than a policy, in 
my view.

This would be similar to the difference between iptables rules and 
loadable eBPF networking code.  I'd be interested to know how the 
eBPF networking scenarios are handled wrt kernel ABI.


> Again, not arguing for or against, but wondering if people fully understand
> the implications.  If it ends up being useful, people will build access
> control systems with it, and it directly exposes a lot of kernel internals to
> userspace.  There was a lot of concern originally about the LSM hook interface
> becoming a stable ABI and/or about it being misused.  Exposing that interface
> along with every kernel data structure exposed through it to userspace seems
> like a major leap.

Agreed this is a leap, although I'm not sure I'd characterize it as 
exposure to userspace -- it allows dynamic extension of the LSM API from 
userland, but the code is executed in the kernel.

KP: One thing I'd like to understand better is the attack surface 
introduced by this.  IIUC, the BTF fields are read only, so the eBPF code 
should not be able to modify any LSM parameters, correct?


>  Even if the mainline kernel doesn't worry about any kind
> of stable interface guarantees for it, the distros might be forced to provide
> some kABI guarantees for it to appease ISVs and users...

How is this handled currently for other eBPF use-cases?

-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-09 18:11             ` James Morris
@ 2020-01-09 18:23               ` Greg Kroah-Hartman
  2020-01-09 18:58               ` Stephen Smalley
  2020-01-09 19:11               ` KP Singh
  2 siblings, 0 replies; 74+ messages in thread
From: Greg Kroah-Hartman @ 2020-01-09 18:23 UTC (permalink / raw)
  To: James Morris
  Cc: Stephen Smalley, Kees Cook, KP Singh, Casey Schaufler, open list,
	bpf, linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Nicolas Ferre,
	Stanislav Fomichev, Quentin Monnet, Andrey Ignatov, Joe Stringer,
	Paul Moore

On Fri, Jan 10, 2020 at 05:11:38AM +1100, James Morris wrote:
> On Wed, 8 Jan 2020, Stephen Smalley wrote:
> 
> > The cover letter subject line and the Kconfig help text refer to it as a
> > BPF-based "MAC and Audit policy".  It has an enforce config option that
> > enables the bpf programs to deny access, providing access control. IIRC, in
> > the earlier discussion threads, the BPF maintainers suggested that Smack and
> > other LSMs could be entirely re-implemented via it in the future, and that
> > such an implementation would be more optimal.
> 
> In this case, the eBPF code is similar to a kernel module, rather than a 
> loadable policy file.  It's a loadable mechanism, rather than a policy, in 
> my view.
> 
> This would be similar to the difference between iptables rules and 
> loadable eBPF networking code.  I'd be interested to know how the 
> eBPF networking scenarios are handled wrt kernel ABI.

I already know of some people who pre-compile ebpf programs based on a
number of "supported" kernel versions and then load the needed one at
runtime.

Messy, yes, but you are right, ebpf code is much more similiar to a
kernel module than userspace code at the moment.

thanks,

greg k-h

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-09 18:11             ` James Morris
  2020-01-09 18:23               ` Greg Kroah-Hartman
@ 2020-01-09 18:58               ` Stephen Smalley
  2020-01-09 19:07                 ` James Morris
  2020-01-09 19:11               ` KP Singh
  2 siblings, 1 reply; 74+ messages in thread
From: Stephen Smalley @ 2020-01-09 18:58 UTC (permalink / raw)
  To: James Morris
  Cc: Kees Cook, KP Singh, Casey Schaufler, open list, bpf,
	linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On 1/9/20 1:11 PM, James Morris wrote:
> On Wed, 8 Jan 2020, Stephen Smalley wrote:
> 
>> The cover letter subject line and the Kconfig help text refer to it as a
>> BPF-based "MAC and Audit policy".  It has an enforce config option that
>> enables the bpf programs to deny access, providing access control. IIRC, in
>> the earlier discussion threads, the BPF maintainers suggested that Smack and
>> other LSMs could be entirely re-implemented via it in the future, and that
>> such an implementation would be more optimal.
> 
> In this case, the eBPF code is similar to a kernel module, rather than a
> loadable policy file.  It's a loadable mechanism, rather than a policy, in
> my view.

I thought you frowned on dynamically loadable LSMs for both security and 
correctness reasons? And a traditional security module would necessarily 
fall under GPL; is the eBPF code required to be likewise?  If not, KRSI 
is a gateway for proprietary LSMs...

> This would be similar to the difference between iptables rules and
> loadable eBPF networking code.  I'd be interested to know how the
> eBPF networking scenarios are handled wrt kernel ABI.
> 
> 
>> Again, not arguing for or against, but wondering if people fully understand
>> the implications.  If it ends up being useful, people will build access
>> control systems with it, and it directly exposes a lot of kernel internals to
>> userspace.  There was a lot of concern originally about the LSM hook interface
>> becoming a stable ABI and/or about it being misused.  Exposing that interface
>> along with every kernel data structure exposed through it to userspace seems
>> like a major leap.
> 
> Agreed this is a leap, although I'm not sure I'd characterize it as
> exposure to userspace -- it allows dynamic extension of the LSM API from
> userland, but the code is executed in the kernel.
> 
> KP: One thing I'd like to understand better is the attack surface
> introduced by this.  IIUC, the BTF fields are read only, so the eBPF code
> should not be able to modify any LSM parameters, correct?
> 
> 
>>   Even if the mainline kernel doesn't worry about any kind
>> of stable interface guarantees for it, the distros might be forced to provide
>> some kABI guarantees for it to appease ISVs and users...
> 
> How is this handled currently for other eBPF use-cases?
> 


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-09 18:58               ` Stephen Smalley
@ 2020-01-09 19:07                 ` James Morris
  2020-01-09 19:43                   ` KP Singh
  0 siblings, 1 reply; 74+ messages in thread
From: James Morris @ 2020-01-09 19:07 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Kees Cook, KP Singh, Casey Schaufler, open list, bpf,
	linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On Thu, 9 Jan 2020, Stephen Smalley wrote:

> On 1/9/20 1:11 PM, James Morris wrote:
> > On Wed, 8 Jan 2020, Stephen Smalley wrote:
> > 
> > > The cover letter subject line and the Kconfig help text refer to it as a
> > > BPF-based "MAC and Audit policy".  It has an enforce config option that
> > > enables the bpf programs to deny access, providing access control. IIRC,
> > > in
> > > the earlier discussion threads, the BPF maintainers suggested that Smack
> > > and
> > > other LSMs could be entirely re-implemented via it in the future, and that
> > > such an implementation would be more optimal.
> > 
> > In this case, the eBPF code is similar to a kernel module, rather than a
> > loadable policy file.  It's a loadable mechanism, rather than a policy, in
> > my view.
> 
> I thought you frowned on dynamically loadable LSMs for both security and
> correctness reasons?

Evaluating the security impact of this is the next step. My understanding 
is that eBPF via BTF is constrained to read only access to hook 
parameters, and that its behavior would be entirely restrictive.

I'd like to understand the security impact more fully, though.  Can the 
eBPF code make arbitrary writes to the kernel, or read anything other than 
the correctly bounded LSM hook parameters?

> And a traditional security module would necessarily fall
> under GPL; is the eBPF code required to be likewise?  If not, KRSI is a
> gateway for proprietary LSMs...

Right, we do not want this to be a GPL bypass.

If these issues can be resolved, this may be a "safe" way to support 
loadable LSM applications.

Again, I'd be interested in knowing how this is is handled in the 
networking stack (keeping in mind that LSM is a much more invasive API, 
and may not be directly comparable).

-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-09 18:11             ` James Morris
  2020-01-09 18:23               ` Greg Kroah-Hartman
  2020-01-09 18:58               ` Stephen Smalley
@ 2020-01-09 19:11               ` KP Singh
  2 siblings, 0 replies; 74+ messages in thread
From: KP Singh @ 2020-01-09 19:11 UTC (permalink / raw)
  To: James Morris
  Cc: Stephen Smalley, Kees Cook, Casey Schaufler, open list, bpf,
	linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On 10-Jan 05:11, James Morris wrote:
> On Wed, 8 Jan 2020, Stephen Smalley wrote:
> 
> > The cover letter subject line and the Kconfig help text refer to it as a
> > BPF-based "MAC and Audit policy".  It has an enforce config option that
> > enables the bpf programs to deny access, providing access control. IIRC, in
> > the earlier discussion threads, the BPF maintainers suggested that Smack and
> > other LSMs could be entirely re-implemented via it in the future, and that
> > such an implementation would be more optimal.
> 
> In this case, the eBPF code is similar to a kernel module, rather than a 
> loadable policy file.  It's a loadable mechanism, rather than a policy, in 
> my view.
> 
> This would be similar to the difference between iptables rules and 
> loadable eBPF networking code.  I'd be interested to know how the 
> eBPF networking scenarios are handled wrt kernel ABI.
> 
> 
> > Again, not arguing for or against, but wondering if people fully understand
> > the implications.  If it ends up being useful, people will build access
> > control systems with it, and it directly exposes a lot of kernel internals to
> > userspace.  There was a lot of concern originally about the LSM hook interface
> > becoming a stable ABI and/or about it being misused.  Exposing that interface
> > along with every kernel data structure exposed through it to userspace seems
> > like a major leap.
> 
> Agreed this is a leap, although I'm not sure I'd characterize it as 
> exposure to userspace -- it allows dynamic extension of the LSM API from 
> userland, but the code is executed in the kernel.
> 
> KP: One thing I'd like to understand better is the attack surface 
> introduced by this.  IIUC, the BTF fields are read only, so the eBPF code 
> should not be able to modify any LSM parameters, correct?
> 

That's correct, the verifier does not allow writes to BTF types:

from kernel/bpf/verifier.c:

        case PTR_TO_BTF_ID:
	if (type == BPF_WRITE) {
	        verbose(env, "Writes through BTF pointers are not allowed\n");
		return -EINVAL;
	}

We can also add additional checks on top of those added by the
verifier using the verifier_ops that each BPF program type can define. 

- KP

> 
> >  Even if the mainline kernel doesn't worry about any kind
> > of stable interface guarantees for it, the distros might be forced to provide
> > some kABI guarantees for it to appease ISVs and users...
> 
> How is this handled currently for other eBPF use-cases?
> 
> -- 
> James Morris
> <jmorris@namei.org>
> 

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-09 19:07                 ` James Morris
@ 2020-01-09 19:43                   ` KP Singh
  2020-01-09 19:47                     ` Stephen Smalley
  0 siblings, 1 reply; 74+ messages in thread
From: KP Singh @ 2020-01-09 19:43 UTC (permalink / raw)
  To: James Morris
  Cc: Stephen Smalley, Kees Cook, KP Singh, Casey Schaufler, open list,
	bpf, linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On 10-Jan 06:07, James Morris wrote:
> On Thu, 9 Jan 2020, Stephen Smalley wrote:
> 
> > On 1/9/20 1:11 PM, James Morris wrote:
> > > On Wed, 8 Jan 2020, Stephen Smalley wrote:
> > > 
> > > > The cover letter subject line and the Kconfig help text refer to it as a
> > > > BPF-based "MAC and Audit policy".  It has an enforce config option that
> > > > enables the bpf programs to deny access, providing access control. IIRC,
> > > > in
> > > > the earlier discussion threads, the BPF maintainers suggested that Smack
> > > > and
> > > > other LSMs could be entirely re-implemented via it in the future, and that
> > > > such an implementation would be more optimal.
> > > 
> > > In this case, the eBPF code is similar to a kernel module, rather than a
> > > loadable policy file.  It's a loadable mechanism, rather than a policy, in
> > > my view.
> > 
> > I thought you frowned on dynamically loadable LSMs for both security and
> > correctness reasons?

Based on the feedback from the lists we've updated the design for v2.

In v2, LSM hook callbacks are allocated dynamically using BPF
trampolines, appended to a separate security_hook_heads and run
only after the statically allocated hooks.

The security_hook_heads for all the other LSMs (SELinux, AppArmor etc)
still remains __lsm_ro_after_init and cannot be modified. We are still
working on v2 (not ready for review yet) but the general idea can be
seen here:

  https://github.com/sinkap/linux-krsi/blob/patch/v1/trampoline_prototype/security/bpf/lsm.c

> 
> Evaluating the security impact of this is the next step. My understanding 
> is that eBPF via BTF is constrained to read only access to hook 
> parameters, and that its behavior would be entirely restrictive.
> 
> I'd like to understand the security impact more fully, though.  Can the 
> eBPF code make arbitrary writes to the kernel, or read anything other than 
> the correctly bounded LSM hook parameters?
> 

As mentioned, the BPF verifier does not allow writes to BTF types.

> > And a traditional security module would necessarily fall
> > under GPL; is the eBPF code required to be likewise?  If not, KRSI is a
> > gateway for proprietary LSMs...
> 
> Right, we do not want this to be a GPL bypass.

This is not intended to be a GPL bypass and the BPF verifier checks
for license compatibility of the loaded program with GPL.

- KP

> 
> If these issues can be resolved, this may be a "safe" way to support 
> loadable LSM applications.
> 
> Again, I'd be interested in knowing how this is is handled in the 
> networking stack (keeping in mind that LSM is a much more invasive API, 
> and may not be directly comparable).
> 
> -- 
> James Morris
> <jmorris@namei.org>
> 

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-09 19:43                   ` KP Singh
@ 2020-01-09 19:47                     ` Stephen Smalley
  2020-01-10 15:27                       ` KP Singh
  0 siblings, 1 reply; 74+ messages in thread
From: Stephen Smalley @ 2020-01-09 19:47 UTC (permalink / raw)
  To: KP Singh, James Morris
  Cc: Kees Cook, Casey Schaufler, open list, bpf,
	linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On 1/9/20 2:43 PM, KP Singh wrote:
> On 10-Jan 06:07, James Morris wrote:
>> On Thu, 9 Jan 2020, Stephen Smalley wrote:
>>
>>> On 1/9/20 1:11 PM, James Morris wrote:
>>>> On Wed, 8 Jan 2020, Stephen Smalley wrote:
>>>>
>>>>> The cover letter subject line and the Kconfig help text refer to it as a
>>>>> BPF-based "MAC and Audit policy".  It has an enforce config option that
>>>>> enables the bpf programs to deny access, providing access control. IIRC,
>>>>> in
>>>>> the earlier discussion threads, the BPF maintainers suggested that Smack
>>>>> and
>>>>> other LSMs could be entirely re-implemented via it in the future, and that
>>>>> such an implementation would be more optimal.
>>>>
>>>> In this case, the eBPF code is similar to a kernel module, rather than a
>>>> loadable policy file.  It's a loadable mechanism, rather than a policy, in
>>>> my view.
>>>
>>> I thought you frowned on dynamically loadable LSMs for both security and
>>> correctness reasons?
> 
> Based on the feedback from the lists we've updated the design for v2.
> 
> In v2, LSM hook callbacks are allocated dynamically using BPF
> trampolines, appended to a separate security_hook_heads and run
> only after the statically allocated hooks.
> 
> The security_hook_heads for all the other LSMs (SELinux, AppArmor etc)
> still remains __lsm_ro_after_init and cannot be modified. We are still
> working on v2 (not ready for review yet) but the general idea can be
> seen here:
> 
>    https://github.com/sinkap/linux-krsi/blob/patch/v1/trampoline_prototype/security/bpf/lsm.c
> 
>>
>> Evaluating the security impact of this is the next step. My understanding
>> is that eBPF via BTF is constrained to read only access to hook
>> parameters, and that its behavior would be entirely restrictive.
>>
>> I'd like to understand the security impact more fully, though.  Can the
>> eBPF code make arbitrary writes to the kernel, or read anything other than
>> the correctly bounded LSM hook parameters?
>>
> 
> As mentioned, the BPF verifier does not allow writes to BTF types.
> 
>>> And a traditional security module would necessarily fall
>>> under GPL; is the eBPF code required to be likewise?  If not, KRSI is a
>>> gateway for proprietary LSMs...
>>
>> Right, we do not want this to be a GPL bypass.
> 
> This is not intended to be a GPL bypass and the BPF verifier checks
> for license compatibility of the loaded program with GPL.

IIUC, it checks that the program is GPL compatible if it uses a function 
marked GPL-only.  But what specifically is marked GPL-only that is 
required for eBPF programs using KRSI?

> 
> - KP
> 
>>
>> If these issues can be resolved, this may be a "safe" way to support
>> loadable LSM applications.
>>
>> Again, I'd be interested in knowing how this is is handled in the
>> networking stack (keeping in mind that LSM is a much more invasive API,
>> and may not be directly comparable).
>>
>> -- 
>> James Morris
>> <jmorris@namei.org>
>>


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-09 19:47                     ` Stephen Smalley
@ 2020-01-10 15:27                       ` KP Singh
  2020-01-10 17:48                         ` James Morris
  2020-01-10 17:53                         ` Alexei Starovoitov
  0 siblings, 2 replies; 74+ messages in thread
From: KP Singh @ 2020-01-10 15:27 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: KP Singh, James Morris, Kees Cook, Casey Schaufler, open list,
	bpf, linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On 09-Jan 14:47, Stephen Smalley wrote:
> On 1/9/20 2:43 PM, KP Singh wrote:
> > On 10-Jan 06:07, James Morris wrote:
> > > On Thu, 9 Jan 2020, Stephen Smalley wrote:
> > > 
> > > > On 1/9/20 1:11 PM, James Morris wrote:
> > > > > On Wed, 8 Jan 2020, Stephen Smalley wrote:
> > > > > 
> > > > > > The cover letter subject line and the Kconfig help text refer to it as a
> > > > > > BPF-based "MAC and Audit policy".  It has an enforce config option that
> > > > > > enables the bpf programs to deny access, providing access control. IIRC,
> > > > > > in
> > > > > > the earlier discussion threads, the BPF maintainers suggested that Smack
> > > > > > and
> > > > > > other LSMs could be entirely re-implemented via it in the future, and that
> > > > > > such an implementation would be more optimal.
> > > > > 
> > > > > In this case, the eBPF code is similar to a kernel module, rather than a
> > > > > loadable policy file.  It's a loadable mechanism, rather than a policy, in
> > > > > my view.
> > > > 
> > > > I thought you frowned on dynamically loadable LSMs for both security and
> > > > correctness reasons?
> > 
> > Based on the feedback from the lists we've updated the design for v2.
> > 
> > In v2, LSM hook callbacks are allocated dynamically using BPF
> > trampolines, appended to a separate security_hook_heads and run
> > only after the statically allocated hooks.
> > 
> > The security_hook_heads for all the other LSMs (SELinux, AppArmor etc)
> > still remains __lsm_ro_after_init and cannot be modified. We are still
> > working on v2 (not ready for review yet) but the general idea can be
> > seen here:
> > 
> >    https://github.com/sinkap/linux-krsi/blob/patch/v1/trampoline_prototype/security/bpf/lsm.c
> > 
> > > 
> > > Evaluating the security impact of this is the next step. My understanding
> > > is that eBPF via BTF is constrained to read only access to hook
> > > parameters, and that its behavior would be entirely restrictive.
> > > 
> > > I'd like to understand the security impact more fully, though.  Can the
> > > eBPF code make arbitrary writes to the kernel, or read anything other than
> > > the correctly bounded LSM hook parameters?
> > > 
> > 
> > As mentioned, the BPF verifier does not allow writes to BTF types.
> > 
> > > > And a traditional security module would necessarily fall
> > > > under GPL; is the eBPF code required to be likewise?  If not, KRSI is a
> > > > gateway for proprietary LSMs...
> > > 
> > > Right, we do not want this to be a GPL bypass.
> > 
> > This is not intended to be a GPL bypass and the BPF verifier checks
> > for license compatibility of the loaded program with GPL.
> 
> IIUC, it checks that the program is GPL compatible if it uses a function
> marked GPL-only.  But what specifically is marked GPL-only that is required
> for eBPF programs using KRSI?

Good point! If no-one objects, I can add it to the BPF_PROG_TYPE_LSM
specific verification for the v2 of the patch-set which would require
all BPF-LSM programs to be GPL.

- KP

> 
> > 
> > - KP
> > 
> > > 
> > > If these issues can be resolved, this may be a "safe" way to support
> > > loadable LSM applications.
> > > 
> > > Again, I'd be interested in knowing how this is is handled in the
> > > networking stack (keeping in mind that LSM is a much more invasive API,
> > > and may not be directly comparable).
> > > 
> > > -- 
> > > James Morris
> > > <jmorris@namei.org>
> > > 
> 

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-10 15:27                       ` KP Singh
@ 2020-01-10 17:48                         ` James Morris
  2020-01-10 17:53                         ` Alexei Starovoitov
  1 sibling, 0 replies; 74+ messages in thread
From: James Morris @ 2020-01-10 17:48 UTC (permalink / raw)
  To: KP Singh
  Cc: Stephen Smalley, Kees Cook, Casey Schaufler, open list, bpf,
	linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On Fri, 10 Jan 2020, KP Singh wrote:

> 
> Good point! If no-one objects, I can add it to the BPF_PROG_TYPE_LSM
> specific verification for the v2 of the patch-set which would require
> all BPF-LSM programs to be GPL.

Sounds good to me.

-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-10 15:27                       ` KP Singh
  2020-01-10 17:48                         ` James Morris
@ 2020-01-10 17:53                         ` Alexei Starovoitov
  2020-01-14 16:54                           ` Stephen Smalley
  1 sibling, 1 reply; 74+ messages in thread
From: Alexei Starovoitov @ 2020-01-10 17:53 UTC (permalink / raw)
  To: KP Singh
  Cc: Stephen Smalley, James Morris, Kees Cook, Casey Schaufler,
	open list, bpf, linux-security-module, Alexei Starovoitov,
	Daniel Borkmann, Thomas Garnier, Michael Halcrow, Paul Turner,
	Brendan Gregg, Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On Fri, Jan 10, 2020 at 04:27:58PM +0100, KP Singh wrote:
> On 09-Jan 14:47, Stephen Smalley wrote:
> > On 1/9/20 2:43 PM, KP Singh wrote:
> > > On 10-Jan 06:07, James Morris wrote:
> > > > On Thu, 9 Jan 2020, Stephen Smalley wrote:
> > > > 
> > > > > On 1/9/20 1:11 PM, James Morris wrote:
> > > > > > On Wed, 8 Jan 2020, Stephen Smalley wrote:
> > > > > > 
> > > > > > > The cover letter subject line and the Kconfig help text refer to it as a
> > > > > > > BPF-based "MAC and Audit policy".  It has an enforce config option that
> > > > > > > enables the bpf programs to deny access, providing access control. IIRC,
> > > > > > > in
> > > > > > > the earlier discussion threads, the BPF maintainers suggested that Smack
> > > > > > > and
> > > > > > > other LSMs could be entirely re-implemented via it in the future, and that
> > > > > > > such an implementation would be more optimal.
> > > > > > 
> > > > > > In this case, the eBPF code is similar to a kernel module, rather than a
> > > > > > loadable policy file.  It's a loadable mechanism, rather than a policy, in
> > > > > > my view.
> > > > > 
> > > > > I thought you frowned on dynamically loadable LSMs for both security and
> > > > > correctness reasons?
> > > 
> > > Based on the feedback from the lists we've updated the design for v2.
> > > 
> > > In v2, LSM hook callbacks are allocated dynamically using BPF
> > > trampolines, appended to a separate security_hook_heads and run
> > > only after the statically allocated hooks.
> > > 
> > > The security_hook_heads for all the other LSMs (SELinux, AppArmor etc)
> > > still remains __lsm_ro_after_init and cannot be modified. We are still
> > > working on v2 (not ready for review yet) but the general idea can be
> > > seen here:
> > > 
> > >    https://github.com/sinkap/linux-krsi/blob/patch/v1/trampoline_prototype/security/bpf/lsm.c
> > > 
> > > > 
> > > > Evaluating the security impact of this is the next step. My understanding
> > > > is that eBPF via BTF is constrained to read only access to hook
> > > > parameters, and that its behavior would be entirely restrictive.
> > > > 
> > > > I'd like to understand the security impact more fully, though.  Can the
> > > > eBPF code make arbitrary writes to the kernel, or read anything other than
> > > > the correctly bounded LSM hook parameters?
> > > > 
> > > 
> > > As mentioned, the BPF verifier does not allow writes to BTF types.
> > > 
> > > > > And a traditional security module would necessarily fall
> > > > > under GPL; is the eBPF code required to be likewise?  If not, KRSI is a
> > > > > gateway for proprietary LSMs...
> > > > 
> > > > Right, we do not want this to be a GPL bypass.
> > > 
> > > This is not intended to be a GPL bypass and the BPF verifier checks
> > > for license compatibility of the loaded program with GPL.
> > 
> > IIUC, it checks that the program is GPL compatible if it uses a function
> > marked GPL-only.  But what specifically is marked GPL-only that is required
> > for eBPF programs using KRSI?
> 
> Good point! If no-one objects, I can add it to the BPF_PROG_TYPE_LSM
> specific verification for the v2 of the patch-set which would require
> all BPF-LSM programs to be GPL.

I don't think it's a good idea to enforce license on the program.
The kernel doesn't do it for modules.
For years all of BPF tracing progs were GPL because they have to use
GPL-ed helpers to do anything meaningful.
So for KRSI just make sure that all helpers are GPL-ed as well.

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-10 17:53                         ` Alexei Starovoitov
@ 2020-01-14 16:54                           ` Stephen Smalley
  2020-01-14 17:42                             ` Stephen Smalley
  0 siblings, 1 reply; 74+ messages in thread
From: Stephen Smalley @ 2020-01-14 16:54 UTC (permalink / raw)
  To: Alexei Starovoitov, KP Singh
  Cc: James Morris, Kees Cook, Casey Schaufler, open list, bpf,
	linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On 1/10/20 12:53 PM, Alexei Starovoitov wrote:
> On Fri, Jan 10, 2020 at 04:27:58PM +0100, KP Singh wrote:
>> On 09-Jan 14:47, Stephen Smalley wrote:
>>> On 1/9/20 2:43 PM, KP Singh wrote:
>>>> On 10-Jan 06:07, James Morris wrote:
>>>>> On Thu, 9 Jan 2020, Stephen Smalley wrote:
>>>>>
>>>>>> On 1/9/20 1:11 PM, James Morris wrote:
>>>>>>> On Wed, 8 Jan 2020, Stephen Smalley wrote:
>>>>>>>
>>>>>>>> The cover letter subject line and the Kconfig help text refer to it as a
>>>>>>>> BPF-based "MAC and Audit policy".  It has an enforce config option that
>>>>>>>> enables the bpf programs to deny access, providing access control. IIRC,
>>>>>>>> in
>>>>>>>> the earlier discussion threads, the BPF maintainers suggested that Smack
>>>>>>>> and
>>>>>>>> other LSMs could be entirely re-implemented via it in the future, and that
>>>>>>>> such an implementation would be more optimal.
>>>>>>>
>>>>>>> In this case, the eBPF code is similar to a kernel module, rather than a
>>>>>>> loadable policy file.  It's a loadable mechanism, rather than a policy, in
>>>>>>> my view.
>>>>>>
>>>>>> I thought you frowned on dynamically loadable LSMs for both security and
>>>>>> correctness reasons?
>>>>
>>>> Based on the feedback from the lists we've updated the design for v2.
>>>>
>>>> In v2, LSM hook callbacks are allocated dynamically using BPF
>>>> trampolines, appended to a separate security_hook_heads and run
>>>> only after the statically allocated hooks.
>>>>
>>>> The security_hook_heads for all the other LSMs (SELinux, AppArmor etc)
>>>> still remains __lsm_ro_after_init and cannot be modified. We are still
>>>> working on v2 (not ready for review yet) but the general idea can be
>>>> seen here:
>>>>
>>>>     https://github.com/sinkap/linux-krsi/blob/patch/v1/trampoline_prototype/security/bpf/lsm.c
>>>>
>>>>>
>>>>> Evaluating the security impact of this is the next step. My understanding
>>>>> is that eBPF via BTF is constrained to read only access to hook
>>>>> parameters, and that its behavior would be entirely restrictive.
>>>>>
>>>>> I'd like to understand the security impact more fully, though.  Can the
>>>>> eBPF code make arbitrary writes to the kernel, or read anything other than
>>>>> the correctly bounded LSM hook parameters?
>>>>>
>>>>
>>>> As mentioned, the BPF verifier does not allow writes to BTF types.
>>>>
>>>>>> And a traditional security module would necessarily fall
>>>>>> under GPL; is the eBPF code required to be likewise?  If not, KRSI is a
>>>>>> gateway for proprietary LSMs...
>>>>>
>>>>> Right, we do not want this to be a GPL bypass.
>>>>
>>>> This is not intended to be a GPL bypass and the BPF verifier checks
>>>> for license compatibility of the loaded program with GPL.
>>>
>>> IIUC, it checks that the program is GPL compatible if it uses a function
>>> marked GPL-only.  But what specifically is marked GPL-only that is required
>>> for eBPF programs using KRSI?
>>
>> Good point! If no-one objects, I can add it to the BPF_PROG_TYPE_LSM
>> specific verification for the v2 of the patch-set which would require
>> all BPF-LSM programs to be GPL.
> 
> I don't think it's a good idea to enforce license on the program.
> The kernel doesn't do it for modules.
> For years all of BPF tracing progs were GPL because they have to use
> GPL-ed helpers to do anything meaningful.
> So for KRSI just make sure that all helpers are GPL-ed as well.

IIUC, the example eBPF code included in this patch series showed a 
program that used a GPL-only helper for the purpose of reporting event 
output to userspace. But it could have just as easily omitted the use of 
that helper and still implemented its own arbitrary access control model 
on the LSM hooks to which it attached.  It seems like the question is 
whether the kernel developers are ok with exposing the entire LSM hook 
interface and all the associated data structures to non-GPLd code, 
irrespective of what helpers it may or may not use.



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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-14 16:54                           ` Stephen Smalley
@ 2020-01-14 17:42                             ` Stephen Smalley
  2020-01-15  2:48                               ` Alexei Starovoitov
  0 siblings, 1 reply; 74+ messages in thread
From: Stephen Smalley @ 2020-01-14 17:42 UTC (permalink / raw)
  To: Alexei Starovoitov, KP Singh
  Cc: James Morris, Kees Cook, Casey Schaufler, open list, bpf,
	linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On 1/14/20 11:54 AM, Stephen Smalley wrote:
> On 1/10/20 12:53 PM, Alexei Starovoitov wrote:
>> On Fri, Jan 10, 2020 at 04:27:58PM +0100, KP Singh wrote:
>>> On 09-Jan 14:47, Stephen Smalley wrote:
>>>> On 1/9/20 2:43 PM, KP Singh wrote:
>>>>> On 10-Jan 06:07, James Morris wrote:
>>>>>> On Thu, 9 Jan 2020, Stephen Smalley wrote:
>>>>>>
>>>>>>> On 1/9/20 1:11 PM, James Morris wrote:
>>>>>>>> On Wed, 8 Jan 2020, Stephen Smalley wrote:
>>>>>>>>
>>>>>>>>> The cover letter subject line and the Kconfig help text refer 
>>>>>>>>> to it as a
>>>>>>>>> BPF-based "MAC and Audit policy".  It has an enforce config 
>>>>>>>>> option that
>>>>>>>>> enables the bpf programs to deny access, providing access 
>>>>>>>>> control. IIRC,
>>>>>>>>> in
>>>>>>>>> the earlier discussion threads, the BPF maintainers suggested 
>>>>>>>>> that Smack
>>>>>>>>> and
>>>>>>>>> other LSMs could be entirely re-implemented via it in the 
>>>>>>>>> future, and that
>>>>>>>>> such an implementation would be more optimal.
>>>>>>>>
>>>>>>>> In this case, the eBPF code is similar to a kernel module, 
>>>>>>>> rather than a
>>>>>>>> loadable policy file.  It's a loadable mechanism, rather than a 
>>>>>>>> policy, in
>>>>>>>> my view.
>>>>>>>
>>>>>>> I thought you frowned on dynamically loadable LSMs for both 
>>>>>>> security and
>>>>>>> correctness reasons?
>>>>>
>>>>> Based on the feedback from the lists we've updated the design for v2.
>>>>>
>>>>> In v2, LSM hook callbacks are allocated dynamically using BPF
>>>>> trampolines, appended to a separate security_hook_heads and run
>>>>> only after the statically allocated hooks.
>>>>>
>>>>> The security_hook_heads for all the other LSMs (SELinux, AppArmor etc)
>>>>> still remains __lsm_ro_after_init and cannot be modified. We are still
>>>>> working on v2 (not ready for review yet) but the general idea can be
>>>>> seen here:
>>>>>
>>>>>     
>>>>> https://github.com/sinkap/linux-krsi/blob/patch/v1/trampoline_prototype/security/bpf/lsm.c 
>>>>>
>>>>>
>>>>>>
>>>>>> Evaluating the security impact of this is the next step. My 
>>>>>> understanding
>>>>>> is that eBPF via BTF is constrained to read only access to hook
>>>>>> parameters, and that its behavior would be entirely restrictive.
>>>>>>
>>>>>> I'd like to understand the security impact more fully, though.  
>>>>>> Can the
>>>>>> eBPF code make arbitrary writes to the kernel, or read anything 
>>>>>> other than
>>>>>> the correctly bounded LSM hook parameters?
>>>>>>
>>>>>
>>>>> As mentioned, the BPF verifier does not allow writes to BTF types.
>>>>>
>>>>>>> And a traditional security module would necessarily fall
>>>>>>> under GPL; is the eBPF code required to be likewise?  If not, 
>>>>>>> KRSI is a
>>>>>>> gateway for proprietary LSMs...
>>>>>>
>>>>>> Right, we do not want this to be a GPL bypass.
>>>>>
>>>>> This is not intended to be a GPL bypass and the BPF verifier checks
>>>>> for license compatibility of the loaded program with GPL.
>>>>
>>>> IIUC, it checks that the program is GPL compatible if it uses a 
>>>> function
>>>> marked GPL-only.  But what specifically is marked GPL-only that is 
>>>> required
>>>> for eBPF programs using KRSI?
>>>
>>> Good point! If no-one objects, I can add it to the BPF_PROG_TYPE_LSM
>>> specific verification for the v2 of the patch-set which would require
>>> all BPF-LSM programs to be GPL.
>>
>> I don't think it's a good idea to enforce license on the program.
>> The kernel doesn't do it for modules.
>> For years all of BPF tracing progs were GPL because they have to use
>> GPL-ed helpers to do anything meaningful.
>> So for KRSI just make sure that all helpers are GPL-ed as well.
> 
> IIUC, the example eBPF code included in this patch series showed a 
> program that used a GPL-only helper for the purpose of reporting event 
> output to userspace. But it could have just as easily omitted the use of 
> that helper and still implemented its own arbitrary access control model 
> on the LSM hooks to which it attached.  It seems like the question is 
> whether the kernel developers are ok with exposing the entire LSM hook 
> interface and all the associated data structures to non-GPLd code, 
> irrespective of what helpers it may or may not use.

Also, to be clear, while kernel modules aren't necessarily GPL, prior to 
this patch series, all Linux security modules were necessarily GPLd in 
order to use the LSM interface.  So allowing non-GPL eBPF-based LSMs 
would be a change.


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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-14 17:42                             ` Stephen Smalley
@ 2020-01-15  2:48                               ` Alexei Starovoitov
  2020-01-15 13:59                                 ` Stephen Smalley
  0 siblings, 1 reply; 74+ messages in thread
From: Alexei Starovoitov @ 2020-01-15  2:48 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: KP Singh, James Morris, Kees Cook, Casey Schaufler, open list,
	bpf, linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On Tue, Jan 14, 2020 at 12:42:22PM -0500, Stephen Smalley wrote:
> On 1/14/20 11:54 AM, Stephen Smalley wrote:
> > On 1/10/20 12:53 PM, Alexei Starovoitov wrote:
> > > On Fri, Jan 10, 2020 at 04:27:58PM +0100, KP Singh wrote:
> > > > On 09-Jan 14:47, Stephen Smalley wrote:
> > > > > On 1/9/20 2:43 PM, KP Singh wrote:
> > > > > > On 10-Jan 06:07, James Morris wrote:
> > > > > > > On Thu, 9 Jan 2020, Stephen Smalley wrote:
> > > > > > > 
> > > > > > > > On 1/9/20 1:11 PM, James Morris wrote:
> > > > > > > > > On Wed, 8 Jan 2020, Stephen Smalley wrote:
> > > > > > > > > 
> > > > > > > > > > The cover letter subject line and the
> > > > > > > > > > Kconfig help text refer to it as a
> > > > > > > > > > BPF-based "MAC and Audit policy".  It
> > > > > > > > > > has an enforce config option that
> > > > > > > > > > enables the bpf programs to deny access,
> > > > > > > > > > providing access control. IIRC,
> > > > > > > > > > in
> > > > > > > > > > the earlier discussion threads, the BPF
> > > > > > > > > > maintainers suggested that Smack
> > > > > > > > > > and
> > > > > > > > > > other LSMs could be entirely
> > > > > > > > > > re-implemented via it in the future, and
> > > > > > > > > > that
> > > > > > > > > > such an implementation would be more optimal.
> > > > > > > > > 
> > > > > > > > > In this case, the eBPF code is similar to a
> > > > > > > > > kernel module, rather than a
> > > > > > > > > loadable policy file.  It's a loadable
> > > > > > > > > mechanism, rather than a policy, in
> > > > > > > > > my view.
> > > > > > > > 
> > > > > > > > I thought you frowned on dynamically loadable
> > > > > > > > LSMs for both security and
> > > > > > > > correctness reasons?
> > > > > > 
> > > > > > Based on the feedback from the lists we've updated the design for v2.
> > > > > > 
> > > > > > In v2, LSM hook callbacks are allocated dynamically using BPF
> > > > > > trampolines, appended to a separate security_hook_heads and run
> > > > > > only after the statically allocated hooks.
> > > > > > 
> > > > > > The security_hook_heads for all the other LSMs (SELinux, AppArmor etc)
> > > > > > still remains __lsm_ro_after_init and cannot be modified. We are still
> > > > > > working on v2 (not ready for review yet) but the general idea can be
> > > > > > seen here:
> > > > > > 
> > > > > >      https://github.com/sinkap/linux-krsi/blob/patch/v1/trampoline_prototype/security/bpf/lsm.c
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > Evaluating the security impact of this is the next
> > > > > > > step. My understanding
> > > > > > > is that eBPF via BTF is constrained to read only access to hook
> > > > > > > parameters, and that its behavior would be entirely restrictive.
> > > > > > > 
> > > > > > > I'd like to understand the security impact more
> > > > > > > fully, though.  Can the
> > > > > > > eBPF code make arbitrary writes to the kernel, or
> > > > > > > read anything other than
> > > > > > > the correctly bounded LSM hook parameters?
> > > > > > > 
> > > > > > 
> > > > > > As mentioned, the BPF verifier does not allow writes to BTF types.
> > > > > > 
> > > > > > > > And a traditional security module would necessarily fall
> > > > > > > > under GPL; is the eBPF code required to be
> > > > > > > > likewise?  If not, KRSI is a
> > > > > > > > gateway for proprietary LSMs...
> > > > > > > 
> > > > > > > Right, we do not want this to be a GPL bypass.
> > > > > > 
> > > > > > This is not intended to be a GPL bypass and the BPF verifier checks
> > > > > > for license compatibility of the loaded program with GPL.
> > > > > 
> > > > > IIUC, it checks that the program is GPL compatible if it
> > > > > uses a function
> > > > > marked GPL-only.  But what specifically is marked GPL-only
> > > > > that is required
> > > > > for eBPF programs using KRSI?
> > > > 
> > > > Good point! If no-one objects, I can add it to the BPF_PROG_TYPE_LSM
> > > > specific verification for the v2 of the patch-set which would require
> > > > all BPF-LSM programs to be GPL.
> > > 
> > > I don't think it's a good idea to enforce license on the program.
> > > The kernel doesn't do it for modules.
> > > For years all of BPF tracing progs were GPL because they have to use
> > > GPL-ed helpers to do anything meaningful.
> > > So for KRSI just make sure that all helpers are GPL-ed as well.
> > 
> > IIUC, the example eBPF code included in this patch series showed a
> > program that used a GPL-only helper for the purpose of reporting event
> > output to userspace. But it could have just as easily omitted the use of
> > that helper and still implemented its own arbitrary access control model
> > on the LSM hooks to which it attached.  It seems like the question is
> > whether the kernel developers are ok with exposing the entire LSM hook
> > interface and all the associated data structures to non-GPLd code,
> > irrespective of what helpers it may or may not use.
> 
> Also, to be clear, while kernel modules aren't necessarily GPL, prior to
> this patch series, all Linux security modules were necessarily GPLd in order
> to use the LSM interface. 

Because they use securityfs_create_file() GPL-ed api, right?
but not because module license is enforced.

> So allowing non-GPL eBPF-based LSMs would be a
> change.

I don't see it this way. seccomp progs technically unlicensed. Yet they can
disallow any syscall. Primitive KRSI progs like
int bpf-prog(void*) { return REJECT; }
would be able to do selectively disable a syscall with an overhead acceptable
in production systems (unlike seccomp). I want this use case to be available to
people. It's a bait, because to do real progs people would need to GPL them.
Key helpers bpf_perf_event_output, bpf_ktime_get_ns, bpf_trace_printk are all
GPL-ed. It may look that most networking helpers are not-GPL, but real life is
different. To debug programs bpf_trace_printk() is necessary. To have
communication with user space bpf_perf_event_output() is necssary. To measure
anything or implement timestamps bpf_ktime_get_ns() is necessary. So today all
meaninful bpf programs are GPL. Those that are not GPL probably exist, but
they're toy programs. Hence I have zero concerns about GPL bypass coming from
tracing, networking, and, in the future, KRSI progs too.

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-15  2:48                               ` Alexei Starovoitov
@ 2020-01-15 13:59                                 ` Stephen Smalley
  2020-01-15 14:09                                   ` Greg Kroah-Hartman
  0 siblings, 1 reply; 74+ messages in thread
From: Stephen Smalley @ 2020-01-15 13:59 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: KP Singh, James Morris, Kees Cook, Casey Schaufler, open list,
	bpf, linux-security-module, Alexei Starovoitov, Daniel Borkmann,
	Thomas Garnier, Michael Halcrow, Paul Turner, Brendan Gregg,
	Jann Horn, Matthew Garrett, Christian Brauner,
	Mickaël Salaün, Florent Revest, Brendan Jackman,
	Martin KaFai Lau, Song Liu, Yonghong Song, Serge E. Hallyn,
	Mauro Carvalho Chehab, David S. Miller, Greg Kroah-Hartman,
	Nicolas Ferre, Stanislav Fomichev, Quentin Monnet,
	Andrey Ignatov, Joe Stringer, Paul Moore

On 1/14/20 9:48 PM, Alexei Starovoitov wrote:
> On Tue, Jan 14, 2020 at 12:42:22PM -0500, Stephen Smalley wrote:
>> On 1/14/20 11:54 AM, Stephen Smalley wrote:
>>> On 1/10/20 12:53 PM, Alexei Starovoitov wrote:
>>>> On Fri, Jan 10, 2020 at 04:27:58PM +0100, KP Singh wrote:
>>>>> On 09-Jan 14:47, Stephen Smalley wrote:
>>>>>> On 1/9/20 2:43 PM, KP Singh wrote:
>>>>>>> On 10-Jan 06:07, James Morris wrote:
>>>>>>>> On Thu, 9 Jan 2020, Stephen Smalley wrote:
>>>>>>>>
>>>>>>>>> On 1/9/20 1:11 PM, James Morris wrote:
>>>>>>>>>> On Wed, 8 Jan 2020, Stephen Smalley wrote:
>>>>>>>>>>
>>>>>>>>>>> The cover letter subject line and the
>>>>>>>>>>> Kconfig help text refer to it as a
>>>>>>>>>>> BPF-based "MAC and Audit policy".  It
>>>>>>>>>>> has an enforce config option that
>>>>>>>>>>> enables the bpf programs to deny access,
>>>>>>>>>>> providing access control. IIRC,
>>>>>>>>>>> in
>>>>>>>>>>> the earlier discussion threads, the BPF
>>>>>>>>>>> maintainers suggested that Smack
>>>>>>>>>>> and
>>>>>>>>>>> other LSMs could be entirely
>>>>>>>>>>> re-implemented via it in the future, and
>>>>>>>>>>> that
>>>>>>>>>>> such an implementation would be more optimal.
>>>>>>>>>>
>>>>>>>>>> In this case, the eBPF code is similar to a
>>>>>>>>>> kernel module, rather than a
>>>>>>>>>> loadable policy file.  It's a loadable
>>>>>>>>>> mechanism, rather than a policy, in
>>>>>>>>>> my view.
>>>>>>>>>
>>>>>>>>> I thought you frowned on dynamically loadable
>>>>>>>>> LSMs for both security and
>>>>>>>>> correctness reasons?
>>>>>>>
>>>>>>> Based on the feedback from the lists we've updated the design for v2.
>>>>>>>
>>>>>>> In v2, LSM hook callbacks are allocated dynamically using BPF
>>>>>>> trampolines, appended to a separate security_hook_heads and run
>>>>>>> only after the statically allocated hooks.
>>>>>>>
>>>>>>> The security_hook_heads for all the other LSMs (SELinux, AppArmor etc)
>>>>>>> still remains __lsm_ro_after_init and cannot be modified. We are still
>>>>>>> working on v2 (not ready for review yet) but the general idea can be
>>>>>>> seen here:
>>>>>>>
>>>>>>>       https://github.com/sinkap/linux-krsi/blob/patch/v1/trampoline_prototype/security/bpf/lsm.c
>>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> Evaluating the security impact of this is the next
>>>>>>>> step. My understanding
>>>>>>>> is that eBPF via BTF is constrained to read only access to hook
>>>>>>>> parameters, and that its behavior would be entirely restrictive.
>>>>>>>>
>>>>>>>> I'd like to understand the security impact more
>>>>>>>> fully, though.  Can the
>>>>>>>> eBPF code make arbitrary writes to the kernel, or
>>>>>>>> read anything other than
>>>>>>>> the correctly bounded LSM hook parameters?
>>>>>>>>
>>>>>>>
>>>>>>> As mentioned, the BPF verifier does not allow writes to BTF types.
>>>>>>>
>>>>>>>>> And a traditional security module would necessarily fall
>>>>>>>>> under GPL; is the eBPF code required to be
>>>>>>>>> likewise?  If not, KRSI is a
>>>>>>>>> gateway for proprietary LSMs...
>>>>>>>>
>>>>>>>> Right, we do not want this to be a GPL bypass.
>>>>>>>
>>>>>>> This is not intended to be a GPL bypass and the BPF verifier checks
>>>>>>> for license compatibility of the loaded program with GPL.
>>>>>>
>>>>>> IIUC, it checks that the program is GPL compatible if it
>>>>>> uses a function
>>>>>> marked GPL-only.  But what specifically is marked GPL-only
>>>>>> that is required
>>>>>> for eBPF programs using KRSI?
>>>>>
>>>>> Good point! If no-one objects, I can add it to the BPF_PROG_TYPE_LSM
>>>>> specific verification for the v2 of the patch-set which would require
>>>>> all BPF-LSM programs to be GPL.
>>>>
>>>> I don't think it's a good idea to enforce license on the program.
>>>> The kernel doesn't do it for modules.
>>>> For years all of BPF tracing progs were GPL because they have to use
>>>> GPL-ed helpers to do anything meaningful.
>>>> So for KRSI just make sure that all helpers are GPL-ed as well.
>>>
>>> IIUC, the example eBPF code included in this patch series showed a
>>> program that used a GPL-only helper for the purpose of reporting event
>>> output to userspace. But it could have just as easily omitted the use of
>>> that helper and still implemented its own arbitrary access control model
>>> on the LSM hooks to which it attached.  It seems like the question is
>>> whether the kernel developers are ok with exposing the entire LSM hook
>>> interface and all the associated data structures to non-GPLd code,
>>> irrespective of what helpers it may or may not use.
>>
>> Also, to be clear, while kernel modules aren't necessarily GPL, prior to
>> this patch series, all Linux security modules were necessarily GPLd in order
>> to use the LSM interface.
> 
> Because they use securityfs_create_file() GPL-ed api, right?
> but not because module license is enforced.

No, securityfs was a later addition and is not required by all LSMs 
either.  Originally LSMs had to register their hooks via 
register_security(), which was intentionally EXPORT_SYMBOL_GPL() to 
avoid exposing the LSM interface to non-GPLd modules because there were 
significant concerns with doing so when LSM was first merged.  Then in 
20510f2f4e2dabb0ff6c13901807627ec9452f98 ("security: Convert LSM into a 
static interface"), the ability for loadable modules to use 
register_security() at all was removed, limiting its use to built-in 
modules.  In commit b1d9e6b0646d0e5ee5d9050bd236b6c65d66faef ("LSM: 
Switch to lists of hooks"), register_security() was replaced by 
security_add_hooks(), but this was likewise not exported for use by 
modules and could only be used by built-in code.  The bpf LSM is 
providing a shim that allows eBPF code to attach to these hooks that 
would otherwise not be exposed to non-GPLd code, so if the bpf LSM does 
not require the eBPF programs to also be GPLd, then that is a change 
from current practice.

>> So allowing non-GPL eBPF-based LSMs would be a
>> change.
> 
> I don't see it this way. seccomp progs technically unlicensed. Yet they can
> disallow any syscall. Primitive KRSI progs like
> int bpf-prog(void*) { return REJECT; }
> would be able to do selectively disable a syscall with an overhead acceptable
> in production systems (unlike seccomp). I want this use case to be available to
> people. It's a bait, because to do real progs people would need to GPL them.
> Key helpers bpf_perf_event_output, bpf_ktime_get_ns, bpf_trace_printk are all
> GPL-ed. It may look that most networking helpers are not-GPL, but real life is
> different. To debug programs bpf_trace_printk() is necessary. To have
> communication with user space bpf_perf_event_output() is necssary. To measure
> anything or implement timestamps bpf_ktime_get_ns() is necessary. So today all
> meaninful bpf programs are GPL. Those that are not GPL probably exist, but
> they're toy programs. Hence I have zero concerns about GPL bypass coming from
> tracing, networking, and, in the future, KRSI progs too.

You have more confidence than I do about that.  I would anticipate 
developers of out-of-tree LSMs latching onto this bpf LSM and using it 
to avoid GPL.  I don't see that any of those helpers are truly needed to 
implement an access control model.

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-15 13:59                                 ` Stephen Smalley
@ 2020-01-15 14:09                                   ` Greg Kroah-Hartman
  2020-01-15 22:23                                     ` Alexei Starovoitov
  0 siblings, 1 reply; 74+ messages in thread
From: Greg Kroah-Hartman @ 2020-01-15 14:09 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Alexei Starovoitov, KP Singh, James Morris, Kees Cook,
	Casey Schaufler, open list, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer, Paul Moore

On Wed, Jan 15, 2020 at 08:59:08AM -0500, Stephen Smalley wrote:
> On 1/14/20 9:48 PM, Alexei Starovoitov wrote:
> > On Tue, Jan 14, 2020 at 12:42:22PM -0500, Stephen Smalley wrote:
> > > On 1/14/20 11:54 AM, Stephen Smalley wrote:
> > > > On 1/10/20 12:53 PM, Alexei Starovoitov wrote:
> > > > > On Fri, Jan 10, 2020 at 04:27:58PM +0100, KP Singh wrote:
> > > > > > On 09-Jan 14:47, Stephen Smalley wrote:
> > > > > > > On 1/9/20 2:43 PM, KP Singh wrote:
> > > > > > > > On 10-Jan 06:07, James Morris wrote:
> > > > > > > > > On Thu, 9 Jan 2020, Stephen Smalley wrote:
> > > > > > > > > 
> > > > > > > > > > On 1/9/20 1:11 PM, James Morris wrote:
> > > > > > > > > > > On Wed, 8 Jan 2020, Stephen Smalley wrote:
> > > > > > > > > > > 
> > > > > > > > > > > > The cover letter subject line and the
> > > > > > > > > > > > Kconfig help text refer to it as a
> > > > > > > > > > > > BPF-based "MAC and Audit policy".  It
> > > > > > > > > > > > has an enforce config option that
> > > > > > > > > > > > enables the bpf programs to deny access,
> > > > > > > > > > > > providing access control. IIRC,
> > > > > > > > > > > > in
> > > > > > > > > > > > the earlier discussion threads, the BPF
> > > > > > > > > > > > maintainers suggested that Smack
> > > > > > > > > > > > and
> > > > > > > > > > > > other LSMs could be entirely
> > > > > > > > > > > > re-implemented via it in the future, and
> > > > > > > > > > > > that
> > > > > > > > > > > > such an implementation would be more optimal.
> > > > > > > > > > > 
> > > > > > > > > > > In this case, the eBPF code is similar to a
> > > > > > > > > > > kernel module, rather than a
> > > > > > > > > > > loadable policy file.  It's a loadable
> > > > > > > > > > > mechanism, rather than a policy, in
> > > > > > > > > > > my view.
> > > > > > > > > > 
> > > > > > > > > > I thought you frowned on dynamically loadable
> > > > > > > > > > LSMs for both security and
> > > > > > > > > > correctness reasons?
> > > > > > > > 
> > > > > > > > Based on the feedback from the lists we've updated the design for v2.
> > > > > > > > 
> > > > > > > > In v2, LSM hook callbacks are allocated dynamically using BPF
> > > > > > > > trampolines, appended to a separate security_hook_heads and run
> > > > > > > > only after the statically allocated hooks.
> > > > > > > > 
> > > > > > > > The security_hook_heads for all the other LSMs (SELinux, AppArmor etc)
> > > > > > > > still remains __lsm_ro_after_init and cannot be modified. We are still
> > > > > > > > working on v2 (not ready for review yet) but the general idea can be
> > > > > > > > seen here:
> > > > > > > > 
> > > > > > > >       https://github.com/sinkap/linux-krsi/blob/patch/v1/trampoline_prototype/security/bpf/lsm.c
> > > > > > > > 
> > > > > > > > 
> > > > > > > > > 
> > > > > > > > > Evaluating the security impact of this is the next
> > > > > > > > > step. My understanding
> > > > > > > > > is that eBPF via BTF is constrained to read only access to hook
> > > > > > > > > parameters, and that its behavior would be entirely restrictive.
> > > > > > > > > 
> > > > > > > > > I'd like to understand the security impact more
> > > > > > > > > fully, though.  Can the
> > > > > > > > > eBPF code make arbitrary writes to the kernel, or
> > > > > > > > > read anything other than
> > > > > > > > > the correctly bounded LSM hook parameters?
> > > > > > > > > 
> > > > > > > > 
> > > > > > > > As mentioned, the BPF verifier does not allow writes to BTF types.
> > > > > > > > 
> > > > > > > > > > And a traditional security module would necessarily fall
> > > > > > > > > > under GPL; is the eBPF code required to be
> > > > > > > > > > likewise?  If not, KRSI is a
> > > > > > > > > > gateway for proprietary LSMs...
> > > > > > > > > 
> > > > > > > > > Right, we do not want this to be a GPL bypass.
> > > > > > > > 
> > > > > > > > This is not intended to be a GPL bypass and the BPF verifier checks
> > > > > > > > for license compatibility of the loaded program with GPL.
> > > > > > > 
> > > > > > > IIUC, it checks that the program is GPL compatible if it
> > > > > > > uses a function
> > > > > > > marked GPL-only.  But what specifically is marked GPL-only
> > > > > > > that is required
> > > > > > > for eBPF programs using KRSI?
> > > > > > 
> > > > > > Good point! If no-one objects, I can add it to the BPF_PROG_TYPE_LSM
> > > > > > specific verification for the v2 of the patch-set which would require
> > > > > > all BPF-LSM programs to be GPL.
> > > > > 
> > > > > I don't think it's a good idea to enforce license on the program.
> > > > > The kernel doesn't do it for modules.
> > > > > For years all of BPF tracing progs were GPL because they have to use
> > > > > GPL-ed helpers to do anything meaningful.
> > > > > So for KRSI just make sure that all helpers are GPL-ed as well.
> > > > 
> > > > IIUC, the example eBPF code included in this patch series showed a
> > > > program that used a GPL-only helper for the purpose of reporting event
> > > > output to userspace. But it could have just as easily omitted the use of
> > > > that helper and still implemented its own arbitrary access control model
> > > > on the LSM hooks to which it attached.  It seems like the question is
> > > > whether the kernel developers are ok with exposing the entire LSM hook
> > > > interface and all the associated data structures to non-GPLd code,
> > > > irrespective of what helpers it may or may not use.
> > > 
> > > Also, to be clear, while kernel modules aren't necessarily GPL, prior to
> > > this patch series, all Linux security modules were necessarily GPLd in order
> > > to use the LSM interface.
> > 
> > Because they use securityfs_create_file() GPL-ed api, right?
> > but not because module license is enforced.
> 
> No, securityfs was a later addition and is not required by all LSMs either.
> Originally LSMs had to register their hooks via register_security(), which
> was intentionally EXPORT_SYMBOL_GPL() to avoid exposing the LSM interface to
> non-GPLd modules because there were significant concerns with doing so when
> LSM was first merged.  Then in 20510f2f4e2dabb0ff6c13901807627ec9452f98
> ("security: Convert LSM into a static interface"), the ability for loadable
> modules to use register_security() at all was removed, limiting its use to
> built-in modules.  In commit b1d9e6b0646d0e5ee5d9050bd236b6c65d66faef ("LSM:
> Switch to lists of hooks"), register_security() was replaced by
> security_add_hooks(), but this was likewise not exported for use by modules
> and could only be used by built-in code.  The bpf LSM is providing a shim
> that allows eBPF code to attach to these hooks that would otherwise not be
> exposed to non-GPLd code, so if the bpf LSM does not require the eBPF
> programs to also be GPLd, then that is a change from current practice.
> 
> > > So allowing non-GPL eBPF-based LSMs would be a
> > > change.
> > 
> > I don't see it this way. seccomp progs technically unlicensed. Yet they can
> > disallow any syscall. Primitive KRSI progs like
> > int bpf-prog(void*) { return REJECT; }
> > would be able to do selectively disable a syscall with an overhead acceptable
> > in production systems (unlike seccomp). I want this use case to be available to
> > people. It's a bait, because to do real progs people would need to GPL them.
> > Key helpers bpf_perf_event_output, bpf_ktime_get_ns, bpf_trace_printk are all
> > GPL-ed. It may look that most networking helpers are not-GPL, but real life is
> > different. To debug programs bpf_trace_printk() is necessary. To have
> > communication with user space bpf_perf_event_output() is necssary. To measure
> > anything or implement timestamps bpf_ktime_get_ns() is necessary. So today all
> > meaninful bpf programs are GPL. Those that are not GPL probably exist, but
> > they're toy programs. Hence I have zero concerns about GPL bypass coming from
> > tracing, networking, and, in the future, KRSI progs too.
> 
> You have more confidence than I do about that.  I would anticipate
> developers of out-of-tree LSMs latching onto this bpf LSM and using it to
> avoid GPL.  I don't see that any of those helpers are truly needed to
> implement an access control model.

Yeah, I'm with Stephen here, this should be explicitly marked for
GPL-only bpf code to prevent anyone from trying to route around the LSM
apis we have today.  We have enough problem with companies trying to do
that as-is, let's not give them any other ways to abuse our license.

thanks,

greg k-h

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

* Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)
  2020-01-15 14:09                                   ` Greg Kroah-Hartman
@ 2020-01-15 22:23                                     ` Alexei Starovoitov
  0 siblings, 0 replies; 74+ messages in thread
From: Alexei Starovoitov @ 2020-01-15 22:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Stephen Smalley, KP Singh, James Morris, Kees Cook,
	Casey Schaufler, open list, bpf, linux-security-module,
	Alexei Starovoitov, Daniel Borkmann, Thomas Garnier,
	Michael Halcrow, Paul Turner, Brendan Gregg, Jann Horn,
	Matthew Garrett, Christian Brauner, Mickaël Salaün,
	Florent Revest, Brendan Jackman, Martin KaFai Lau, Song Liu,
	Yonghong Song, Serge E. Hallyn, Mauro Carvalho Chehab,
	David S. Miller, Nicolas Ferre, Stanislav Fomichev,
	Quentin Monnet, Andrey Ignatov, Joe Stringer, Paul Moore

On Wed, Jan 15, 2020 at 03:09:53PM +0100, Greg Kroah-Hartman wrote:
> On Wed, Jan 15, 2020 at 08:59:08AM -0500, Stephen Smalley wrote:
> > On 1/14/20 9:48 PM, Alexei Starovoitov wrote:
> > > On Tue, Jan 14, 2020 at 12:42:22PM -0500, Stephen Smalley wrote:
> > > > On 1/14/20 11:54 AM, Stephen Smalley wrote:
> > > > > On 1/10/20 12:53 PM, Alexei Starovoitov wrote:
> > > > > > On Fri, Jan 10, 2020 at 04:27:58PM +0100, KP Singh wrote:
> > > > > > > On 09-Jan 14:47, Stephen Smalley wrote:
> > > > > > > > On 1/9/20 2:43 PM, KP Singh wrote:
> > > > > > > > > On 10-Jan 06:07, James Morris wrote:
> > > > > > > > > > On Thu, 9 Jan 2020, Stephen Smalley wrote:
> > > > > > > > > > 
> > > > > > > > > > > On 1/9/20 1:11 PM, James Morris wrote:
> > > > > > > > > > > > On Wed, 8 Jan 2020, Stephen Smalley wrote:
> > > > > > > > > > > > 
> > > > > > > > > > > > > The cover letter subject line and the
> > > > > > > > > > > > > Kconfig help text refer to it as a
> > > > > > > > > > > > > BPF-based "MAC and Audit policy".  It
> > > > > > > > > > > > > has an enforce config option that
> > > > > > > > > > > > > enables the bpf programs to deny access,
> > > > > > > > > > > > > providing access control. IIRC,
> > > > > > > > > > > > > in
> > > > > > > > > > > > > the earlier discussion threads, the BPF
> > > > > > > > > > > > > maintainers suggested that Smack
> > > > > > > > > > > > > and
> > > > > > > > > > > > > other LSMs could be entirely
> > > > > > > > > > > > > re-implemented via it in the future, and
> > > > > > > > > > > > > that
> > > > > > > > > > > > > such an implementation would be more optimal.
> > > > > > > > > > > > 
> > > > > > > > > > > > In this case, the eBPF code is similar to a
> > > > > > > > > > > > kernel module, rather than a
> > > > > > > > > > > > loadable policy file.  It's a loadable
> > > > > > > > > > > > mechanism, rather than a policy, in
> > > > > > > > > > > > my view.
> > > > > > > > > > > 
> > > > > > > > > > > I thought you frowned on dynamically loadable
> > > > > > > > > > > LSMs for both security and
> > > > > > > > > > > correctness reasons?
> > > > > > > > > 
> > > > > > > > > Based on the feedback from the lists we've updated the design for v2.
> > > > > > > > > 
> > > > > > > > > In v2, LSM hook callbacks are allocated dynamically using BPF
> > > > > > > > > trampolines, appended to a separate security_hook_heads and run
> > > > > > > > > only after the statically allocated hooks.
> > > > > > > > > 
> > > > > > > > > The security_hook_heads for all the other LSMs (SELinux, AppArmor etc)
> > > > > > > > > still remains __lsm_ro_after_init and cannot be modified. We are still
> > > > > > > > > working on v2 (not ready for review yet) but the general idea can be
> > > > > > > > > seen here:
> > > > > > > > > 
> > > > > > > > >       https://github.com/sinkap/linux-krsi/blob/patch/v1/trampoline_prototype/security/bpf/lsm.c
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > > Evaluating the security impact of this is the next
> > > > > > > > > > step. My understanding
> > > > > > > > > > is that eBPF via BTF is constrained to read only access to hook
> > > > > > > > > > parameters, and that its behavior would be entirely restrictive.
> > > > > > > > > > 
> > > > > > > > > > I'd like to understand the security impact more
> > > > > > > > > > fully, though.  Can the
> > > > > > > > > > eBPF code make arbitrary writes to the kernel, or
> > > > > > > > > > read anything other than
> > > > > > > > > > the correctly bounded LSM hook parameters?
> > > > > > > > > > 
> > > > > > > > > 
> > > > > > > > > As mentioned, the BPF verifier does not allow writes to BTF types.
> > > > > > > > > 
> > > > > > > > > > > And a traditional security module would necessarily fall
> > > > > > > > > > > under GPL; is the eBPF code required to be
> > > > > > > > > > > likewise?  If not, KRSI is a
> > > > > > > > > > > gateway for proprietary LSMs...
> > > > > > > > > > 
> > > > > > > > > > Right, we do not want this to be a GPL bypass.
> > > > > > > > > 
> > > > > > > > > This is not intended to be a GPL bypass and the BPF verifier checks
> > > > > > > > > for license compatibility of the loaded program with GPL.
> > > > > > > > 
> > > > > > > > IIUC, it checks that the program is GPL compatible if it
> > > > > > > > uses a function
> > > > > > > > marked GPL-only.  But what specifically is marked GPL-only
> > > > > > > > that is required
> > > > > > > > for eBPF programs using KRSI?
> > > > > > > 
> > > > > > > Good point! If no-one objects, I can add it to the BPF_PROG_TYPE_LSM
> > > > > > > specific verification for the v2 of the patch-set which would require
> > > > > > > all BPF-LSM programs to be GPL.
> > > > > > 
> > > > > > I don't think it's a good idea to enforce license on the program.
> > > > > > The kernel doesn't do it for modules.
> > > > > > For years all of BPF tracing progs were GPL because they have to use
> > > > > > GPL-ed helpers to do anything meaningful.
> > > > > > So for KRSI just make sure that all helpers are GPL-ed as well.
> > > > > 
> > > > > IIUC, the example eBPF code included in this patch series showed a
> > > > > program that used a GPL-only helper for the purpose of reporting event
> > > > > output to userspace. But it could have just as easily omitted the use of
> > > > > that helper and still implemented its own arbitrary access control model
> > > > > on the LSM hooks to which it attached.  It seems like the question is
> > > > > whether the kernel developers are ok with exposing the entire LSM hook
> > > > > interface and all the associated data structures to non-GPLd code,
> > > > > irrespective of what helpers it may or may not use.
> > > > 
> > > > Also, to be clear, while kernel modules aren't necessarily GPL, prior to
> > > > this patch series, all Linux security modules were necessarily GPLd in order
> > > > to use the LSM interface.
> > > 
> > > Because they use securityfs_create_file() GPL-ed api, right?
> > > but not because module license is enforced.
> > 
> > No, securityfs was a later addition and is not required by all LSMs either.
> > Originally LSMs had to register their hooks via register_security(), which
> > was intentionally EXPORT_SYMBOL_GPL() to avoid exposing the LSM interface to
> > non-GPLd modules because there were significant concerns with doing so when
> > LSM was first merged.  Then in 20510f2f4e2dabb0ff6c13901807627ec9452f98
> > ("security: Convert LSM into a static interface"), the ability for loadable
> > modules to use register_security() at all was removed, limiting its use to
> > built-in modules.  In commit b1d9e6b0646d0e5ee5d9050bd236b6c65d66faef ("LSM:
> > Switch to lists of hooks"), register_security() was replaced by
> > security_add_hooks(), but this was likewise not exported for use by modules
> > and could only be used by built-in code.  The bpf LSM is providing a shim
> > that allows eBPF code to attach to these hooks that would otherwise not be
> > exposed to non-GPLd code, so if the bpf LSM does not require the eBPF
> > programs to also be GPLd, then that is a change from current practice.
> > 
> > > > So allowing non-GPL eBPF-based LSMs would be a
> > > > change.
> > > 
> > > I don't see it this way. seccomp progs technically unlicensed. Yet they can
> > > disallow any syscall. Primitive KRSI progs like
> > > int bpf-prog(void*) { return REJECT; }
> > > would be able to do selectively disable a syscall with an overhead acceptable
> > > in production systems (unlike seccomp). I want this use case to be available to
> > > people. It's a bait, because to do real progs people would need to GPL them.
> > > Key helpers bpf_perf_event_output, bpf_ktime_get_ns, bpf_trace_printk are all
> > > GPL-ed. It may look that most networking helpers are not-GPL, but real life is
> > > different. To debug programs bpf_trace_printk() is necessary. To have
> > > communication with user space bpf_perf_event_output() is necssary. To measure
> > > anything or implement timestamps bpf_ktime_get_ns() is necessary. So today all
> > > meaninful bpf programs are GPL. Those that are not GPL probably exist, but
> > > they're toy programs. Hence I have zero concerns about GPL bypass coming from
> > > tracing, networking, and, in the future, KRSI progs too.
> > 
> > You have more confidence than I do about that.  I would anticipate
> > developers of out-of-tree LSMs latching onto this bpf LSM and using it to
> > avoid GPL.  I don't see that any of those helpers are truly needed to
> > implement an access control model.
> 
> Yeah, I'm with Stephen here, this should be explicitly marked for
> GPL-only bpf code to prevent anyone from trying to route around the LSM
> apis we have today.  We have enough problem with companies trying to do
> that as-is, let's not give them any other ways to abuse our license.

Fine. Let's do per prog type check. We can undo it later when this early
concerns prove to be overblown.

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

end of thread, back to index

Thread overview: 74+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-20 15:41 [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) KP Singh
2019-12-20 15:41 ` [PATCH bpf-next v1 01/13] bpf: Refactor BPF_EVENT context macros to its own header KP Singh
2019-12-20 20:10   ` Andrii Nakryiko
2019-12-20 20:26     ` KP Singh
2019-12-20 15:41 ` [PATCH bpf-next v1 02/13] bpf: lsm: Add a skeleton and config options KP Singh
2020-01-07 21:13   ` James Morris
2019-12-20 15:41 ` [PATCH bpf-next v1 03/13] bpf: lsm: Introduce types for eBPF based LSM KP Singh
2019-12-20 15:41 ` [PATCH bpf-next v1 04/13] bpf: lsm: Allow btf_id based attachment for LSM hooks KP Singh
2019-12-23 23:54   ` Andrii Nakryiko
2019-12-30 19:22     ` KP Singh
2019-12-20 15:42 ` [PATCH bpf-next v1 05/13] tools/libbpf: Add support in libbpf for BPF_PROG_TYPE_LSM KP Singh
2019-12-24  0:07   ` Andrii Nakryiko
2019-12-24  0:09     ` Andrii Nakryiko
2020-01-03 23:59     ` KP Singh
2019-12-20 15:42 ` [PATCH bpf-next v1 06/13] bpf: lsm: Init Hooks and create files in securityfs KP Singh
2019-12-24  6:28   ` Andrii Nakryiko
2019-12-30 15:37     ` KP Singh
2019-12-30 18:52       ` Andrii Nakryiko
2019-12-30 19:20       ` Kees Cook
2020-01-03 23:53         ` KP Singh
2020-01-07 21:22   ` James Morris
2019-12-20 15:42 ` [PATCH bpf-next v1 07/13] bpf: lsm: Implement attach, detach and execution KP Singh
2019-12-24  5:48   ` Andrii Nakryiko
2020-01-07 21:27   ` James Morris
2019-12-20 15:42 ` [PATCH bpf-next v1 08/13] bpf: lsm: Show attached program names in hook read handler KP Singh
2020-01-07 21:28   ` James Morris
2019-12-20 15:42 ` [PATCH bpf-next v1 09/13] bpf: lsm: Add a helper function bpf_lsm_event_output KP Singh
2019-12-24  6:36   ` Andrii Nakryiko
2019-12-30 15:11     ` KP Singh
2019-12-30 18:56       ` Andrii Nakryiko
2019-12-20 15:42 ` [PATCH bpf-next v1 10/13] bpf: lsm: Handle attachment of the same program KP Singh
2019-12-24  6:38   ` Andrii Nakryiko
2020-01-08 18:21   ` James Morris
2019-12-20 15:42 ` [PATCH bpf-next v1 11/13] tools/libbpf: Add bpf_program__attach_lsm KP Singh
2019-12-24  6:44   ` Andrii Nakryiko
2020-01-08 18:24   ` James Morris
2019-12-20 15:42 ` [PATCH bpf-next v1 12/13] bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM KP Singh
2019-12-24  6:49   ` Andrii Nakryiko
2020-01-04  0:09     ` KP Singh
2020-01-09 17:59       ` Andrii Nakryiko
2020-01-08 18:25   ` James Morris
2019-12-20 15:42 ` [PATCH bpf-next v1 13/13] bpf: lsm: Add Documentation KP Singh
2019-12-20 17:17 ` [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI) Casey Schaufler
2019-12-20 17:38   ` KP Singh
2019-12-30 19:15     ` Kees Cook
2020-01-08 15:25       ` Stephen Smalley
2020-01-08 18:58         ` James Morris
2020-01-08 19:33           ` Stephen Smalley
2020-01-09 18:11             ` James Morris
2020-01-09 18:23               ` Greg Kroah-Hartman
2020-01-09 18:58               ` Stephen Smalley
2020-01-09 19:07                 ` James Morris
2020-01-09 19:43                   ` KP Singh
2020-01-09 19:47                     ` Stephen Smalley
2020-01-10 15:27                       ` KP Singh
2020-01-10 17:48                         ` James Morris
2020-01-10 17:53                         ` Alexei Starovoitov
2020-01-14 16:54                           ` Stephen Smalley
2020-01-14 17:42                             ` Stephen Smalley
2020-01-15  2:48                               ` Alexei Starovoitov
2020-01-15 13:59                                 ` Stephen Smalley
2020-01-15 14:09                                   ` Greg Kroah-Hartman
2020-01-15 22:23                                     ` Alexei Starovoitov
2020-01-09 19:11               ` KP Singh
2020-01-08 18:27       ` James Morris
2019-12-20 22:46 ` Mickaël Salaün
2019-12-30 19:30   ` Kees Cook
2019-12-31 12:11     ` Mickaël Salaün
2019-12-22  1:27 ` Alexei Starovoitov
2019-12-30 14:58   ` KP Singh
2019-12-30 19:14     ` Andrii Nakryiko
2019-12-24  6:51 ` Andrii Nakryiko
2019-12-30 15:04   ` KP Singh
2019-12-30 18:58     ` Andrii Nakryiko

BPF Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/bpf/0 bpf/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 bpf bpf/ https://lore.kernel.org/bpf \
		bpf@vger.kernel.org
	public-inbox-index bpf

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.bpf


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