Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <vmlinux.h>
0003 #include <bpf/bpf_tracing.h>
0004 #include <bpf/bpf_helpers.h>
0005 
0006 struct map_value {
0007     struct prog_test_ref_kfunc __kptr *unref_ptr;
0008     struct prog_test_ref_kfunc __kptr_ref *ref_ptr;
0009 };
0010 
0011 struct array_map {
0012     __uint(type, BPF_MAP_TYPE_ARRAY);
0013     __type(key, int);
0014     __type(value, struct map_value);
0015     __uint(max_entries, 1);
0016 } array_map SEC(".maps");
0017 
0018 struct hash_map {
0019     __uint(type, BPF_MAP_TYPE_HASH);
0020     __type(key, int);
0021     __type(value, struct map_value);
0022     __uint(max_entries, 1);
0023 } hash_map SEC(".maps");
0024 
0025 struct hash_malloc_map {
0026     __uint(type, BPF_MAP_TYPE_HASH);
0027     __type(key, int);
0028     __type(value, struct map_value);
0029     __uint(max_entries, 1);
0030     __uint(map_flags, BPF_F_NO_PREALLOC);
0031 } hash_malloc_map SEC(".maps");
0032 
0033 struct lru_hash_map {
0034     __uint(type, BPF_MAP_TYPE_LRU_HASH);
0035     __type(key, int);
0036     __type(value, struct map_value);
0037     __uint(max_entries, 1);
0038 } lru_hash_map SEC(".maps");
0039 
0040 #define DEFINE_MAP_OF_MAP(map_type, inner_map_type, name)       \
0041     struct {                                                \
0042         __uint(type, map_type);                         \
0043         __uint(max_entries, 1);                         \
0044         __uint(key_size, sizeof(int));                  \
0045         __uint(value_size, sizeof(int));                \
0046         __array(values, struct inner_map_type);         \
0047     } name SEC(".maps") = {                                 \
0048         .values = { [0] = &inner_map_type },            \
0049     }
0050 
0051 DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, array_map, array_of_array_maps);
0052 DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, hash_map, array_of_hash_maps);
0053 DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, hash_malloc_map, array_of_hash_malloc_maps);
0054 DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, lru_hash_map, array_of_lru_hash_maps);
0055 DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, array_map, hash_of_array_maps);
0056 DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, hash_map, hash_of_hash_maps);
0057 DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, hash_malloc_map, hash_of_hash_malloc_maps);
0058 DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, lru_hash_map, hash_of_lru_hash_maps);
0059 
0060 extern struct prog_test_ref_kfunc *bpf_kfunc_call_test_acquire(unsigned long *sp) __ksym;
0061 extern struct prog_test_ref_kfunc *
0062 bpf_kfunc_call_test_kptr_get(struct prog_test_ref_kfunc **p, int a, int b) __ksym;
0063 extern void bpf_kfunc_call_test_release(struct prog_test_ref_kfunc *p) __ksym;
0064 
0065 static void test_kptr_unref(struct map_value *v)
0066 {
0067     struct prog_test_ref_kfunc *p;
0068 
0069     p = v->unref_ptr;
0070     /* store untrusted_ptr_or_null_ */
0071     v->unref_ptr = p;
0072     if (!p)
0073         return;
0074     if (p->a + p->b > 100)
0075         return;
0076     /* store untrusted_ptr_ */
0077     v->unref_ptr = p;
0078     /* store NULL */
0079     v->unref_ptr = NULL;
0080 }
0081 
0082 static void test_kptr_ref(struct map_value *v)
0083 {
0084     struct prog_test_ref_kfunc *p;
0085 
0086     p = v->ref_ptr;
0087     /* store ptr_or_null_ */
0088     v->unref_ptr = p;
0089     if (!p)
0090         return;
0091     if (p->a + p->b > 100)
0092         return;
0093     /* store NULL */
0094     p = bpf_kptr_xchg(&v->ref_ptr, NULL);
0095     if (!p)
0096         return;
0097     if (p->a + p->b > 100) {
0098         bpf_kfunc_call_test_release(p);
0099         return;
0100     }
0101     /* store ptr_ */
0102     v->unref_ptr = p;
0103     bpf_kfunc_call_test_release(p);
0104 
0105     p = bpf_kfunc_call_test_acquire(&(unsigned long){0});
0106     if (!p)
0107         return;
0108     /* store ptr_ */
0109     p = bpf_kptr_xchg(&v->ref_ptr, p);
0110     if (!p)
0111         return;
0112     if (p->a + p->b > 100) {
0113         bpf_kfunc_call_test_release(p);
0114         return;
0115     }
0116     bpf_kfunc_call_test_release(p);
0117 }
0118 
0119 static void test_kptr_get(struct map_value *v)
0120 {
0121     struct prog_test_ref_kfunc *p;
0122 
0123     p = bpf_kfunc_call_test_kptr_get(&v->ref_ptr, 0, 0);
0124     if (!p)
0125         return;
0126     if (p->a + p->b > 100) {
0127         bpf_kfunc_call_test_release(p);
0128         return;
0129     }
0130     bpf_kfunc_call_test_release(p);
0131 }
0132 
0133 static void test_kptr(struct map_value *v)
0134 {
0135     test_kptr_unref(v);
0136     test_kptr_ref(v);
0137     test_kptr_get(v);
0138 }
0139 
0140 SEC("tc")
0141 int test_map_kptr(struct __sk_buff *ctx)
0142 {
0143     struct map_value *v;
0144     int key = 0;
0145 
0146 #define TEST(map)                   \
0147     v = bpf_map_lookup_elem(&map, &key);        \
0148     if (!v)                     \
0149         return 0;               \
0150     test_kptr(v)
0151 
0152     TEST(array_map);
0153     TEST(hash_map);
0154     TEST(hash_malloc_map);
0155     TEST(lru_hash_map);
0156 
0157 #undef TEST
0158     return 0;
0159 }
0160 
0161 SEC("tc")
0162 int test_map_in_map_kptr(struct __sk_buff *ctx)
0163 {
0164     struct map_value *v;
0165     int key = 0;
0166     void *map;
0167 
0168 #define TEST(map_in_map)                                \
0169     map = bpf_map_lookup_elem(&map_in_map, &key);   \
0170     if (!map)                                       \
0171         return 0;                               \
0172     v = bpf_map_lookup_elem(map, &key);     \
0173     if (!v)                     \
0174         return 0;               \
0175     test_kptr(v)
0176 
0177     TEST(array_of_array_maps);
0178     TEST(array_of_hash_maps);
0179     TEST(array_of_hash_malloc_maps);
0180     TEST(array_of_lru_hash_maps);
0181     TEST(hash_of_array_maps);
0182     TEST(hash_of_hash_maps);
0183     TEST(hash_of_hash_malloc_maps);
0184     TEST(hash_of_lru_hash_maps);
0185 
0186 #undef TEST
0187     return 0;
0188 }
0189 
0190 SEC("tc")
0191 int test_map_kptr_ref(struct __sk_buff *ctx)
0192 {
0193     struct prog_test_ref_kfunc *p, *p_st;
0194     unsigned long arg = 0;
0195     struct map_value *v;
0196     int key = 0, ret;
0197 
0198     p = bpf_kfunc_call_test_acquire(&arg);
0199     if (!p)
0200         return 1;
0201 
0202     p_st = p->next;
0203     if (p_st->cnt.refs.counter != 2) {
0204         ret = 2;
0205         goto end;
0206     }
0207 
0208     v = bpf_map_lookup_elem(&array_map, &key);
0209     if (!v) {
0210         ret = 3;
0211         goto end;
0212     }
0213 
0214     p = bpf_kptr_xchg(&v->ref_ptr, p);
0215     if (p) {
0216         ret = 4;
0217         goto end;
0218     }
0219     if (p_st->cnt.refs.counter != 2)
0220         return 5;
0221 
0222     p = bpf_kfunc_call_test_kptr_get(&v->ref_ptr, 0, 0);
0223     if (!p)
0224         return 6;
0225     if (p_st->cnt.refs.counter != 3) {
0226         ret = 7;
0227         goto end;
0228     }
0229     bpf_kfunc_call_test_release(p);
0230     if (p_st->cnt.refs.counter != 2)
0231         return 8;
0232 
0233     p = bpf_kptr_xchg(&v->ref_ptr, NULL);
0234     if (!p)
0235         return 9;
0236     bpf_kfunc_call_test_release(p);
0237     if (p_st->cnt.refs.counter != 1)
0238         return 10;
0239 
0240     p = bpf_kfunc_call_test_acquire(&arg);
0241     if (!p)
0242         return 11;
0243     p = bpf_kptr_xchg(&v->ref_ptr, p);
0244     if (p) {
0245         ret = 12;
0246         goto end;
0247     }
0248     if (p_st->cnt.refs.counter != 2)
0249         return 13;
0250     /* Leave in map */
0251 
0252     return 0;
0253 end:
0254     bpf_kfunc_call_test_release(p);
0255     return ret;
0256 }
0257 
0258 SEC("tc")
0259 int test_map_kptr_ref2(struct __sk_buff *ctx)
0260 {
0261     struct prog_test_ref_kfunc *p, *p_st;
0262     struct map_value *v;
0263     int key = 0;
0264 
0265     v = bpf_map_lookup_elem(&array_map, &key);
0266     if (!v)
0267         return 1;
0268 
0269     p_st = v->ref_ptr;
0270     if (!p_st || p_st->cnt.refs.counter != 2)
0271         return 2;
0272 
0273     p = bpf_kptr_xchg(&v->ref_ptr, NULL);
0274     if (!p)
0275         return 3;
0276     if (p_st->cnt.refs.counter != 2) {
0277         bpf_kfunc_call_test_release(p);
0278         return 4;
0279     }
0280 
0281     p = bpf_kptr_xchg(&v->ref_ptr, p);
0282     if (p) {
0283         bpf_kfunc_call_test_release(p);
0284         return 5;
0285     }
0286     if (p_st->cnt.refs.counter != 2)
0287         return 6;
0288 
0289     return 0;
0290 }
0291 
0292 char _license[] SEC("license") = "GPL";