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

Frederick Lawler fred at cloudflare.com
Wed Mar 11 21:31:20 UTC 2026


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 at 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




More information about the Linux-security-module-archive mailing list