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