Skip to content

Commit 93c6f2b

Browse files
kkdwivediKernel Patches Daemon
authored andcommitted
selftests/bpf: Add C tests for kptr
This uses the __kptr and __kptr_ref macros as well, and tries to test the stuff that is supposed to work, since we have negative tests in test_verifier suite. Also include some code to test map-in-map support, such that the inner_map_meta matches the kptr_off_tab of map added as element. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
1 parent 079a27a commit 93c6f2b

File tree

2 files changed

+227
-0
lines changed

2 files changed

+227
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <test_progs.h>
3+
4+
#include "map_kptr.skel.h"
5+
6+
void test_map_kptr(void)
7+
{
8+
struct map_kptr *skel;
9+
int key = 0, ret;
10+
char buf[24];
11+
12+
skel = map_kptr__open_and_load();
13+
if (!ASSERT_OK_PTR(skel, "map_kptr__open_and_load"))
14+
return;
15+
16+
ret = bpf_map_update_elem(bpf_map__fd(skel->maps.array_map), &key, buf, 0);
17+
ASSERT_OK(ret, "array_map update");
18+
ret = bpf_map_update_elem(bpf_map__fd(skel->maps.array_map), &key, buf, 0);
19+
ASSERT_OK(ret, "array_map update2");
20+
21+
ret = bpf_map_update_elem(bpf_map__fd(skel->maps.hash_map), &key, buf, 0);
22+
ASSERT_OK(ret, "hash_map update");
23+
ret = bpf_map_delete_elem(bpf_map__fd(skel->maps.hash_map), &key);
24+
ASSERT_OK(ret, "hash_map delete");
25+
26+
ret = bpf_map_update_elem(bpf_map__fd(skel->maps.hash_malloc_map), &key, buf, 0);
27+
ASSERT_OK(ret, "hash_malloc_map update");
28+
ret = bpf_map_delete_elem(bpf_map__fd(skel->maps.hash_malloc_map), &key);
29+
ASSERT_OK(ret, "hash_malloc_map delete");
30+
31+
ret = bpf_map_update_elem(bpf_map__fd(skel->maps.lru_hash_map), &key, buf, 0);
32+
ASSERT_OK(ret, "lru_hash_map update");
33+
ret = bpf_map_delete_elem(bpf_map__fd(skel->maps.lru_hash_map), &key);
34+
ASSERT_OK(ret, "lru_hash_map delete");
35+
36+
map_kptr__destroy(skel);
37+
}
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <vmlinux.h>
3+
#include <bpf/bpf_tracing.h>
4+
#include <bpf/bpf_helpers.h>
5+
6+
struct map_value {
7+
struct prog_test_ref_kfunc __kptr *unref_ptr;
8+
struct prog_test_ref_kfunc __kptr_ref *ref_ptr;
9+
};
10+
11+
struct array_map {
12+
__uint(type, BPF_MAP_TYPE_ARRAY);
13+
__type(key, int);
14+
__type(value, struct map_value);
15+
__uint(max_entries, 1);
16+
} array_map SEC(".maps");
17+
18+
struct hash_map {
19+
__uint(type, BPF_MAP_TYPE_HASH);
20+
__type(key, int);
21+
__type(value, struct map_value);
22+
__uint(max_entries, 1);
23+
} hash_map SEC(".maps");
24+
25+
struct hash_malloc_map {
26+
__uint(type, BPF_MAP_TYPE_HASH);
27+
__type(key, int);
28+
__type(value, struct map_value);
29+
__uint(max_entries, 1);
30+
__uint(map_flags, BPF_F_NO_PREALLOC);
31+
} hash_malloc_map SEC(".maps");
32+
33+
struct lru_hash_map {
34+
__uint(type, BPF_MAP_TYPE_LRU_HASH);
35+
__type(key, int);
36+
__type(value, struct map_value);
37+
__uint(max_entries, 1);
38+
} lru_hash_map SEC(".maps");
39+
40+
#define DEFINE_MAP_OF_MAP(map_type, inner_map_type, name) \
41+
struct { \
42+
__uint(type, map_type); \
43+
__uint(max_entries, 1); \
44+
__uint(key_size, sizeof(int)); \
45+
__uint(value_size, sizeof(int)); \
46+
__array(values, struct inner_map_type); \
47+
} name SEC(".maps") = { \
48+
.values = { [0] = &inner_map_type }, \
49+
}
50+
51+
DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, array_map, array_of_array_maps);
52+
DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, hash_map, array_of_hash_maps);
53+
DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, hash_malloc_map, array_of_hash_malloc_maps);
54+
DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, lru_hash_map, array_of_lru_hash_maps);
55+
DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, array_map, hash_of_array_maps);
56+
DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, hash_map, hash_of_hash_maps);
57+
DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, hash_malloc_map, hash_of_hash_malloc_maps);
58+
DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, lru_hash_map, hash_of_lru_hash_maps);
59+
60+
extern struct prog_test_ref_kfunc *bpf_kfunc_call_test_acquire(unsigned long *sp) __ksym;
61+
extern struct prog_test_ref_kfunc *
62+
bpf_kfunc_call_test_kptr_get(struct prog_test_ref_kfunc **p, int a, int b) __ksym;
63+
extern void bpf_kfunc_call_test_release(struct prog_test_ref_kfunc *p) __ksym;
64+
65+
static void test_kptr_unref(struct map_value *v)
66+
{
67+
struct prog_test_ref_kfunc *p;
68+
69+
p = v->unref_ptr;
70+
/* store untrusted_ptr_or_null_ */
71+
v->unref_ptr = p;
72+
if (!p)
73+
return;
74+
if (p->a + p->b > 100)
75+
return;
76+
/* store untrusted_ptr_ */
77+
v->unref_ptr = p;
78+
/* store NULL */
79+
v->unref_ptr = NULL;
80+
}
81+
82+
static void test_kptr_ref(struct map_value *v)
83+
{
84+
struct prog_test_ref_kfunc *p;
85+
86+
p = v->ref_ptr;
87+
/* store ptr_or_null_ */
88+
v->unref_ptr = p;
89+
if (!p)
90+
return;
91+
if (p->a + p->b > 100)
92+
return;
93+
/* store NULL */
94+
p = bpf_kptr_xchg(&v->ref_ptr, NULL);
95+
if (!p)
96+
return;
97+
if (p->a + p->b > 100) {
98+
bpf_kfunc_call_test_release(p);
99+
return;
100+
}
101+
/* store ptr_ */
102+
v->unref_ptr = p;
103+
bpf_kfunc_call_test_release(p);
104+
105+
p = bpf_kfunc_call_test_acquire(&(unsigned long){0});
106+
if (!p)
107+
return;
108+
/* store ptr_ */
109+
p = bpf_kptr_xchg(&v->ref_ptr, p);
110+
if (!p)
111+
return;
112+
if (p->a + p->b > 100) {
113+
bpf_kfunc_call_test_release(p);
114+
return;
115+
}
116+
bpf_kfunc_call_test_release(p);
117+
}
118+
119+
static void test_kptr_get(struct map_value *v)
120+
{
121+
struct prog_test_ref_kfunc *p;
122+
123+
p = bpf_kfunc_call_test_kptr_get(&v->ref_ptr, 0, 0);
124+
if (!p)
125+
return;
126+
if (p->a + p->b > 100) {
127+
bpf_kfunc_call_test_release(p);
128+
return;
129+
}
130+
bpf_kfunc_call_test_release(p);
131+
}
132+
133+
static void test_kptr(struct map_value *v)
134+
{
135+
test_kptr_unref(v);
136+
test_kptr_ref(v);
137+
test_kptr_get(v);
138+
}
139+
140+
SEC("tc")
141+
int test_map_kptr(struct __sk_buff *ctx)
142+
{
143+
struct map_value *v;
144+
int i, key = 0;
145+
146+
#define TEST(map) \
147+
v = bpf_map_lookup_elem(&map, &key); \
148+
if (!v) \
149+
return 0; \
150+
test_kptr(v)
151+
152+
TEST(array_map);
153+
TEST(hash_map);
154+
TEST(hash_malloc_map);
155+
TEST(lru_hash_map);
156+
157+
#undef TEST
158+
return 0;
159+
}
160+
161+
SEC("tc")
162+
int test_map_in_map_kptr(struct __sk_buff *ctx)
163+
{
164+
struct map_value *v;
165+
int i, key = 0;
166+
void *map;
167+
168+
#define TEST(map_in_map) \
169+
map = bpf_map_lookup_elem(&map_in_map, &key); \
170+
if (!map) \
171+
return 0; \
172+
v = bpf_map_lookup_elem(map, &key); \
173+
if (!v) \
174+
return 0; \
175+
test_kptr(v)
176+
177+
TEST(array_of_array_maps);
178+
TEST(array_of_hash_maps);
179+
TEST(array_of_hash_malloc_maps);
180+
TEST(array_of_lru_hash_maps);
181+
TEST(hash_of_array_maps);
182+
TEST(hash_of_hash_maps);
183+
TEST(hash_of_hash_malloc_maps);
184+
TEST(hash_of_lru_hash_maps);
185+
186+
#undef TEST
187+
return 0;
188+
}
189+
190+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)