Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
14static 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
24cleanup_ns:
25 SYS_NOFAIL("ip netns del %s", TEST_NS);
26fail:
27 return -1;
28}
29
30static void cleanup_network(struct nstoken *ns)
31{
32 close_netns(ns);
33 SYS_NOFAIL("ip netns del %s", TEST_NS);
34}
35
36void 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
96cleanup_progs:
97 cgroup_storage__destroy(skel);
98cleanup_network:
99 cleanup_network(ns);
100cleanup_cgroup:
101 close(cgroup_fd);
102 cleanup_cgroup_environment();
103}
104
105void 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
138cleanup_skel:
139 cgroup_storage__destroy(skel);
140cleanup_cgroup:
141 close(cgroup_fd);
142 cleanup_cgroup_environment();
143}