Skip to content

Commit ca46fbc

Browse files
kkdwvdNobody
authored andcommitted
selftests/bpf: Extend kfunc selftests
Use the prog_test kfuncs to test the referenced PTR_TO_BTF_ID kfunc support, and PTR_TO_CTX, PTR_TO_MEM argument passing support. Also testing the various failure cases for invalid kfunc prototypes. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
1 parent abc21e1 commit ca46fbc

File tree

4 files changed

+241
-2
lines changed

4 files changed

+241
-2
lines changed

net/bpf/test_run.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,105 @@ struct sock * noinline bpf_kfunc_call_test3(struct sock *sk)
232232
return sk;
233233
}
234234

235+
struct prog_test_ref_kfunc {
236+
int a;
237+
int b;
238+
struct prog_test_ref_kfunc *next;
239+
};
240+
241+
static struct prog_test_ref_kfunc prog_test_struct = {
242+
.a = 42,
243+
.b = 108,
244+
.next = &prog_test_struct,
245+
};
246+
247+
noinline struct prog_test_ref_kfunc *
248+
bpf_kfunc_call_test_acquire(unsigned long *scalar_ptr)
249+
{
250+
/* randomly return NULL */
251+
if (get_jiffies_64() % 2)
252+
return NULL;
253+
return &prog_test_struct;
254+
}
255+
256+
noinline void bpf_kfunc_call_test_release(struct prog_test_ref_kfunc *p)
257+
{
258+
}
259+
260+
struct prog_test_pass1 {
261+
int x0;
262+
struct {
263+
int x1;
264+
struct {
265+
int x2;
266+
struct {
267+
int x3;
268+
};
269+
};
270+
};
271+
};
272+
273+
struct prog_test_pass2 {
274+
int len;
275+
short arr1[4];
276+
struct {
277+
char arr2[4];
278+
unsigned long arr3[8];
279+
} x;
280+
};
281+
282+
struct prog_test_fail1 {
283+
void *p;
284+
int x;
285+
};
286+
287+
struct prog_test_fail2 {
288+
int x8;
289+
struct prog_test_pass1 x;
290+
};
291+
292+
struct prog_test_fail3 {
293+
int len;
294+
char arr1[2];
295+
char arr2[0];
296+
};
297+
298+
noinline void bpf_kfunc_call_test_pass_ctx(struct __sk_buff *skb)
299+
{
300+
}
301+
302+
noinline void bpf_kfunc_call_test_pass1(struct prog_test_pass1 *p)
303+
{
304+
}
305+
306+
noinline void bpf_kfunc_call_test_pass2(struct prog_test_pass2 *p)
307+
{
308+
}
309+
310+
noinline void bpf_kfunc_call_test_fail1(struct prog_test_fail1 *p)
311+
{
312+
}
313+
314+
noinline void bpf_kfunc_call_test_fail2(struct prog_test_fail2 *p)
315+
{
316+
}
317+
318+
noinline void bpf_kfunc_call_test_fail3(struct prog_test_fail3 *p)
319+
{
320+
}
321+
322+
noinline void bpf_kfunc_call_test_mem_len_pass1(void *mem, int mem__sz)
323+
{
324+
}
325+
326+
noinline void bpf_kfunc_call_test_mem_len_fail1(void *mem, int len)
327+
{
328+
}
329+
330+
noinline void bpf_kfunc_call_test_mem_len_fail2(u64 *mem, int len)
331+
{
332+
}
333+
235334
__diag_pop();
236335

