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

selftests/bpf: convert test_dev_cgroup to test_progs

test_dev_cgroup is defined as a standalone test program, and so is not
executed in CI.

Convert it to test_progs framework so it is tested automatically in CI, and
remove the old test. In order to be able to run it in test_progs, /dev/null
must remain usable, so change the new test to test operations on devices
1:3 as valid, and operations on devices 1:5 (/dev/zero) as invalid.

Reviewed-by: Alan Maguire <alan.maguire@oracle.com>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
Link: https://lore.kernel.org/r/20240731-convert_dev_cgroup-v4-2-849425d90de6@bootlin.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>

authored by

Alexis Lothoré (eBPF Foundation) and committed by
Martin KaFai Lau
d83d8230 ba6a9018

+121 -88
-1
tools/testing/selftests/bpf/.gitignore
··· 9 9 test_tag 10 10 FEATURE-DUMP.libbpf 11 11 fixdep 12 - test_dev_cgroup 13 12 /test_progs 14 13 /test_progs-no_alu32 15 14 /test_progs-bpf_gcc
-2
tools/testing/selftests/bpf/Makefile
··· 67 67 68 68 # Order correspond to 'make run_tests' order 69 69 TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \ 70 - test_dev_cgroup \ 71 70 test_sock test_sockmap get_cgroup_id_user \ 72 71 test_cgroup_storage \ 73 72 test_tcpnotify_user test_sysctl \ ··· 291 292 CAP_HELPERS := $(OUTPUT)/cap_helpers.o 292 293 NETWORK_HELPERS := $(OUTPUT)/network_helpers.o 293 294 294 - $(OUTPUT)/test_dev_cgroup: $(CGROUP_HELPERS) $(TESTING_HELPERS) 295 295 $(OUTPUT)/test_skb_cgroup_id_user: $(CGROUP_HELPERS) $(TESTING_HELPERS) 296 296 $(OUTPUT)/test_sock: $(CGROUP_HELPERS) $(TESTING_HELPERS) 297 297 $(OUTPUT)/test_sockmap: $(CGROUP_HELPERS) $(TESTING_HELPERS)
+121
tools/testing/selftests/bpf/prog_tests/cgroup_dev.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <sys/stat.h> 4 + #include <sys/sysmacros.h> 5 + #include <errno.h> 6 + #include "test_progs.h" 7 + #include "cgroup_helpers.h" 8 + #include "dev_cgroup.skel.h" 9 + 10 + #define TEST_CGROUP "/test-bpf-based-device-cgroup/" 11 + #define TEST_BUFFER_SIZE 64 12 + 13 + static void test_mknod(const char *path, mode_t mode, int dev_major, 14 + int dev_minor, int expected_ret, int expected_errno) 15 + { 16 + int ret; 17 + 18 + unlink(path); 19 + ret = mknod(path, mode, makedev(dev_major, dev_minor)); 20 + ASSERT_EQ(ret, expected_ret, "mknod"); 21 + if (expected_ret) 22 + ASSERT_EQ(errno, expected_errno, "mknod errno"); 23 + else 24 + unlink(path); 25 + } 26 + 27 + static void test_read(const char *path, char *buf, int buf_size, 28 + int expected_ret, int expected_errno) 29 + { 30 + int ret, fd; 31 + 32 + fd = open(path, O_RDONLY); 33 + 34 + /* A bare open on unauthorized device should fail */ 35 + if (expected_ret < 0) { 36 + ASSERT_EQ(fd, expected_ret, "open ret for read"); 37 + ASSERT_EQ(errno, expected_errno, "open errno for read"); 38 + if (fd >= 0) 39 + close(fd); 40 + return; 41 + } 42 + 43 + if (!ASSERT_OK_FD(fd, "open ret for read")) 44 + return; 45 + 46 + ret = read(fd, buf, buf_size); 47 + ASSERT_EQ(ret, expected_ret, "read"); 48 + 49 + close(fd); 50 + } 51 + 52 + static void test_write(const char *path, char *buf, int buf_size, 53 + int expected_ret, int expected_errno) 54 + { 55 + int ret, fd; 56 + 57 + fd = open(path, O_WRONLY); 58 + 59 + /* A bare open on unauthorized device should fail */ 60 + if (expected_ret < 0) { 61 + ASSERT_EQ(fd, expected_ret, "open ret for write"); 62 + ASSERT_EQ(errno, expected_errno, "open errno for write"); 63 + if (fd >= 0) 64 + close(fd); 65 + return; 66 + } 67 + 68 + if (!ASSERT_OK_FD(fd, "open ret for write")) 69 + return; 70 + 71 + ret = write(fd, buf, buf_size); 72 + ASSERT_EQ(ret, expected_ret, "write"); 73 + 74 + close(fd); 75 + } 76 + 77 + void test_cgroup_dev(void) 78 + { 79 + char buf[TEST_BUFFER_SIZE] = "some random test data"; 80 + struct dev_cgroup *skel; 81 + int cgroup_fd; 82 + 83 + cgroup_fd = cgroup_setup_and_join(TEST_CGROUP); 84 + if (!ASSERT_OK_FD(cgroup_fd, "cgroup switch")) 85 + return; 86 + 87 + skel = dev_cgroup__open_and_load(); 88 + if (!ASSERT_OK_PTR(skel, "load program")) 89 + goto cleanup_cgroup; 90 + 91 + skel->links.bpf_prog1 = 92 + bpf_program__attach_cgroup(skel->progs.bpf_prog1, cgroup_fd); 93 + if (!ASSERT_OK_PTR(skel->links.bpf_prog1, "attach_program")) 94 + goto cleanup_progs; 95 + 96 + if (test__start_subtest("allow-mknod")) 97 + test_mknod("/dev/test_dev_cgroup_null", S_IFCHR, 1, 3, 0, 0); 98 + 99 + if (test__start_subtest("allow-read")) 100 + test_read("/dev/urandom", buf, TEST_BUFFER_SIZE, 101 + TEST_BUFFER_SIZE, 0); 102 + 103 + if (test__start_subtest("allow-write")) 104 + test_write("/dev/null", buf, TEST_BUFFER_SIZE, 105 + TEST_BUFFER_SIZE, 0); 106 + 107 + if (test__start_subtest("deny-mknod")) 108 + test_mknod("/dev/test_dev_cgroup_zero", S_IFCHR, 1, 5, -1, 109 + EPERM); 110 + 111 + if (test__start_subtest("deny-read")) 112 + test_read("/dev/random", buf, TEST_BUFFER_SIZE, -1, EPERM); 113 + 114 + if (test__start_subtest("deny-write")) 115 + test_write("/dev/zero", buf, TEST_BUFFER_SIZE, -1, EPERM); 116 + 117 + cleanup_progs: 118 + dev_cgroup__destroy(skel); 119 + cleanup_cgroup: 120 + cleanup_cgroup_environment(); 121 + }
-85
tools/testing/selftests/bpf/test_dev_cgroup.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* Copyright (c) 2017 Facebook 3 - */ 4 - 5 - #include <stdio.h> 6 - #include <stdlib.h> 7 - #include <string.h> 8 - #include <errno.h> 9 - #include <assert.h> 10 - #include <sys/time.h> 11 - 12 - #include <linux/bpf.h> 13 - #include <bpf/bpf.h> 14 - #include <bpf/libbpf.h> 15 - 16 - #include "cgroup_helpers.h" 17 - #include "testing_helpers.h" 18 - 19 - #define DEV_CGROUP_PROG "./dev_cgroup.bpf.o" 20 - 21 - #define TEST_CGROUP "/test-bpf-based-device-cgroup/" 22 - 23 - int main(int argc, char **argv) 24 - { 25 - struct bpf_object *obj; 26 - int error = EXIT_FAILURE; 27 - int prog_fd, cgroup_fd; 28 - __u32 prog_cnt; 29 - 30 - /* Use libbpf 1.0 API mode */ 31 - libbpf_set_strict_mode(LIBBPF_STRICT_ALL); 32 - 33 - if (bpf_prog_test_load(DEV_CGROUP_PROG, BPF_PROG_TYPE_CGROUP_DEVICE, 34 - &obj, &prog_fd)) { 35 - printf("Failed to load DEV_CGROUP program\n"); 36 - goto out; 37 - } 38 - 39 - cgroup_fd = cgroup_setup_and_join(TEST_CGROUP); 40 - if (cgroup_fd < 0) { 41 - printf("Failed to create test cgroup\n"); 42 - goto out; 43 - } 44 - 45 - /* Attach bpf program */ 46 - if (bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE, 0)) { 47 - printf("Failed to attach DEV_CGROUP program"); 48 - goto err; 49 - } 50 - 51 - if (bpf_prog_query(cgroup_fd, BPF_CGROUP_DEVICE, 0, NULL, NULL, 52 - &prog_cnt)) { 53 - printf("Failed to query attached programs"); 54 - goto err; 55 - } 56 - 57 - /* All operations with /dev/null and /dev/urandom are allowed, 58 - * everything else is forbidden. 59 - */ 60 - assert(system("rm -f /tmp/test_dev_cgroup_zero") == 0); 61 - assert(system("mknod /tmp/test_dev_cgroup_zero c 1 5")); 62 - assert(system("rm -f /tmp/test_dev_cgroup_zero") == 0); 63 - 64 - /* /dev/null is whitelisted */ 65 - assert(system("rm -f /tmp/test_dev_cgroup_null") == 0); 66 - assert(system("mknod /tmp/test_dev_cgroup_null c 1 3") == 0); 67 - assert(system("rm -f /tmp/test_dev_cgroup_null") == 0); 68 - 69 - assert(system("dd if=/dev/urandom of=/dev/null count=64") == 0); 70 - 71 - /* src is allowed, target is forbidden */ 72 - assert(system("dd if=/dev/urandom of=/dev/full count=64")); 73 - 74 - /* src is forbidden, target is allowed */ 75 - assert(system("dd if=/dev/random of=/dev/null count=64")); 76 - 77 - error = 0; 78 - printf("test_dev_cgroup:PASS\n"); 79 - 80 - err: 81 - cleanup_cgroup_environment(); 82 - 83 - out: 84 - return error; 85 - }