0001 .. SPDX-License-Identifier: GPL-2.0+
0002 .. Copyright (C) 2020 Google LLC.
0003
0004 ================
0005 LSM BPF Programs
0006 ================
0007
0008 These BPF programs allow runtime instrumentation of the LSM hooks by privileged
0009 users to implement system-wide MAC (Mandatory Access Control) and Audit
0010 policies using eBPF.
0011
0012 Structure
0013 ---------
0014
0015 The example shows an eBPF program that can be attached to the ``file_mprotect``
0016 LSM hook:
0017
0018 .. c:function:: int file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot);
0019
0020 Other LSM hooks which can be instrumented can be found in
0021 ``include/linux/lsm_hooks.h``.
0022
0023 eBPF programs that use Documentation/bpf/btf.rst do not need to include kernel
0024 headers for accessing information from the attached eBPF program's context.
0025 They can simply declare the structures in the eBPF program and only specify
0026 the fields that need to be accessed.
0027
0028 .. code-block:: c
0029
0030 struct mm_struct {
0031 unsigned long start_brk, brk, start_stack;
0032 } __attribute__((preserve_access_index));
0033
0034 struct vm_area_struct {
0035 unsigned long start_brk, brk, start_stack;
0036 unsigned long vm_start, vm_end;
0037 struct mm_struct *vm_mm;
0038 } __attribute__((preserve_access_index));
0039
0040
0041 .. note:: The order of the fields is irrelevant.
0042
0043 This can be further simplified (if one has access to the BTF information at
0044 build time) by generating the ``vmlinux.h`` with:
0045
0046 .. code-block:: console
0047
0048 # bpftool btf dump file <path-to-btf-vmlinux> format c > vmlinux.h
0049
0050 .. note:: ``path-to-btf-vmlinux`` can be ``/sys/kernel/btf/vmlinux`` if the
0051 build environment matches the environment the BPF programs are
0052 deployed in.
0053
0054 The ``vmlinux.h`` can then simply be included in the BPF programs without
0055 requiring the definition of the types.
0056
0057 The eBPF programs can be declared using the``BPF_PROG``
0058 macros defined in `tools/lib/bpf/bpf_tracing.h`_. In this
0059 example:
0060
0061 * ``"lsm/file_mprotect"`` indicates the LSM hook that the program must
0062 be attached to
0063 * ``mprotect_audit`` is the name of the eBPF program
0064
0065 .. code-block:: c
0066
0067 SEC("lsm/file_mprotect")
0068 int BPF_PROG(mprotect_audit, struct vm_area_struct *vma,
0069 unsigned long reqprot, unsigned long prot, int ret)
0070 {
0071 /* ret is the return value from the previous BPF program
0072 * or 0 if it's the first hook.
0073 */
0074 if (ret != 0)
0075 return ret;
0076
0077 int is_heap;
0078
0079 is_heap = (vma->vm_start >= vma->vm_mm->start_brk &&
0080 vma->vm_end <= vma->vm_mm->brk);
0081
0082 /* Return an -EPERM or write information to the perf events buffer
0083 * for auditing
0084 */
0085 if (is_heap)
0086 return -EPERM;
0087 }
0088
0089 The ``__attribute__((preserve_access_index))`` is a clang feature that allows
0090 the BPF verifier to update the offsets for the access at runtime using the
0091 Documentation/bpf/btf.rst information. Since the BPF verifier is aware of the
0092 types, it also validates all the accesses made to the various types in the
0093 eBPF program.
0094
0095 Loading
0096 -------
0097
0098 eBPF programs can be loaded with the :manpage:`bpf(2)` syscall's
0099 ``BPF_PROG_LOAD`` operation:
0100
0101 .. code-block:: c
0102
0103 struct bpf_object *obj;
0104
0105 obj = bpf_object__open("./my_prog.o");
0106 bpf_object__load(obj);
0107
0108 This can be simplified by using a skeleton header generated by ``bpftool``:
0109
0110 .. code-block:: console
0111
0112 # bpftool gen skeleton my_prog.o > my_prog.skel.h
0113
0114 and the program can be loaded by including ``my_prog.skel.h`` and using
0115 the generated helper, ``my_prog__open_and_load``.
0116
0117 Attachment to LSM Hooks
0118 -----------------------
0119
0120 The LSM allows attachment of eBPF programs as LSM hooks using :manpage:`bpf(2)`
0121 syscall's ``BPF_RAW_TRACEPOINT_OPEN`` operation or more simply by
0122 using the libbpf helper ``bpf_program__attach_lsm``.
0123
0124 The program can be detached from the LSM hook by *destroying* the ``link``
0125 link returned by ``bpf_program__attach_lsm`` using ``bpf_link__destroy``.
0126
0127 One can also use the helpers generated in ``my_prog.skel.h`` i.e.
0128 ``my_prog__attach`` for attachment and ``my_prog__destroy`` for cleaning up.
0129
0130 Examples
0131 --------
0132
0133 An example eBPF program can be found in
0134 `tools/testing/selftests/bpf/progs/lsm.c`_ and the corresponding
0135 userspace code in `tools/testing/selftests/bpf/prog_tests/test_lsm.c`_
0136
0137 .. Links
0138 .. _tools/lib/bpf/bpf_tracing.h:
0139 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/lib/bpf/bpf_tracing.h
0140 .. _tools/testing/selftests/bpf/progs/lsm.c:
0141 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/lsm.c
0142 .. _tools/testing/selftests/bpf/prog_tests/test_lsm.c:
0143 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/prog_tests/test_lsm.c