[PATCH RFC bpf-next 4/4] selftests/bpf: Add lsm_audit_kfuncs tests

Frederick Lawler
2026-03-11T21:31:32Z

Add selftests for the audit kfunc BPF LSM functionality including
both the test program and BPF progs.

Assisted-by: Claude:claude-4.5-opus
Signed-off-by: Frederick Lawler <fred@cloudflare.com>
---
.../selftests/bpf/prog_tests/lsm_audit_kfuncs.c | 598 +++++++++++++++++++++
.../selftests/bpf/progs/test_lsm_audit_kfuncs.c | 263 +++++++++
2 files changed, 861 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/lsm_audit_kfuncs.c b/tools/testing/selftests/bpf/prog_tests/lsm_audit_kfuncs.c
new file mode 100644
index 0000000000000000000000000000000000000000..de18e1a3c79578d4151a12a029f2a9e6cc7648e3
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/lsm_audit_kfuncs.c
@@ -0,0 +1,598 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026 Cloudflare */
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/audit.h>
+#include <linux/netlink.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+#include "audit_helpers.h"
+#include "test_lsm_audit_kfuncs.skel.h"
+#include "test_progs.h"
+
+#ifndef AUDIT_BPF_LSM_ACCESS
+#define AUDIT_BPF_LSM_ACCESS 1427
+#endif
+
+static inline struct sockaddr_in addr4(void)
+{
+ return (struct sockaddr_in){
+ .sin_family = AF_INET,
+ .sin_port = htons(1234),
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+ };
+}
+
+static inline struct sockaddr_in6 addr6(void)
+{
+ return (struct sockaddr_in6){
+ .sin6_family = AF_INET6,
+ .sin6_port = htons(1234),
+ .sin6_addr = in6addr_loopback,
+ };
+}
+
+static int bind_connect(const struct sockaddr *addr, int addrlen)
+{
+ int err;
+ int sock;
+ int opt = 1;
+ socklen_t optlen = sizeof(opt);
+
+ sock = socket(addr->sa_family, SOCK_STREAM, 0);
+ if (!ASSERT_OK_FD(sock, "socket"))
+ return 1;
+
+ err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, optlen);
+ if (!ASSERT_OK(err, "setsockopt"))
+ goto done;
+
+ err = bind(sock, addr, addrlen);
+ if (!ASSERT_OK(err, "bind"))
+ goto done;
+
+ err = connect(sock, addr, addrlen);
+ ASSERT_OK(err, "connect");
+
+ err = getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, &optlen);
+ ASSERT_OK(err, "getsockopt");
+
+done:
+ close(sock);
+ return err;
+}
+
+static void test_audit_log_sockaddr_src(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct sockaddr_in sin = addr4();
+ struct sockaddr_in6 sin6 = addr6();
+ struct bpf_link *link;
+
+ link = bpf_program__attach_lsm(skel->progs.test_sockaddr_src);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"bind4\" saddr=127.0.0.1 src=1234 netif=lo",
+ 1);
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"bind6\" saddr=::1 src=1234 netif=lo", 1);
+
+ if (bind_connect((const struct sockaddr *)&sin, sizeof(sin)))
+ goto done;
+
+ if (bind_connect((const struct sockaddr *)&sin6, sizeof(sin6)))
+ goto done;
+
+ ASSERT_OK(audit_observer_wait(obs), "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+done:
+ bpf_link__destroy(link);
+}
+
+static void test_audit_log_sockaddr_dest(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct sockaddr_in sin = addr4();
+ struct sockaddr_in6 sin6 = addr6();
+ struct bpf_link *link;
+
+ link = bpf_program__attach_lsm(skel->progs.test_sockaddr_dest);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"connect4\" daddr=127.0.0.1 dest=1234 netif=lo",
+ 1);
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"connect6\" daddr=::1 dest=1234 netif=lo",
+ 1);
+
+ if (bind_connect((const struct sockaddr *)&sin, sizeof(sin)))
+ goto out;
+
+ if (bind_connect((const struct sockaddr *)&sin6, sizeof(sin6)))
+ goto out;
+
+ ASSERT_OK(audit_observer_wait(obs), "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+out:
+ bpf_link__destroy(link);
+}
+
+static void test_audit_log_sock(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct sockaddr_in sin = addr4();
+ struct sockaddr_in6 sin6 = addr6();
+ struct bpf_link *link;
+
+ link = bpf_program__attach_lsm(skel->progs.test_sock);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"sock4\" laddr=127.0.0.1 lport=1234 faddr=127.0.0.1 fport=1234 netif=lo",
+ 1);
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"sock6\" laddr=::1 lport=1234 faddr=::1 fport=1234 netif=lo",
+ 1);
+
+ if (bind_connect((const struct sockaddr *)&sin, sizeof(sin)))
+ goto out;
+
+ if (bind_connect((const struct sockaddr *)&sin6, sizeof(sin6)))
+ goto out;
+
+ ASSERT_OK(audit_observer_wait(obs), "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+out:
+ bpf_link__destroy(link);
+}
+
+static void test_audit_log_sock_unix(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct sockaddr_un addr;
+ struct bpf_link *link;
+ char expected[256];
+ char sun_path[108];
+ int server_fd = -1;
+ int opt = 1;
+ socklen_t optlen = sizeof(opt);
+ int err;
+
+ snprintf(sun_path, sizeof(sun_path), "/root/tmp/bpf_audit_test_%d.sock",
+ getpid());
+
+ /* Ensure directory exists */
+ mkdir("/root/tmp", 0755);
+ unlink(sun_path);
+
+ link = bpf_program__attach_lsm(skel->progs.test_sock_unix);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ snprintf(expected, sizeof(expected), "cause=\"sock_unix\" path=\"%s\"",
+ sun_path);
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS, expected, 1);
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, sun_path, sizeof(addr.sun_path) - 1);
+
+ server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (!ASSERT_OK_FD(server_fd, "socket"))
+ goto out;
+
+ err = bind(server_fd, (struct sockaddr *)&addr, sizeof(addr));
+ if (!ASSERT_OK(err, "bind"))
+ goto out;
+
+ err = getsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, &optlen);
+ ASSERT_OK(err, "getsockopt");
+
+ ASSERT_OK(audit_observer_wait(obs), "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+out:
+ if (server_fd >= 0)
+ close(server_fd);
+ unlink(sun_path);
+ bpf_link__destroy(link);
+}
+
+static void test_audit_log_file(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct bpf_link *link;
+ int err;
+ int fd;
+
+ link = bpf_program__attach_lsm(skel->progs.test_file);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"file\" path=\"/dev/null\" dev=\"devtmpfs\" ino=4",
+ 1);
+
+ fd = open("/dev/null", O_RDONLY);
+ close(fd);
+ if (!ASSERT_OK_FD(fd, "open(/dev/null)"))
+ goto out;
+
+ err = audit_observer_wait(obs);
+ ASSERT_OK(err, "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+out:
+ bpf_link__destroy(link);
+}
+
+static void test_audit_log_path(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct bpf_link *link;
+ int err;
+ int fd;
+
+ link = bpf_program__attach_lsm(skel->progs.test_file_path);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"path\" path=\"/dev/null\" dev=\"devtmpfs\" ino=4",
+ 1);
+
+ fd = open("/dev/null", O_RDONLY);
+ close(fd);
+ if (!ASSERT_OK_FD(fd, "open(/dev/null)"))
+ goto out;
+
+ err = audit_observer_wait(obs);
+ ASSERT_OK(err, "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+out:
+ bpf_link__destroy(link);
+}
+
+static void test_audit_log_dentry(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct bpf_link *link;
+ char expected[128];
+ char buf[64];
+ int err;
+
+ link = bpf_program__attach_lsm(skel->progs.test_dentry);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ snprintf(expected, sizeof(expected),
+ "cause=\"dentry\" name=\"exe\" dev=");
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS, expected, 1);
+
+ /* readlink triggers inode_readlink hook */
+ err = readlink("/proc/self/exe", buf, sizeof(buf));
+ if (!ASSERT_GT(err, 0, "readlink(/proc/self/exe)"))
+ goto out;
+
+ err = audit_observer_wait(obs);
+ ASSERT_OK(err, "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+out:
+ bpf_link__destroy(link);
+}
+
+static void test_audit_log_inode(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct bpf_link *link;
+ char expected[128];
+ struct stat st;
+ int err;
+ int fd;
+
+ if (!ASSERT_OK(stat("/dev/null", &st), "stat(/dev/null)"))
+ return;
+
+ link = bpf_program__attach_lsm(skel->progs.test_inode);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ snprintf(expected, sizeof(expected),
+ "cause=\"inode\" name=\"null\" dev=\"devtmpfs\" ino=%lu",
+ st.st_ino);
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS, expected, 1);
+
+ fd = open("/dev/null", O_RDONLY);
+ close(fd);
+ if (!ASSERT_OK_FD(fd, "open(/dev/null)"))
+ goto out;
+
+ err = audit_observer_wait(obs);
+ ASSERT_OK(err, "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+out:
+ bpf_link__destroy(link);
+}
+
+static void test_audit_log_task(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct bpf_link *link;
+ char expected[128];
+ pid_t pid;
+ int err;
+
+ pid = getpid();
+
+ link = bpf_program__attach_lsm(skel->progs.test_task);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ snprintf(expected, sizeof(expected),
+ "cause=\"task\" opid=%d ocomm=\"test_progs\"", pid);
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS, expected, 1);
+
+ err = getpgid(pid);
+ if (!ASSERT_GT(err, -1, "pid pgid match"))
+ goto out;
+
+ err = audit_observer_wait(obs);
+ ASSERT_OK(err, "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+out:
+ bpf_link__destroy(link);
+}
+
+static void test_audit_log_cap(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct bpf_link *link;
+ int err;
+ int fd;
+
+ link = bpf_program__attach_lsm(skel->progs.test_cap);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"cap\" capability=", 1);
+
+ fd = open("/proc/kallsyms", O_RDONLY);
+ close(fd);
+ if (!ASSERT_OK_FD(fd, "open(/proc/kallsyms)"))
+ goto out;
+
+ err = audit_observer_wait(obs);
+ ASSERT_OK(err, "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+out:
+ bpf_link__destroy(link);
+}
+
+static void test_audit_log_ioctl_op(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct bpf_link *link;
+ char expected[128];
+ struct stat st;
+ int err;
+ int fd;
+
+ if (!ASSERT_OK(stat("/dev/null", &st), "stat(/dev/null)"))
+ return;
+
+ link = bpf_program__attach_lsm(skel->progs.test_ioctl_op);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ snprintf(expected, sizeof(expected),
+ "cause=\"ioctl_op\" path=\"/dev/null\" dev=\"devtmpfs\" ino=%lu ioctlcmd=0x%x",
+ st.st_ino, TCGETS);
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS, expected, 1);
+
+ fd = open("/dev/null", O_RDONLY);
+ if (!ASSERT_OK_FD(fd, "open(/dev/null)"))
+ goto out;
+
+ /* ioctl will fail with ENOTTY but the LSM hook fires regardless */
+ ioctl(fd, TCGETS, NULL);
+ close(fd);
+
+ err = audit_observer_wait(obs);
+ ASSERT_OK(err, "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+out:
+ bpf_link__destroy(link);
+}
+
+static void test_audit_log_sleepable(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct bpf_link *link;
+ int err;
+ int fd;
+
+ link = bpf_program__attach_lsm(skel->progs.test_sleepable);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"sleepable\" path=\"/dev/null\" dev=\"devtmpfs\" ino=4",
+ 1);
+
+ fd = open("/dev/null", O_RDONLY);
+ close(fd);
+ if (!ASSERT_OK_FD(fd, "open(/dev/null)"))
+ goto out;
+
+ err = audit_observer_wait(obs);
+ ASSERT_OK(err, "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+out:
+ bpf_link__destroy(link);
+}
+
+static void
+test_audit_log_sockaddr_both_null(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct sockaddr_in sin = addr4();
+ struct bpf_link *link;
+
+ link = bpf_program__attach_lsm(skel->progs.test_sockaddr_both_null);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ /* Should see cause but no saddr/daddr since both were NULL */
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"sockaddr_both_null\"", 1);
+
+ bind_connect((const struct sockaddr *)&sin, sizeof(sin));
+
+ ASSERT_OK(audit_observer_wait(obs), "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+ bpf_link__destroy(link);
+}
+
+static void
+test_audit_log_sockaddr_small_addrlen(struct audit_observer *obs,
+ struct test_lsm_audit_kfuncs *skel)
+{
+ struct sockaddr_in sin = addr4();
+ struct bpf_link *link;
+
+ link = bpf_program__attach_lsm(skel->progs.test_sockaddr_small_addrlen);
+ if (!ASSERT_OK_PTR(link, "attach"))
+ return;
+
+ audit_observer_reset(obs);
+
+ /* Should see cause but no saddr since addrlen was too small */
+ audit_observer_expect(obs, AUDIT_BPF_LSM_ACCESS,
+ "cause=\"sockaddr_small_addrlen\"", 1);
+
+ bind_connect((const struct sockaddr *)&sin, sizeof(sin));
+
+ ASSERT_OK(audit_observer_wait(obs), "audit_observer_wait");
+ ASSERT_TRUE(audit_observer_check_satisfied(obs),
+ "all expectations met");
+
+ bpf_link__destroy(link);
+}
+
+void test_lsm_audit_kfuncs(void)
+{
+ struct test_lsm_audit_kfuncs *skel = NULL;
+ struct audit_observer obs;
+ FILE *log = NULL;
+ int audit_fd;
+
+ audit_fd = audit_init();
+ if (!ASSERT_GE(audit_fd, 0, "audit_init"))
+ return;
+
+ if (env.verbosity > VERBOSE_NONE)
+ log = env.stdout_saved;
+
+ audit_observer_init(&obs, audit_fd, log, 500);
+
+ skel = test_lsm_audit_kfuncs__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "skel load"))
+ goto close_prog;
+
+ if (test__start_subtest("net")) {
+ test_audit_log_sockaddr_src(&obs, skel);
+ test_audit_log_sockaddr_dest(&obs, skel);
+ test_audit_log_sockaddr_both_null(&obs, skel);
+ test_audit_log_sockaddr_small_addrlen(&obs, skel);
+ test_audit_log_sock(&obs, skel);
+ test_audit_log_sock_unix(&obs, skel);
+ }
+
+ if (test__start_subtest("file")) {
+ test_audit_log_file(&obs, skel);
+ test_audit_log_path(&obs, skel);
+ test_audit_log_dentry(&obs, skel);
+ test_audit_log_inode(&obs, skel);
+ }
+
+ if (test__start_subtest("task")) {
+ test_audit_log_task(&obs, skel);
+ test_audit_log_cap(&obs, skel);
+ }
+
+ if (test__start_subtest("ioctl"))
+ test_audit_log_ioctl_op(&obs, skel);
+
+ if (test__start_subtest("sleepable"))
+ test_audit_log_sleepable(&obs, skel);
+
+close_prog:
+ test_lsm_audit_kfuncs__destroy(skel);
+ audit_cleanup(audit_fd);
+}
diff --git a/tools/testing/selftests/bpf/progs/test_lsm_audit_kfuncs.c b/tools/testing/selftests/bpf/progs/test_lsm_audit_kfuncs.c
new file mode 100644
index 0000000000000000000000000000000000000000..952ba09fce638f3bd14c18060a5baa3ccaec19ca
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_lsm_audit_kfuncs.c
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026 Cloudflare */
+
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include <errno.h>
+
+#define AF_UNIX 1
+#define AF_INET 2
+#define AF_INET6 10
+
+char _license[] SEC("license") = "GPL";
+
+SEC("lsm/socket_bind")
+int BPF_PROG(test_sockaddr_src, struct socket *sock, struct sockaddr *address,
+ int addrlen)
+{
+ struct bpf_audit_context *ac;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ switch (address->sa_family) {
+ case AF_INET:
+ bpf_audit_log_cause(ac, "bind4");
+ break;
+ case AF_INET6:
+ bpf_audit_log_cause(ac, "bind6");
+ }
+
+ bpf_audit_log_net_sockaddr(ac, 1, address, NULL, addrlen);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/socket_connect")
+int BPF_PROG(test_sockaddr_dest, struct socket *sock, struct sockaddr *address,
+ int addrlen)
+{
+ struct bpf_audit_context *ac;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ switch (address->sa_family) {
+ case AF_INET:
+ bpf_audit_log_cause(ac, "connect4");
+ break;
+ case AF_INET6:
+ bpf_audit_log_cause(ac, "connect6");
+ }
+
+ bpf_audit_log_net_sockaddr(ac, 1, NULL, address, addrlen);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/socket_bind")
+int BPF_PROG(test_sockaddr_both_null, struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct bpf_audit_context *ac;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ bpf_audit_log_cause(ac, "sockaddr_both_null");
+ bpf_audit_log_net_sockaddr(ac, 1, NULL, NULL, addrlen);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/socket_bind")
+int BPF_PROG(test_sockaddr_small_addrlen, struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct bpf_audit_context *ac;
+
+ if (address->sa_family != AF_INET)
+ return -EINVAL;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ bpf_audit_log_cause(ac, "sockaddr_small_addrlen");
+ bpf_audit_log_net_sockaddr(ac, 1, address, NULL, 1);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/socket_getsockopt")
+int BPF_PROG(test_sock, struct socket *sock, int level, int optname)
+{
+ struct bpf_audit_context *ac;
+ struct sock *sk = sock->sk;
+
+ if (!sk)
+ return -EINVAL;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ switch (sk->__sk_common.skc_family) {
+ case AF_INET:
+ bpf_audit_log_cause(ac, "sock4");
+ break;
+ case AF_INET6:
+ bpf_audit_log_cause(ac, "sock6");
+ }
+
+ bpf_audit_log_net_sock(ac, 1, sock);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/socket_getsockopt")
+int BPF_PROG(test_sock_unix, struct socket *sock, int level, int optname)
+{
+ struct bpf_audit_context *ac;
+ struct sock *sk = sock->sk;
+
+ if (!sk || sk->__sk_common.skc_family != AF_UNIX)
+ return -EINVAL;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ bpf_audit_log_cause(ac, "sock_unix");
+ bpf_audit_log_net_sock(ac, 0, sock);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/file_open")
+int BPF_PROG(test_file, struct file *file)
+{
+ struct bpf_audit_context *ac;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ bpf_audit_log_cause(ac, "file");
+ bpf_audit_log_file(ac, file);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/file_open")
+int BPF_PROG(test_file_path, struct file *file)
+{
+ struct bpf_audit_context *ac;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ bpf_audit_log_cause(ac, "path");
+ bpf_audit_log_path(ac, &file->f_path);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/inode_readlink")
+int BPF_PROG(test_dentry, struct dentry *dentry)
+{
+ struct bpf_audit_context *ac;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ bpf_audit_log_cause(ac, "dentry");
+ bpf_audit_log_dentry(ac, dentry);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/file_open")
+int BPF_PROG(test_inode, struct file *file)
+{
+ struct bpf_audit_context *ac;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ bpf_audit_log_cause(ac, "inode");
+ bpf_audit_log_inode(ac, file->f_inode);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/task_getpgid")
+int BPF_PROG(test_task, struct task_struct *task)
+{
+ struct bpf_audit_context *ac;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ bpf_audit_log_cause(ac, "task");
+ bpf_audit_log_task(ac, task);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/capable")
+int BPF_PROG(test_cap, const struct cred *cred, struct user_namespace *ns,
+ int cap, unsigned int opts)
+{
+ struct bpf_audit_context *ac;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ bpf_audit_log_cause(ac, "cap");
+ bpf_audit_log_cap(ac, cap);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm/file_ioctl")
+int BPF_PROG(test_ioctl_op, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct bpf_audit_context *ac;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ bpf_audit_log_cause(ac, "ioctl_op");
+ bpf_audit_log_ioctl_op(ac, file, cmd);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+
+SEC("lsm.s/file_open")
+int BPF_PROG(test_sleepable, struct file *file)
+{
+ struct bpf_audit_context *ac;
+
+ ac = bpf_audit_log_start();
+ if (!ac)
+ return -ENOMEM;
+
+ bpf_audit_log_cause(ac, "sleepable");
+ bpf_audit_log_file(ac, file);
+ bpf_audit_log_end(ac);
+ return 0;
+}
+

--
2.43.0