Back to home page

OSCL-LXR

 
 

    


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