Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: lsm: Add Documentation

Document how eBPF programs (BPF_PROG_TYPE_LSM) can be loaded and
attached (BPF_LSM_MAC) to the LSM hooks.

Signed-off-by: KP Singh <kpsingh@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Brendan Jackman <jackmanb@google.com>
Reviewed-by: Florent Revest <revest@google.com>
Reviewed-by: Thomas Garnier <thgarnie@google.com>
Reviewed-by: James Morris <jamorris@linux.microsoft.com>
Link: https://lore.kernel.org/bpf/20200329004356.27286-9-kpsingh@chromium.org

authored by

KP Singh and committed by
Daniel Borkmann
4dece7f3 03e54f10

+143
+142
Documentation/bpf/bpf_lsm.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + .. Copyright (C) 2020 Google LLC. 3 + 4 + ================ 5 + LSM BPF Programs 6 + ================ 7 + 8 + These BPF programs allow runtime instrumentation of the LSM hooks by privileged 9 + users to implement system-wide MAC (Mandatory Access Control) and Audit 10 + policies using eBPF. 11 + 12 + Structure 13 + --------- 14 + 15 + The example shows an eBPF program that can be attached to the ``file_mprotect`` 16 + LSM hook: 17 + 18 + .. c:function:: int file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot); 19 + 20 + Other LSM hooks which can be instrumented can be found in 21 + ``include/linux/lsm_hooks.h``. 22 + 23 + eBPF programs that use :doc:`/bpf/btf` do not need to include kernel headers 24 + for accessing information from the attached eBPF program's context. They can 25 + simply declare the structures in the eBPF program and only specify the fields 26 + that need to be accessed. 27 + 28 + .. code-block:: c 29 + 30 + struct mm_struct { 31 + unsigned long start_brk, brk, start_stack; 32 + } __attribute__((preserve_access_index)); 33 + 34 + struct vm_area_struct { 35 + unsigned long start_brk, brk, start_stack; 36 + unsigned long vm_start, vm_end; 37 + struct mm_struct *vm_mm; 38 + } __attribute__((preserve_access_index)); 39 + 40 + 41 + .. note:: The order of the fields is irrelevant. 42 + 43 + This can be further simplified (if one has access to the BTF information at 44 + build time) by generating the ``vmlinux.h`` with: 45 + 46 + .. code-block:: console 47 + 48 + # bpftool btf dump file <path-to-btf-vmlinux> format c > vmlinux.h 49 + 50 + .. note:: ``path-to-btf-vmlinux`` can be ``/sys/kernel/btf/vmlinux`` if the 51 + build environment matches the environment the BPF programs are 52 + deployed in. 53 + 54 + The ``vmlinux.h`` can then simply be included in the BPF programs without 55 + requiring the definition of the types. 56 + 57 + The eBPF programs can be declared using the``BPF_PROG`` 58 + macros defined in `tools/lib/bpf/bpf_tracing.h`_. In this 59 + example: 60 + 61 + * ``"lsm/file_mprotect"`` indicates the LSM hook that the program must 62 + be attached to 63 + * ``mprotect_audit`` is the name of the eBPF program 64 + 65 + .. code-block:: c 66 + 67 + SEC("lsm/file_mprotect") 68 + int BPF_PROG(mprotect_audit, struct vm_area_struct *vma, 69 + unsigned long reqprot, unsigned long prot, int ret) 70 + { 71 + /* ret is the return value from the previous BPF program 72 + * or 0 if it's the first hook. 73 + */ 74 + if (ret != 0) 75 + return ret; 76 + 77 + int is_heap; 78 + 79 + is_heap = (vma->vm_start >= vma->vm_mm->start_brk && 80 + vma->vm_end <= vma->vm_mm->brk); 81 + 82 + /* Return an -EPERM or write information to the perf events buffer 83 + * for auditing 84 + */ 85 + if (is_heap) 86 + return -EPERM; 87 + } 88 + 89 + The ``__attribute__((preserve_access_index))`` is a clang feature that allows 90 + the BPF verifier to update the offsets for the access at runtime using the 91 + :doc:`/bpf/btf` information. Since the BPF verifier is aware of the types, it 92 + also validates all the accesses made to the various types in the eBPF program. 93 + 94 + Loading 95 + ------- 96 + 97 + eBPF programs can be loaded with the :manpage:`bpf(2)` syscall's 98 + ``BPF_PROG_LOAD`` operation: 99 + 100 + .. code-block:: c 101 + 102 + struct bpf_object *obj; 103 + 104 + obj = bpf_object__open("./my_prog.o"); 105 + bpf_object__load(obj); 106 + 107 + This can be simplified by using a skeleton header generated by ``bpftool``: 108 + 109 + .. code-block:: console 110 + 111 + # bpftool gen skeleton my_prog.o > my_prog.skel.h 112 + 113 + and the program can be loaded by including ``my_prog.skel.h`` and using 114 + the generated helper, ``my_prog__open_and_load``. 115 + 116 + Attachment to LSM Hooks 117 + ----------------------- 118 + 119 + The LSM allows attachment of eBPF programs as LSM hooks using :manpage:`bpf(2)` 120 + syscall's ``BPF_RAW_TRACEPOINT_OPEN`` operation or more simply by 121 + using the libbpf helper ``bpf_program__attach_lsm``. 122 + 123 + The program can be detached from the LSM hook by *destroying* the ``link`` 124 + link returned by ``bpf_program__attach_lsm`` using ``bpf_link__destroy``. 125 + 126 + One can also use the helpers generated in ``my_prog.skel.h`` i.e. 127 + ``my_prog__attach`` for attachment and ``my_prog__destroy`` for cleaning up. 128 + 129 + Examples 130 + -------- 131 + 132 + An example eBPF program can be found in 133 + `tools/testing/selftests/bpf/progs/lsm.c`_ and the corresponding 134 + userspace code in `tools/testing/selftests/bpf/prog_tests/test_lsm.c`_ 135 + 136 + .. Links 137 + .. _tools/lib/bpf/bpf_tracing.h: 138 + https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/lib/bpf/bpf_tracing.h 139 + .. _tools/testing/selftests/bpf/progs/lsm.c: 140 + https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm.c 141 + .. _tools/testing/selftests/bpf/prog_tests/test_lsm.c: 142 + https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/prog_tests/test_lsm.c
+1
Documentation/bpf/index.rst
··· 45 45 prog_cgroup_sockopt 46 46 prog_cgroup_sysctl 47 47 prog_flow_dissector 48 + bpf_lsm 48 49 49 50 50 51 Testing and debugging BPF