Message ID | 20191220154208.15895-1-kpsingh@chromium.org (mailing list archive) |
---|---|
Headers | show |
Series | MAC and Audit policy using eBPF (KRSI) | expand |
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 >
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 > > >
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 >
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.
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 > [...]
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
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 > > > > [...]
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 > > > > > > > [...]
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 >
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
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...
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
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...
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.
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.
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...
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?
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
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? >
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).
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> >
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> >
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> >>
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> > > > >
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.
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.
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.
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.
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.
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.
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
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.
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