Skip to content

Commit f0b5c14

Browse files
author
Alexei Starovoitov
committed
Merge branch 'bpf-allow-union-argument-in-trampoline-based-programs'
Leon Hwang says: ==================== bpf: Allow union argument in trampoline based programs While tracing 'release_pages' with bpfsnoop[0], the verifier reports: The function release_pages arg0 type UNION is unsupported. However, it should be acceptable to trace functions that have 'union' arguments. This patch set enables such support in the verifier by allowing 'union' as a valid argument type. Changes: v3 -> v4: * Address comments from Alexei: * Trim bpftrace output in patch #1 log. * Drop the referenced commit info and the test output in patch #2 log. v2 -> v3: * Address comments from Alexei: * Reuse the existing flag BTF_FMODEL_STRUCT_ARG. * Update the comment of the flag BTF_FMODEL_STRUCT_ARG. v1 -> v2: * Add 16B 'union' argument support in x86_64 trampoline. * Update selftests using bpf_testmod. * Add test case about 16-bytes 'union' argument. * Address comments from Alexei: * Study the patch set about 'struct' argument support. * Update selftests to cover more cases. v1: https://lore.kernel.org/bpf/[email protected]/ Links: [0] https://github.com/bpfsnoop/bpfsnoop ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents 2383e45 + 1c6686b commit f0b5c14

File tree

5 files changed

+98
-5
lines changed

5 files changed

