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

bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM

* Load/attach a BPF program that hooks to file_mprotect (int)
and bprm_committed_creds (void).
* Perform an action that triggers the hook.
* Verify if the audit event was received using the shared global
variables for the process executed.
* Verify if the mprotect returns a -EPERM.

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>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Link: https://lore.kernel.org/bpf/20200329004356.27286-8-kpsingh@chromium.org

authored by

KP Singh and committed by
Daniel Borkmann
03e54f10 1e092a03

+136
+2
tools/testing/selftests/bpf/config
··· 35 35 CONFIG_MPLS_IPTUNNEL=m 36 36 CONFIG_IPV6_SIT=m 37 37 CONFIG_BPF_JIT=y 38 + CONFIG_BPF_LSM=y 39 + CONFIG_SECURITY=y
+86
tools/testing/selftests/bpf/prog_tests/test_lsm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + /* 4 + * Copyright (C) 2020 Google LLC. 5 + */ 6 + 7 + #include <test_progs.h> 8 + #include <sys/mman.h> 9 + #include <sys/wait.h> 10 + #include <unistd.h> 11 + #include <malloc.h> 12 + #include <stdlib.h> 13 + 14 + #include "lsm.skel.h" 15 + 16 + char *CMD_ARGS[] = {"true", NULL}; 17 + 18 + int heap_mprotect(void) 19 + { 20 + void *buf; 21 + long sz; 22 + int ret; 23 + 24 + sz = sysconf(_SC_PAGESIZE); 25 + if (sz < 0) 26 + return sz; 27 + 28 + buf = memalign(sz, 2 * sz); 29 + if (buf == NULL) 30 + return -ENOMEM; 31 + 32 + ret = mprotect(buf, sz, PROT_READ | PROT_WRITE | PROT_EXEC); 33 + free(buf); 34 + return ret; 35 + } 36 + 37 + int exec_cmd(int *monitored_pid) 38 + { 39 + int child_pid, child_status; 40 + 41 + child_pid = fork(); 42 + if (child_pid == 0) { 43 + *monitored_pid = getpid(); 44 + execvp(CMD_ARGS[0], CMD_ARGS); 45 + return -EINVAL; 46 + } else if (child_pid > 0) { 47 + waitpid(child_pid, &child_status, 0); 48 + return child_status; 49 + } 50 + 51 + return -EINVAL; 52 + } 53 + 54 + void test_test_lsm(void) 55 + { 56 + struct lsm *skel = NULL; 57 + int err, duration = 0; 58 + 59 + skel = lsm__open_and_load(); 60 + if (CHECK(!skel, "skel_load", "lsm skeleton failed\n")) 61 + goto close_prog; 62 + 63 + err = lsm__attach(skel); 64 + if (CHECK(err, "attach", "lsm attach failed: %d\n", err)) 65 + goto close_prog; 66 + 67 + err = exec_cmd(&skel->bss->monitored_pid); 68 + if (CHECK(err < 0, "exec_cmd", "err %d errno %d\n", err, errno)) 69 + goto close_prog; 70 + 71 + CHECK(skel->bss->bprm_count != 1, "bprm_count", "bprm_count = %d\n", 72 + skel->bss->bprm_count); 73 + 74 + skel->bss->monitored_pid = getpid(); 75 + 76 + err = heap_mprotect(); 77 + if (CHECK(errno != EPERM, "heap_mprotect", "want errno=EPERM, got %d\n", 78 + errno)) 79 + goto close_prog; 80 + 81 + CHECK(skel->bss->mprotect_count != 1, "mprotect_count", 82 + "mprotect_count = %d\n", skel->bss->mprotect_count); 83 + 84 + close_prog: 85 + lsm__destroy(skel); 86 + }
+48
tools/testing/selftests/bpf/progs/lsm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + /* 4 + * Copyright 2020 Google LLC. 5 + */ 6 + 7 + #include "vmlinux.h" 8 + #include <bpf/bpf_helpers.h> 9 + #include <bpf/bpf_tracing.h> 10 + #include <errno.h> 11 + 12 + char _license[] SEC("license") = "GPL"; 13 + 14 + int monitored_pid = 0; 15 + int mprotect_count = 0; 16 + int bprm_count = 0; 17 + 18 + SEC("lsm/file_mprotect") 19 + int BPF_PROG(test_int_hook, struct vm_area_struct *vma, 20 + unsigned long reqprot, unsigned long prot, int ret) 21 + { 22 + if (ret != 0) 23 + return ret; 24 + 25 + __u32 pid = bpf_get_current_pid_tgid() >> 32; 26 + int is_heap = 0; 27 + 28 + is_heap = (vma->vm_start >= vma->vm_mm->start_brk && 29 + vma->vm_end <= vma->vm_mm->brk); 30 + 31 + if (is_heap && monitored_pid == pid) { 32 + mprotect_count++; 33 + ret = -EPERM; 34 + } 35 + 36 + return ret; 37 + } 38 + 39 + SEC("lsm/bprm_committed_creds") 40 + int BPF_PROG(test_void_hook, struct linux_binprm *bprm) 41 + { 42 + __u32 pid = bpf_get_current_pid_tgid() >> 32; 43 + 44 + if (monitored_pid == pid) 45 + bprm_count++; 46 + 47 + return 0; 48 + }