237336
ALLOW_ERROR_INJECTION(bpf_modify_return_test, ERRNO);
@@ -240,6 +339,17 @@ BTF_KFUNC_SET_START(tc, check, test_sk_kfunc_ids)
240339
BTF_ID(func, bpf_kfunc_call_test1)
241340
BTF_ID(func, bpf_kfunc_call_test2)
242341
BTF_ID(func, bpf_kfunc_call_test3)
342+
BTF_ID(func, bpf_kfunc_call_test_acquire)
343+
BTF_ID(func, bpf_kfunc_call_test_release)
344+
BTF_ID(func, bpf_kfunc_call_test_pass_ctx)
345+
BTF_ID(func, bpf_kfunc_call_test_pass1)
346+
BTF_ID(func, bpf_kfunc_call_test_pass2)
347+
BTF_ID(func, bpf_kfunc_call_test_fail1)
348+
BTF_ID(func, bpf_kfunc_call_test_fail2)
349+
BTF_ID(func, bpf_kfunc_call_test_fail3)
350+
BTF_ID(func, bpf_kfunc_call_test_mem_len_pass1)
351+
BTF_ID(func, bpf_kfunc_call_test_mem_len_fail1)
352+
BTF_ID(func, bpf_kfunc_call_test_mem_len_fail2)
243353
BTF_KFUNC_SET_END(tc, check, test_sk_kfunc_ids)
244354

245355
static void *bpf_test_init(const union bpf_attr *kattr, u32 size,

tools/testing/selftests/bpf/prog_tests/kfunc_call.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ static void test_main(void)
2727
ASSERT_OK(err, "bpf_prog_test_run(test2)");
2828
ASSERT_EQ(retval, 3, "test2-retval");
2929

30+
prog_fd = skel->progs.kfunc_call_test_ref_btf_id.prog_fd;
31+
err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
32+
NULL, NULL, (__u32 *)&retval, NULL);
33+
ASSERT_OK(err, "bpf_prog_test_run(test_ref_btf_id)");
34+
ASSERT_EQ(retval, 0, "test_ref_btf_id-retval");
35+
3036
kfunc_call_test_lskel__destroy(skel);
3137
}
3238

tools/testing/selftests/bpf/progs/kfunc_call_test.c

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
// SPDX-License-Identifier: GPL-2.0
22
/* Copyright (c) 2021 Facebook */
3-
#include <linux/bpf.h>
3+
#include <vmlinux.h>
44
#include <bpf/bpf_helpers.h>
5-
#include "bpf_tcp_helpers.h"
65

76
extern int bpf_kfunc_call_test2(struct sock *sk, __u32 a, __u32 b) __ksym;
87
extern __u64 bpf_kfunc_call_test1(struct sock *sk, __u32 a, __u64 b,
98
__u32 c, __u64 d) __ksym;
109

10+
extern struct prog_test_ref_kfunc *bpf_kfunc_call_test_acquire(unsigned long *sp) __ksym;
11+
extern void bpf_kfunc_call_test_release(struct prog_test_ref_kfunc *p) __ksym;
12+
extern void bpf_kfunc_call_test_pass_ctx(struct __sk_buff *skb) __ksym;
13+
extern void bpf_kfunc_call_test_pass1(struct prog_test_pass1 *p) __ksym;
14+
extern void bpf_kfunc_call_test_pass2(struct prog_test_pass2 *p) __ksym;
15+
extern void bpf_kfunc_call_test_mem_len_pass1(void *mem, int len) __ksym;
16+
extern void bpf_kfunc_call_test_mem_len_fail2(__u64 *mem, int len) __ksym;
17+
1118
SEC("tc")
1219
int kfunc_call_test2(struct __sk_buff *skb)
1320
{
@@ -44,4 +51,45 @@ int kfunc_call_test1(struct __sk_buff *skb)
4451
return ret;
4552
}
4653