+98
-5
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,7 @@ struct bpf_prog_offload {
11281128
*/
11291129
#define MAX_BPF_FUNC_REG_ARGS 5
11301130

1131-
/* The argument is a structure. */
1131+
/* The argument is a structure or a union. */
11321132
#define BTF_FMODEL_STRUCT_ARG BIT(0)
11331133

11341134
/* The argument is signed. */

kernel/bpf/btf.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6751,7 +6751,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
67516751
/* skip modifiers */
67526752
while (btf_type_is_modifier(t))
67536753
t = btf_type_by_id(btf, t->type);
6754-
if (btf_type_is_small_int(t) || btf_is_any_enum(t) || __btf_type_is_struct(t))
6754+
if (btf_type_is_small_int(t) || btf_is_any_enum(t) || btf_type_is_struct(t))
67556755
/* accessing a scalar */
67566756
return true;
67576757
if (!btf_type_is_ptr(t)) {
@@ -7323,7 +7323,7 @@ static int __get_type_size(struct btf *btf, u32 btf_id,
73237323
if (btf_type_is_ptr(t))
73247324
/* kernel size of pointer. Not BPF's size of pointer*/
73257325
return sizeof(void *);
7326-
if (btf_type_is_int(t) || btf_is_any_enum(t) || __btf_type_is_struct(t))
7326+
if (btf_type_is_int(t) || btf_is_any_enum(t) || btf_type_is_struct(t))
73277327
return t->size;
73287328
return -EINVAL;
73297329
}
@@ -7332,7 +7332,7 @@ static u8 __get_type_fmodel_flags(const struct btf_type *t)
73327332
{
73337333
u8 flags = 0;
73347334

7335-
if (__btf_type_is_struct(t))
7335+
if (btf_type_is_struct(t))
73367336
flags |= BTF_FMODEL_STRUCT_ARG;
73377337
if (btf_type_is_signed_int(t))
73387338
flags |= BTF_FMODEL_SIGNED_ARG;
@@ -7373,7 +7373,7 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
73737373
return -EINVAL;
73747374
}
73757375
ret = __get_type_size(btf, func->type, &t);
7376-
if (ret < 0 || __btf_type_is_struct(t)) {
7376+
if (ret < 0 || btf_type_is_struct(t)) {
73777377
bpf_log(log,
73787378
"The function %s return type %s is unsupported.\n",
73797379
tname, btf_type_str(t));

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,39 @@ static void test_struct_many_args(void)
112112
tracing_struct_many_args__destroy(skel);
113113
}
114114

115+
static void test_union_args(void)
116+
{
117+
struct tracing_struct *skel;
118+
int err;
119+
120+
skel = tracing_struct__open_and_load();
121+
if (!ASSERT_OK_PTR(skel, "tracing_struct__open_and_load"))
122+
return;
123+
124+
err = tracing_struct__attach(skel);
125+
if (!ASSERT_OK(err, "tracing_struct__attach"))
126+
goto out;
127+
128+
ASSERT_OK(trigger_module_test_read(256), "trigger_read");
129+
130+
ASSERT_EQ(skel->bss->ut1_a_a, 1, "ut1:a.arg.a");
131+
ASSERT_EQ(skel->bss->ut1_b, 4, "ut1:b");
132+
ASSERT_EQ(skel->bss->ut1_c, 5, "ut1:c");
133+
134+
ASSERT_EQ(skel->bss->ut2_a, 6, "ut2:a");
135+
ASSERT_EQ(skel->bss->ut2_b_a, 2, "ut2:b.arg.a");
136+
ASSERT_EQ(skel->bss->ut2_b_b, 3, "ut2:b.arg.b");
137+
138+
out:
139+
tracing_struct__destroy(skel);
140+
}
141+
115142
void test_tracing_struct(void)
116143
{
117144
if (test__start_subtest("struct_args"))
118145
test_struct_args();
119146
if (test__start_subtest("struct_many_args"))
120147
test_struct_many_args();
148+
if (test__start_subtest("union_args"))
149+
test_union_args();
121150
}

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ struct bpf_testmod_struct_arg_3 {
1818
int b[];
1919
};
2020

21+
union bpf_testmod_union_arg_1 {
22+
char a;
23+
short b;
24+
struct bpf_testmod_struct_arg_1 arg;
25+
};
26+
27+
union bpf_testmod_union_arg_2 {
28+
int a;
29+
long b;
30+
struct bpf_testmod_struct_arg_2 arg;
31+
};
32+
2133
long t1_a_a, t1_a_b, t1_b, t1_c, t1_ret, t1_nregs;
2234
__u64 t1_reg0, t1_reg1, t1_reg2, t1_reg3;
2335
long t2_a, t2_b_a, t2_b_b, t2_c, t2_ret;
@@ -26,6 +38,9 @@ long t4_a_a, t4_b, t4_c, t4_d, t4_e_a, t4_e_b, t4_ret;
2638
long t5_ret;
2739
int t6;
2840

41+
long ut1_a_a, ut1_b, ut1_c;
42+
long ut2_a, ut2_b_a, ut2_b_b;
43+
2944
SEC("fentry/bpf_testmod_test_struct_arg_1")
3045
int BPF_PROG2(test_struct_arg_1, struct bpf_testmod_struct_arg_2, a, int, b, int, c)
3146
{
@@ -130,4 +145,22 @@ int BPF_PROG2(test_struct_arg_11, struct bpf_testmod_struct_arg_3 *, a)
130145
return 0;
131146
}
132147

148+
SEC("fexit/bpf_testmod_test_union_arg_1")
149+
int BPF_PROG2(test_union_arg_1, union bpf_testmod_union_arg_1, a, int, b, int, c)
150+
{
151+
ut1_a_a = a.arg.a;
152+
ut1_b = b;
153+
ut1_c = c;
154+
return 0;
155+
}
156+
157+
SEC("fexit/bpf_testmod_test_union_arg_2")
158+
int BPF_PROG2(test_union_arg_2, int, a, union bpf_testmod_union_arg_2, b)
159+
{
160+
ut2_a = a;
161+
ut2_b_a = b.arg.a;
162+
ut2_b_b = b.arg.b;
163+
return 0;
164+
}
165+
133166
char _license[] SEC("license") = "GPL";

tools/testing/selftests/bpf/test_kmods/bpf_testmod.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ struct bpf_testmod_struct_arg_5 {
6262
long d;
6363
};
6464

65+
union bpf_testmod_union_arg_1 {
66+
char a;
67+
short b;
68+
struct bpf_testmod_struct_arg_1 arg;
69+
};
70+
71+
union bpf_testmod_union_arg_2 {
72+
int a;
73+
long b;
74+
struct bpf_testmod_struct_arg_2 arg;
75+
};
76+
6577
__bpf_hook_start();
6678

6779
noinline int
@@ -128,6 +140,20 @@ bpf_testmod_test_struct_arg_9(u64 a, void *b, short c, int d, void *e, char f,
128140
return bpf_testmod_test_struct_arg_result;
129141
}
130142

143+
noinline int
144+
bpf_testmod_test_union_arg_1(union bpf_testmod_union_arg_1 a, int b, int c)
145+
{
146+
bpf_testmod_test_struct_arg_result = a.arg.a + b + c;
147+
return bpf_testmod_test_struct_arg_result;
148+
}
149+
150+
noinline int
151+
bpf_testmod_test_union_arg_2(int a, union bpf_testmod_union_arg_2 b)
152+
{
153+
bpf_testmod_test_struct_arg_result = a + b.arg.a + b.arg.b;
154+
return bpf_testmod_test_struct_arg_result;
155+
}
156+
131157
noinline int
132158
bpf_testmod_test_arg_ptr_to_struct(struct bpf_testmod_struct_arg_1 *a) {
133159
bpf_testmod_test_struct_arg_result = a->a;
@@ -408,6 +434,8 @@ bpf_testmod_test_read(struct file *file, struct kobject *kobj,
408434
struct bpf_testmod_struct_arg_3 *struct_arg3;
409435
struct bpf_testmod_struct_arg_4 struct_arg4 = {21, 22};
410436
struct bpf_testmod_struct_arg_5 struct_arg5 = {23, 24, 25, 26};
437+
union bpf_testmod_union_arg_1 union_arg1 = { .arg = {1} };
438+
union bpf_testmod_union_arg_2 union_arg2 = { .arg = {2, 3} };
411439
int i = 1;
412440

413441
while (bpf_testmod_return_ptr(i))
@@ -425,6 +453,9 @@ bpf_testmod_test_read(struct file *file, struct kobject *kobj,
425453
(void)bpf_testmod_test_struct_arg_9(16, (void *)17, 18, 19, (void *)20,
426454
21, 22, struct_arg5, 27);
427455

456+
(void)bpf_testmod_test_union_arg_1(union_arg1, 4, 5);
457+
(void)bpf_testmod_test_union_arg_2(6, union_arg2);
458+
428459
(void)bpf_testmod_test_arg_ptr_to_struct(&struct_arg1_2);
429460

430461
(void)trace_bpf_testmod_test_raw_tp_null_tp(NULL);

0 commit comments

Comments
 (0)