-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]>
- Loading branch information
Showing
2 changed files
with
102 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
tools/testing/selftests/bpf/progs/verifier_bitfield_write.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
#include <linux/bpf.h> | ||
#include <stdint.h> | ||
|
||
#include <bpf/bpf_helpers.h> | ||
#include <bpf/bpf_core_read.h> | ||
|
||
#include "bpf_misc.h" | ||
|
||
struct core_reloc_bitfields { | ||
/* unsigned bitfields */ | ||
uint8_t ub1: 1; | ||
uint8_t ub2: 2; | ||
uint32_t ub7: 7; | ||
/* signed bitfields */ | ||
int8_t sb4: 4; | ||
int32_t sb20: 20; | ||
/* non-bitfields */ | ||
uint32_t u32; | ||
int32_t s32; | ||
} __attribute__((preserve_access_index)); | ||
|
||
SEC("tc") | ||
__description("single CO-RE bitfield roundtrip") | ||
__btf_path("btf__core_reloc_bitfields.bpf.o") | ||
__success | ||
__retval(3) | ||
int single_field_roundtrip(struct __sk_buff *ctx) | ||
{ | ||
struct core_reloc_bitfields bitfields; | ||
|
||
__builtin_memset(&bitfields, 0, sizeof(bitfields)); | ||
BPF_CORE_WRITE_BITFIELD(&bitfields, ub2, 3); | ||
return BPF_CORE_READ_BITFIELD(&bitfields, ub2); | ||
} | ||
|
||
SEC("tc") | ||
__description("multiple CO-RE bitfield roundtrip") | ||
__btf_path("btf__core_reloc_bitfields.bpf.o") | ||
__success | ||
__retval(0x3FD) | ||
int multiple_field_roundtrip(struct __sk_buff *ctx) | ||
{ | ||
struct core_reloc_bitfields bitfields; | ||
uint8_t ub2; | ||
int8_t sb4; | ||
|
||
__builtin_memset(&bitfields, 0, sizeof(bitfields)); | ||
BPF_CORE_WRITE_BITFIELD(&bitfields, ub2, 1); | ||
BPF_CORE_WRITE_BITFIELD(&bitfields, sb4, -1); | ||
|
||
ub2 = BPF_CORE_READ_BITFIELD(&bitfields, ub2); | ||
sb4 = BPF_CORE_READ_BITFIELD(&bitfields, sb4); | ||
|
||
return (((uint8_t)sb4) << 2) | ub2; | ||
} | ||
|
||
SEC("tc") | ||
__description("adjacent CO-RE bitfield roundtrip") | ||
__btf_path("btf__core_reloc_bitfields.bpf.o") | ||
__success | ||
__retval(7) | ||
int adjacent_field_roundtrip(struct __sk_buff *ctx) | ||
{ | ||
struct core_reloc_bitfields bitfields; | ||
uint8_t ub1, ub2; | ||
|
||
__builtin_memset(&bitfields, 0, sizeof(bitfields)); | ||
BPF_CORE_WRITE_BITFIELD(&bitfields, ub1, 1); | ||
BPF_CORE_WRITE_BITFIELD(&bitfields, ub2, 3); | ||
|
||
ub1 = BPF_CORE_READ_BITFIELD(&bitfields, ub1); | ||
ub2 = BPF_CORE_READ_BITFIELD(&bitfields, ub2); | ||
|
||
return (ub2 << 1) | ub1; | ||
} | ||
|
||
SEC("tc") | ||
__description("multibyte CO-RE bitfield roundtrip") | ||
__btf_path("btf__core_reloc_bitfields.bpf.o") | ||
__success | ||
__retval(0x21) | ||
int multibyte_field_roundtrip(struct __sk_buff *ctx) | ||
{ | ||
struct core_reloc_bitfields bitfields; | ||
uint32_t ub7; | ||
uint8_t ub1; | ||
|
||
__builtin_memset(&bitfields, 0, sizeof(bitfields)); | ||
BPF_CORE_WRITE_BITFIELD(&bitfields, ub1, 1); | ||
BPF_CORE_WRITE_BITFIELD(&bitfields, ub7, 16); | ||
|
||
ub1 = BPF_CORE_READ_BITFIELD(&bitfields, ub1); | ||
ub7 = BPF_CORE_READ_BITFIELD(&bitfields, ub7); | ||
|
||
return (ub7 << 1) | ub1; | ||
} | ||
|
||
char _license[] SEC("license") = "GPL"; |