Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <andrii@kernel.org>
Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
Link: https://lore.kernel.org/r/72698a1080fa565f541d5654705255984ea2a029.1702325874.git.dxu@dxuuu.xyz
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>

authored by

Daniel Xu and committed by
Martin KaFai Lau
f04f2ce6 7d19c00e

+102
+2
tools/testing/selftests/bpf/prog_tests/verifier.c
··· 6 6 #include "verifier_and.skel.h" 7 7 #include "verifier_array_access.skel.h" 8 8 #include "verifier_basic_stack.skel.h" 9 + #include "verifier_bitfield_write.skel.h" 9 10 #include "verifier_bounds.skel.h" 10 11 #include "verifier_bounds_deduction.skel.h" 11 12 #include "verifier_bounds_deduction_non_const.skel.h" ··· 117 116 118 117 void test_verifier_and(void) { RUN(verifier_and); } 119 118 void test_verifier_basic_stack(void) { RUN(verifier_basic_stack); } 119 + void test_verifier_bitfield_write(void) { RUN(verifier_bitfield_write); } 120 120 void test_verifier_bounds(void) { RUN(verifier_bounds); } 121 121 void test_verifier_bounds_deduction(void) { RUN(verifier_bounds_deduction); } 122 122 void test_verifier_bounds_deduction_non_const(void) { RUN(verifier_bounds_deduction_non_const); }
+100
tools/testing/selftests/bpf/progs/verifier_bitfield_write.c
··· 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";