All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH testsuite] tests/bpf: Add tests for SELinux BPF token access control
@ 2025-08-08 18:47 Eric Suen
  2025-08-08 19:59 ` Stephen Smalley
  0 siblings, 1 reply; 5+ messages in thread
From: Eric Suen @ 2025-08-08 18:47 UTC (permalink / raw)
  To: selinux; +Cc: paul, stephen.smalley.work, omosnace

This patch adds new tests to verify the SELinux support for BPF token
access control, as introduced in the corresponding kernel patch:
  https://lore.kernel.org/selinux/20250806180149.1995-1-ericsu@linux.microsoft.com/

Four new tests are added to cover both positive and negative scenarios,
ensuring that the SELinux policy enforcement on BPF token usage behaves
as expected.
  - Successful map_create and prog_load when SELinux permissions are
    granted.
  - Enforcement of SELinux policy restrictions when access is denied.

These tests are located under the tests/bpf directory and can be run
using the standard SELinux testsuite workflow.

Signed-off-by: Eric Suen <ericsu@linux.microsoft.com>
---
 policy/test_bpf.te     | 48 ++++++++++++++++++++++++++++++++++
 tests/bpf/Makefile     |  5 ++--
 tests/bpf/bpf_common.h | 10 +++++++
 tests/bpf/bpf_test.c   | 59 ++++++++++++++++++++++++++++++------------
 tests/bpf/test         | 21 ++++++++++++++-
 5 files changed, 124 insertions(+), 19 deletions(-)

diff --git a/policy/test_bpf.te b/policy/test_bpf.te
index 5eab0bd..ef226a8 100644
--- a/policy/test_bpf.te
+++ b/policy/test_bpf.te
@@ -57,3 +57,51 @@ typeattribute test_bpf_deny_prog_run_t bpfdomain;
 allow test_bpf_deny_prog_run_t self:process { setrlimit };
 allow test_bpf_deny_prog_run_t self:capability { sys_resource sys_admin };
 allow test_bpf_deny_prog_run_t self:bpf { map_create map_read map_write prog_load };
+
+################### Allow map_create_as and prog_load_as ###################
+fs_list_bpf_dirs(test_bpf_t);
+allow kernel_t test_bpf_t:bpf map_create;
+allow test_bpf_t bpf_t:dir { ioctl open read search };
+allow test_bpf_t bpf_t:filesystem mount;
+allow test_bpf_t root_t:dir mounton;
+allow test_bpf_t self:bpf { map_create_as prog_load_as };
+allow test_bpf_t self:cap2_userns { bpf perfmon };
+allow test_bpf_t self:cap_userns { net_admin setgid setuid sys_admin };
+allow test_bpf_t self:user_namespace create;
+allow test_bpf_t unlabeled_t:dir search;
+
+############################ Deny map_create_as ############################
+type test_bpf_deny_map_create_as_t;
+testsuite_domain_type(test_bpf_deny_map_create_as_t)
+typeattribute test_bpf_deny_map_create_as_t bpfdomain;
+allow test_bpf_deny_map_create_as_t self:process { setrlimit };
+allow test_bpf_deny_map_create_as_t self:capability { sys_resource sys_admin };
+
+fs_list_bpf_dirs(test_bpf_deny_map_create_as_t);
+allow kernel_t test_bpf_deny_map_create_as_t:bpf map_create;
+allow test_bpf_deny_map_create_as_t bpf_t:dir { ioctl open read search };
+allow test_bpf_deny_map_create_as_t bpf_t:filesystem mount;
+allow test_bpf_deny_map_create_as_t root_t:dir mounton;
+allow test_bpf_deny_map_create_as_t self:bpf { prog_load_as };
+allow test_bpf_deny_map_create_as_t self:cap2_userns { bpf perfmon };
+allow test_bpf_deny_map_create_as_t self:cap_userns { net_admin setgid setuid sys_admin };
+allow test_bpf_deny_map_create_as_t self:user_namespace create;
+allow test_bpf_deny_map_create_as_t unlabeled_t:dir search;
+
+############################ Deny prog_load_as #############################
+type test_bpf_deny_prog_load_as_t;
+testsuite_domain_type(test_bpf_deny_prog_load_as_t)
+typeattribute test_bpf_deny_prog_load_as_t bpfdomain;
+allow test_bpf_deny_prog_load_as_t self:process { setrlimit };
+allow test_bpf_deny_prog_load_as_t self:capability { sys_resource sys_admin };
+
+fs_list_bpf_dirs(test_bpf_deny_prog_load_as_t);
+allow kernel_t test_bpf_deny_prog_load_as_t:bpf map_create;
+allow test_bpf_deny_prog_load_as_t bpf_t:dir { ioctl open read search };
+allow test_bpf_deny_prog_load_as_t bpf_t:filesystem mount;
+allow test_bpf_deny_prog_load_as_t root_t:dir mounton;
+allow test_bpf_deny_prog_load_as_t self:bpf { map_create_as };
+allow test_bpf_deny_prog_load_as_t self:cap2_userns { bpf perfmon };
+allow test_bpf_deny_prog_load_as_t self:cap_userns { net_admin setgid setuid sys_admin };
+allow test_bpf_deny_prog_load_as_t self:user_namespace create;
+allow test_bpf_deny_prog_load_as_t unlabeled_t:dir search;
diff --git a/tests/bpf/Makefile b/tests/bpf/Makefile
index 1ae8ce9..cacefbe 100644
--- a/tests/bpf/Makefile
+++ b/tests/bpf/Makefile
@@ -1,5 +1,5 @@
 TARGETS = bpf_test
-DEPS = bpf_common.c bpf_common.h
+SRCS = bpf_test.c bpf_common.c token_test.c
 LDLIBS += -lselinux -lbpf
 
 # export so that BPF_ENABLED entries get built correctly on local build
@@ -14,4 +14,5 @@ clean:
 	rm -f $(TARGETS) test_sock flag *_flag
 	@set -e; for i in $(BPF_ENABLED); do $(MAKE) -C $$i clean ; done
 
-$(TARGETS): $(DEPS)
+$(TARGETS): $(SRCS)
+	$(CC) $(CFLAGS) -o $@ $^ $(LDLIBS)
\ No newline at end of file
diff --git a/tests/bpf/bpf_common.h b/tests/bpf/bpf_common.h
index 44ac28f..adba522 100644
--- a/tests/bpf/bpf_common.h
+++ b/tests/bpf/bpf_common.h
@@ -12,6 +12,8 @@
 extern int create_bpf_map(void);
 extern int create_bpf_prog(void);
 extern void bpf_setrlimit(void);
+extern int test_bpf_map_create(void);
+extern int test_bpf_prog_load(void);
 
 /* edited eBPF instruction library */
 /* Short form of mov, dst_reg = imm32 */
@@ -32,3 +34,11 @@ extern void bpf_setrlimit(void);
 					       .off   = 0,			\
 							.imm   = 0 })
 
+/* Raw code statement block */
+#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM)			\
+	((struct bpf_insn) {					\
+		.code  = CODE,					\
+			.dst_reg = DST,					\
+				.src_reg = SRC,					\
+					.off   = OFF,					\
+						.imm   = IMM })
diff --git a/tests/bpf/bpf_test.c b/tests/bpf/bpf_test.c
index 3c6a29c..a8dc383 100644
--- a/tests/bpf/bpf_test.c
+++ b/tests/bpf/bpf_test.c
@@ -1,28 +1,38 @@
 #include "bpf_common.h"
 
+#define write_verbose(verbose, fmt, ...) \
+	do { \
+		if (verbose) \
+			printf(fmt "\n", ##__VA_ARGS__); \
+	} while (0)
+
 static void usage(char *progname)
 {
 	fprintf(stderr,
-		"usage:  %s -m|-p [-v]\n"
+		"usage:  %s -m|-p|-c|-l [-v]\n"
 		"Where:\n\t"
 		"-m    Create BPF map fd\n\t"
 		"-p    Create BPF prog fd\n\t"
+		"-c    Test BPF token map create\n\t"
+		"-l    Test BPF token program load\n\t"
 		"-v Print information.\n", progname);
 	exit(-1);
 }
 
 int main(int argc, char *argv[])
 {
-	int opt, result, fd;
-	bool verbose = false;
+	int opt, result, ret;
+	bool verbose = false, is_fd = true;
 	char *context;
 
 	enum {
 		MAP_FD = 1,
-		PROG_FD
+		PROG_FD,
+		MAP_CREATE,
+		PROG_LOAD,
 	} bpf_fd_type;
 
-	while ((opt = getopt(argc, argv, "mpv")) != -1) {
+	while ((opt = getopt(argc, argv, "mpclv")) != -1) {
 		switch (opt) {
 		case 'm':
 			bpf_fd_type = MAP_FD;
@@ -30,6 +40,12 @@ int main(int argc, char *argv[])
 		case 'p':
 			bpf_fd_type = PROG_FD;
 			break;
+		case 'c':
+			bpf_fd_type = MAP_CREATE;
+			break;
+		case 'l':
+			bpf_fd_type = PROG_LOAD;
+			break;
 		case 'v':
 			verbose = true;
 			break;
@@ -44,8 +60,7 @@ int main(int argc, char *argv[])
 		exit(-1);
 	}
 
-	if (verbose)
-		printf("Process context:\n\t%s\n", context);
+	write_verbose(verbose, "Process context:\n\n%s", context);
 
 	free(context);
 
@@ -54,24 +69,36 @@ int main(int argc, char *argv[])
 
 	switch (bpf_fd_type) {
 	case MAP_FD:
-		if (verbose)
-			printf("Creating BPF map\n");
+		write_verbose(verbose, "Creating BPF map");
 
-		fd = create_bpf_map();
+		ret = create_bpf_map();
 		break;
 	case PROG_FD:
-		if (verbose)
-			printf("Creating BPF prog\n");
+		write_verbose(verbose, "Creating BPF prog");
+
+		ret = create_bpf_prog();
+		break;
+	case MAP_CREATE:
+		is_fd = false;
+		write_verbose(verbose, "Testing BPF map create");
+
+		ret = test_bpf_map_create();
+		break;
+	case PROG_LOAD:
+		is_fd = false;
+		write_verbose(verbose, "Testing BPF prog load");
 
-		fd = create_bpf_prog();
+		ret = test_bpf_prog_load();
 		break;
 	default:
 		usage(argv[0]);
 	}
 
-	if (fd < 0)
-		return fd;
+	if (ret < 0)
+		return ret;
+
+	if (is_fd)
+		close(ret);
 
-	close(fd);
 	return 0;
 }
diff --git a/tests/bpf/test b/tests/bpf/test
index a3fd856..aefc70c 100755
--- a/tests/bpf/test
+++ b/tests/bpf/test
@@ -9,8 +9,10 @@ BEGIN {
 
     $test_bpf_count       = 7;
     $test_fdreceive_count = 4;
+    $test_bpf_token_count = 4;
 
-    $test_count = $test_bpf_count + $test_fdreceive_count;
+    $test_count = $test_bpf_count + $test_fdreceive_count +
+                  $test_bpf_token_count;
 
     # allow info to be shown during tests
     $v = $ARGV[0];
@@ -67,6 +69,13 @@ ok( $result eq 0 );
 $result = system "runcon -t test_bpf_t $basedir/bpf_test -p $v";
 ok( $result eq 0 );
 
+# BPF token - BPF_MAP_CREATE_AS, BPF_PROG_LOAD_AS
+$result = system "runcon -t test_bpf_t $basedir/bpf_test -c $v";
+ok ( $result eq 0 );
+
+$result = system "runcon -t test_bpf_t $basedir/bpf_test -l $v";
+ok ( $result eq 0 );
+
 # Deny map_create permission
 $result =
   system "runcon -t test_bpf_deny_map_create_t $basedir/bpf_test -m $v 2>&1";
@@ -92,6 +101,16 @@ $result =
   system "runcon -t test_bpf_deny_prog_run_t $basedir/bpf_test -p $v 2>&1";
 ok($result);
 
+# BPF token - deny BPF_MAP_CREATE_AS
+$result =
+  system "runcon -t test_bpf_deny_map_create_as_t $basedir/bpf_test -c $v 2>&1";
+ok($result);
+
+# BPF token - deny BPF_PROG_LOAD_AS
+$result =
+  system "runcon -t test_bpf_deny_prog_load_as_t $basedir/bpf_test -l $v 2>&1";
+ok($result);
+
 #
 ################ BPF Tests for fdreceive #######################
 #
-- 
2.50.1.windows.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-08-12 13:05 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-08 18:47 [PATCH testsuite] tests/bpf: Add tests for SELinux BPF token access control Eric Suen
2025-08-08 19:59 ` Stephen Smalley
2025-08-11 18:36   ` Eric Suen
2025-08-12 12:18     ` Stephen Smalley
2025-08-12 13:05       ` Stephen Smalley

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.