54+
SEC("tc")
55+
int kfunc_call_test_ref_btf_id(struct __sk_buff *skb)
56+
{
57+
struct prog_test_ref_kfunc *pt;
58+
unsigned long s = 0;
59+
int ret = 0;
60+
61+
pt = bpf_kfunc_call_test_acquire(&s);
62+
if (pt) {
63+
if (pt->a != 42 || pt->b != 108)
64+
ret = -1;
65+
bpf_kfunc_call_test_release(pt);
66+
}
67+
return ret;
68+
}
69+
70+
SEC("tc")
71+
int kfunc_call_test_pass(struct __sk_buff *skb)
72+
{
73+
struct prog_test_pass1 p1 = {};
74+
struct prog_test_pass2 p2 = {};
75+
short a = 0;
76+
__u64 b = 0;
77+
long c = 0;
78+
char d = 0;
79+
int e = 0;
80+
81+
bpf_kfunc_call_test_pass_ctx(skb);
82+
bpf_kfunc_call_test_pass1(&p1);
83+
bpf_kfunc_call_test_pass2(&p2);
84+
85+
bpf_kfunc_call_test_mem_len_pass1(&a, sizeof(a));
86+
bpf_kfunc_call_test_mem_len_pass1(&b, sizeof(b));
87+
bpf_kfunc_call_test_mem_len_pass1(&c, sizeof(c));
88+
bpf_kfunc_call_test_mem_len_pass1(&d, sizeof(d));
89+
bpf_kfunc_call_test_mem_len_pass1(&e, sizeof(e));
90+
bpf_kfunc_call_test_mem_len_fail2(&b, -1);
91+
92+
return 0;
93+
}
94+
4795
char _license[] SEC("license") = "GPL";

tools/testing/selftests/bpf/verifier/calls.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,81 @@
2121
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
2222
.result = ACCEPT,
2323
},
24+
{
25+
"calls: invalid kfunc call: ptr_to_mem to struct with non-scalar",
26+
.insns = {
27+
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
28+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
29+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
30+
BPF_EXIT_INSN(),
31+
},
32+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
33+
.result = REJECT,
34+
.errstr = "arg#0 pointer type STRUCT prog_test_fail1 must point to scalar",
35+
.fixup_kfunc_btf_id = {
36+
{ "bpf_kfunc_call_test_fail1", 2 },
37+
},
38+
},
39+
{
40+
"calls: invalid kfunc call: ptr_to_mem to struct with nesting depth > 4",
41+
.insns = {
42+
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
43+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
44+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
45+
BPF_EXIT_INSN(),
46+
},
47+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
48+
.result = REJECT,
49+
.errstr = "max struct nesting depth exceeded\narg#0 pointer type STRUCT prog_test_fail2",
50+
.fixup_kfunc_btf_id = {
51+
{ "bpf_kfunc_call_test_fail2", 2 },
52+
},
53+
},
54+
{
55+
"calls: invalid kfunc call: ptr_to_mem to struct with FAM",
56+
.insns = {
57+
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
58+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
59+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
60+
BPF_EXIT_INSN(),
61+
},
62+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
63+
.result = REJECT,
64+
.errstr = "arg#0 pointer type STRUCT prog_test_fail3 must point to scalar",
65+
.fixup_kfunc_btf_id = {
66+
{ "bpf_kfunc_call_test_fail3", 2 },
67+
},
68+
},
69+
{
70+
"calls: invalid kfunc call: reg->type != PTR_TO_CTX",
71+
.insns = {
72+
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
73+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
74+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
75+
BPF_EXIT_INSN(),
76+
},
77+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
78+
.result = REJECT,
79+
.errstr = "arg#0 expected pointer to ctx, but got PTR",
80+
.fixup_kfunc_btf_id = {
81+
{ "bpf_kfunc_call_test_pass_ctx", 2 },
82+
},
83+
},
84+
{
85+
"calls: invalid kfunc call: void * not allowed in func proto without mem size arg",
86+
.insns = {
87+
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
88+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
89+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
90+
BPF_EXIT_INSN(),
91+
},
92+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
93+
.result = REJECT,
94+
.errstr = "arg#0 pointer type UNKNOWN must point to scalar",
95+
.fixup_kfunc_btf_id = {
96+
{ "bpf_kfunc_call_test_mem_len_fail1", 2 },
97+
},
98+
},
2499
{
25100
"calls: basic sanity",
26101
.insns = {

0 commit comments

Comments
 (0)