From cbdebca3310183baf2db40f37204c381857f9e46 Mon Sep 17 00:00:00 2001 From: DavadDi Date: Thu, 4 Jan 2024 17:22:46 +0800 Subject: [PATCH] Add the LSM BPF sample code, and enhance the README.md documentation. Signed-off-by: DavadDi --- README.md | 27 +++++++++++++++++++++++ examples/c/.gitignore | 1 + examples/c/Makefile | 2 +- examples/c/lsm.bpf.c | 20 +++++++++++++++++ examples/c/lsm.c | 51 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 examples/c/lsm.bpf.c create mode 100644 examples/c/lsm.c diff --git a/README.md b/README.md index ec4fd307..9d646213 100644 --- a/README.md +++ b/README.md @@ -322,6 +322,33 @@ Task Info. Pid: 1600497. Process Name: tmux: server. Kernel Stack Len: 0. State: Task Info. Pid: 1600498. Process Name: bash. Kernel Stack Len: 5. State: INTERRUPTIBLE ``` +## lsm +`lsm` serves as an illustrative example of utilizing [LSM BPF](https://docs.kernel.org/bpf/prog_lsm.html). In this example, the `bpf()` system call is effectively blocked. Once the `lsm` program is operational, its successful execution can be confirmed by using the `bpftool prog list` command. + +```shell +$ sudo ./lsm +libbpf: loading object 'lsm_bpf' from buffer +... +Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` to see output of the BPF programs. +.......... +``` + +The output from `lsm` in `/sys/kernel/debug/tracing/trace_pipe` is expected to resemble the following: + +````shell +$ sudo cat /sys/kernel/debug/tracing/trace_pipe + bpftool-70646 [002] ...11 279318.416393: bpf_trace_printk: LSM: block bpf() worked + bpftool-70646 [002] ...11 279318.416532: bpf_trace_printk: LSM: block bpf() worked + bpftool-70646 [002] ...11 279318.416533: bpf_trace_printk: LSM: block bpf() worked +```` + +When the `bpf()` system call gets blocked, the `bpftool prog list` command yields the following output: + +```shell +$ sudo bpftool prog list +Error: can't get next program: Operation not permitted +``` + # Building libbpf-bootstrap supports multiple build systems that do the same thing. diff --git a/examples/c/.gitignore b/examples/c/.gitignore index 4948fd35..456deb07 100644 --- a/examples/c/.gitignore +++ b/examples/c/.gitignore @@ -11,5 +11,6 @@ /tc /ksyscall /task_iter +/lsm /cmake-build-debug/ /cmake-build-release/ diff --git a/examples/c/Makefile b/examples/c/Makefile index bb3d704e..cd0a70b9 100644 --- a/examples/c/Makefile +++ b/examples/c/Makefile @@ -24,7 +24,7 @@ INCLUDES := -I$(OUTPUT) -I../../libbpf/include/uapi -I$(dir $(VMLINUX)) -I$(LIBB CFLAGS := -g -Wall ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) -APPS = minimal minimal_legacy bootstrap uprobe kprobe fentry usdt sockfilter tc ksyscall task_iter +APPS = minimal minimal_legacy bootstrap uprobe kprobe fentry usdt sockfilter tc ksyscall task_iter lsm CARGO ?= $(shell which cargo) ifeq ($(strip $(CARGO)),) diff --git a/examples/c/lsm.bpf.c b/examples/c/lsm.bpf.c new file mode 100644 index 00000000..8ebdf683 --- /dev/null +++ b/examples/c/lsm.bpf.c @@ -0,0 +1,20 @@ +#include "vmlinux.h" +#include +#include + +char LICENSE[] SEC("license") = "GPL"; + +#define EPERM 1 + +SEC("lsm/bpf") +int BPF_PROG(lsm_bpf, int cmd, union bpf_attr *attr, unsigned int size, int ret) +{ + /* ret is the return value from the previous BPF program + * or 0 if it's the first hook. + */ + if (ret != 0) + return ret; + + bpf_printk("LSM: block bpf() worked"); + return -EPERM; +} diff --git a/examples/c/lsm.c b/examples/c/lsm.c new file mode 100644 index 00000000..d47b95cd --- /dev/null +++ b/examples/c/lsm.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +/* Copyright (c) 2024 David Di */ +#include +#include +#include +#include +#include "lsm.skel.h" + +/* Notice: Ensure your kernel version is 5.7 or higher, BTF (BPF Type Format) is enabled, + * and the file '/sys/kernel/security/lsm' includes 'bpf'. + */ +static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) +{ + return vfprintf(stderr, format, args); +} + +int main(int argc, char **argv) +{ + struct lsm_bpf *skel; + int err; + + /* Set up libbpf errors and debug info callback */ + libbpf_set_print(libbpf_print_fn); + + /* Open, load, and verify BPF application */ + skel = lsm_bpf__open_and_load(); + if (!skel) { + fprintf(stderr, "Failed to open and load BPF skeleton\n"); + goto cleanup; + } + + /* Attach lsm handler */ + err = lsm_bpf__attach(skel); + if (err) { + fprintf(stderr, "Failed to attach BPF skeleton\n"); + goto cleanup; + } + + printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` " + "to see output of the BPF programs.\n"); + + for (;;) { + /* trigger our BPF program */ + fprintf(stderr, "."); + sleep(1); + } + +cleanup: + lsm_bpf__destroy(skel); + return -err; +}