1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <unistd.h> 4 #include <sys/socket.h> 5 #include <test_progs.h> 6 #include "cgroup_helpers.h" 7 #include "network_helpers.h" 8 #include "cgroup_storage.skel.h" 9 10 #define TEST_CGROUP "/test-bpf-cgroup-storage-buf/" 11 #define TEST_NS "cgroup_storage_ns" 12 #define PING_CMD "ping localhost -c 1 -W 1 -q" 13 14 static int setup_network(struct nstoken **token) 15 { 16 SYS(fail, "ip netns add %s", TEST_NS); 17 *token = open_netns(TEST_NS); 18 if (!ASSERT_OK_PTR(*token, "open netns")) 19 goto cleanup_ns; 20 SYS(cleanup_ns, "ip link set lo up"); 21 22 return 0; 23 24 cleanup_ns: 25 SYS_NOFAIL("ip netns del %s", TEST_NS); 26 fail: 27 return -1; 28 } 29 30 static void cleanup_network(struct nstoken *ns) 31 { 32 close_netns(ns); 33 SYS_NOFAIL("ip netns del %s", TEST_NS); 34 } 35 36 void test_cgroup_storage(void) 37 { 38 struct bpf_cgroup_storage_key key; 39 struct cgroup_storage *skel; 40 struct nstoken *ns = NULL; 41 unsigned long long value; 42 int cgroup_fd; 43 int err; 44 45 cgroup_fd = cgroup_setup_and_join(TEST_CGROUP); 46 if (!ASSERT_OK_FD(cgroup_fd, "create cgroup")) 47 return; 48 49 if (!ASSERT_OK(setup_network(&ns), "setup network")) 50 goto cleanup_cgroup; 51 52 skel = cgroup_storage__open_and_load(); 53 if (!ASSERT_OK_PTR(skel, "load program")) 54 goto cleanup_network; 55 56 skel->links.bpf_prog = 57 bpf_program__attach_cgroup(skel->progs.bpf_prog, cgroup_fd); 58 if (!ASSERT_OK_PTR(skel->links.bpf_prog, "attach program")) 59 goto cleanup_progs; 60 61 /* Check that one out of every two packets is dropped */ 62 err = SYS_NOFAIL(PING_CMD); 63 ASSERT_OK(err, "first ping"); 64 err = SYS_NOFAIL(PING_CMD); 65 ASSERT_NEQ(err, 0, "second ping"); 66 err = SYS_NOFAIL(PING_CMD); 67 ASSERT_OK(err, "third ping"); 68 69 err = bpf_map__get_next_key(skel->maps.cgroup_storage, NULL, &key, 70 sizeof(key)); 71 if (!ASSERT_OK(err, "get first key")) 72 goto cleanup_progs; 73 err = bpf_map__lookup_elem(skel->maps.cgroup_storage, &key, sizeof(key), 74 &value, sizeof(value), 0); 75 if (!ASSERT_OK(err, "first packet count read")) 76 goto cleanup_progs; 77 78 /* Add one to the packet counter, check again packet filtering */ 79 value++; 80 err = bpf_map__update_elem(skel->maps.cgroup_storage, &key, sizeof(key), 81 &value, sizeof(value), 0); 82 if (!ASSERT_OK(err, "increment packet counter")) 83 goto cleanup_progs; 84 err = SYS_NOFAIL(PING_CMD); 85 ASSERT_OK(err, "fourth ping"); 86 err = SYS_NOFAIL(PING_CMD); 87 ASSERT_NEQ(err, 0, "fifth ping"); 88 err = SYS_NOFAIL(PING_CMD); 89 ASSERT_OK(err, "sixth ping"); 90 91 err = bpf_map__get_next_key(skel->maps.cgroup_storage, &key, &key, 92 sizeof(key)); 93 ASSERT_ERR(err, "bpf_map__get_next_key should fail"); 94 ASSERT_EQ(errno, ENOENT, "no second key"); 95 96 cleanup_progs: 97 cgroup_storage__destroy(skel); 98 cleanup_network: 99 cleanup_network(ns); 100 cleanup_cgroup: 101 close(cgroup_fd); 102 cleanup_cgroup_environment(); 103 } 104 105 void test_cgroup_storage_oob(void) 106 { 107 struct cgroup_storage *skel; 108 int cgroup_fd, sock_fd; 109 110 cgroup_fd = cgroup_setup_and_join(TEST_CGROUP); 111 if (!ASSERT_OK_FD(cgroup_fd, "create cgroup")) 112 return; 113 114 /* Load and attach BPF program */ 115 skel = cgroup_storage__open_and_load(); 116 if (!ASSERT_OK_PTR(skel, "cgroup_storage__open_and_load")) 117 goto cleanup_cgroup; 118 119 skel->links.trigger_oob = bpf_program__attach_cgroup(skel->progs.trigger_oob, 120 cgroup_fd); 121 if (!ASSERT_OK_PTR(skel->links.trigger_oob, "attach_cgroup")) 122 goto cleanup_skel; 123 124 /* Create a socket to trigger cgroup/sock_create hook. 125 * This will execute our BPF program and trigger the OOB read 126 * if the bug is present (before the fix). 127 */ 128 sock_fd = socket(AF_INET, SOCK_DGRAM, 0); 129 if (!ASSERT_OK_FD(sock_fd, "create socket")) 130 goto cleanup_skel; 131 132 close(sock_fd); 133 134 /* If we reach here without a kernel panic or KASAN report, 135 * the test passes (the fix is working). 136 */ 137 138 cleanup_skel: 139 cgroup_storage__destroy(skel); 140 cleanup_cgroup: 141 close(cgroup_fd); 142 cleanup_cgroup_environment(); 143 } 144