xref: /linux/tools/testing/selftests/bpf/progs/verifier_bitfield_write.c (revision bf5802238dc181b1f7375d358af1d01cd72d1c11)
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";
101