Skip to content

Commit f04f2ce

Browse files
danobiMartin KaFai Lau
authored and
Martin KaFai Lau
committed
bpf: selftests: Add verifier tests for CO-RE bitfield writes
Add some tests that exercise BPF_CORE_WRITE_BITFIELD() macro. Since some non-trivial bit fiddling is going on, make sure various edge cases (such as adjacent bitfields and bitfields at the edge of structs) are exercised. Acked-by: Andrii Nakryiko <[email protected]> Signed-off-by: Daniel Xu <[email protected]> Link: https://lore.kernel.org/r/72698a1080fa565f541d5654705255984ea2a029.1702325874.git.dxu@dxuuu.xyz Signed-off-by: Martin KaFai Lau <[email protected]>
1 parent 7d19c00 commit f04f2ce

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

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

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "verifier_and.skel.h"
77
#include "verifier_array_access.skel.h"
88
#include "verifier_basic_stack.skel.h"
9+
#include "verifier_bitfield_write.skel.h"
910
#include "verifier_bounds.skel.h"
1011
#include "verifier_bounds_deduction.skel.h"
1112
#include "verifier_bounds_deduction_non_const.skel.h"
@@ -116,6 +117,7 @@ static void run_tests_aux(const char *skel_name,
116117

117118
void test_verifier_and(void) { RUN(verifier_and); }
118119
void test_verifier_basic_stack(void) { RUN(verifier_basic_stack); }
120+
void test_verifier_bitfield_write(void) { RUN(verifier_bitfield_write); }
119121
void test_verifier_bounds(void) { RUN(verifier_bounds); }
120122
void test_verifier_bounds_deduction(void) { RUN(verifier_bounds_deduction); }
121123
void test_verifier_bounds_deduction_non_const(void) { RUN(verifier_bounds_deduction_non_const); }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/bpf.h>
4+
#include <stdint.h>
5+
6+
#include <bpf/bpf_helpers.h>
7+
#include <bpf/bpf_core_read.h>
8+
9+
#include "bpf_misc.h"
10+
11+
struct core_reloc_bitfields {
12+
/* unsigned bitfields */
13+
uint8_t ub1: 1;
14+
uint8_t ub2: 2;
15+
uint32_t ub7: 7;
16+
/* signed bitfields */
17+
int8_t sb4: 4;
18+
int32_t sb20: 20;
19+
/* non-bitfields */
20+
uint32_t u32;
21+
int32_t s32;
22+
} __attribute__((preserve_access_index));
23+
24+
SEC("tc")
25+
__description("single CO-RE bitfield roundtrip")
26+
__btf_path("btf__core_reloc_bitfields.bpf.o")
27+
__success
28+
__retval(3)
29+
int single_field_roundtrip(struct __sk_buff *ctx)
30+
{
31+
struct core_reloc_bitfields bitfields;
32+
33+
__builtin_memset(&bitfields, 0, sizeof(bitfields));
34+
BPF_CORE_WRITE_BITFIELD(&bitfields, ub2, 3);
35+
return BPF_CORE_READ_BITFIELD(&bitfields, ub2);
36+
}
37+
38+
SEC("tc")
39+
__description("multiple CO-RE bitfield roundtrip")
40+
__btf_path("btf__core_reloc_bitfields.bpf.o")
41+
__success
42+
__retval(0x3FD)
43+
int multiple_field_roundtrip(struct __sk_buff *ctx)
44+
{
45+
struct core_reloc_bitfields bitfields;
46+
uint8_t ub2;
47+
int8_t sb4;
48+
49+
__builtin_memset(&bitfields, 0, sizeof(bitfields));
50+
BPF_CORE_WRITE_BITFIELD(&bitfields, ub2, 1);
51+
BPF_CORE_WRITE_BITFIELD(&bitfields, sb4, -1);
52+
53+
ub2 = BPF_CORE_READ_BITFIELD(&bitfields, ub2);
54+
sb4 = BPF_CORE_READ_BITFIELD(&bitfields, sb4);
55+
56+
return (((uint8_t)sb4) << 2) | ub2;
57+
}
58+
59+
SEC("tc")
60+
__description("adjacent CO-RE bitfield roundtrip")
61+
__btf_path("btf__core_reloc_bitfields.bpf.o")
62+
__success
63+
__retval(7)
64+
int adjacent_field_roundtrip(struct __sk_buff *ctx)
65+
{
66+
struct core_reloc_bitfields bitfields;
67+
uint8_t ub1, ub2;
68+
69+
__builtin_memset(&bitfields, 0, sizeof(bitfields));
70+
BPF_CORE_WRITE_BITFIELD(&bitfields, ub1, 1);
71+
BPF_CORE_WRITE_BITFIELD(&bitfields, ub2, 3);
72+
73+
ub1 = BPF_CORE_READ_BITFIELD(&bitfields, ub1);
74+
ub2 = BPF_CORE_READ_BITFIELD(&bitfields, ub2);
75+
76+
return (ub2 << 1) | ub1;
77+
}
78+
79+
SEC("tc")
80+
__description("multibyte CO-RE bitfield roundtrip")
81+
__btf_path("btf__core_reloc_bitfields.bpf.o")
82+
__success
83+
__retval(0x21)
84+
int multibyte_field_roundtrip(struct __sk_buff *ctx)
85+
{
86+
struct core_reloc_bitfields bitfields;
87+
uint32_t ub7;
88+
uint8_t ub1;
89+
90+
__builtin_memset(&bitfields, 0, sizeof(bitfields));
91+
BPF_CORE_WRITE_BITFIELD(&bitfields, ub1, 1);
92+
BPF_CORE_WRITE_BITFIELD(&bitfields, ub7, 16);
93+
94+
ub1 = BPF_CORE_READ_BITFIELD(&bitfields, ub1);
95+
ub7 = BPF_CORE_READ_BITFIELD(&bitfields, ub7);
96+
97+
return (ub7 << 1) | ub1;
98+
}
99+
100+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)