The struct bpf_reg_state is 112 bytes long on 64-bit architectures, with several fields that have limited ranges. In particular, the bool 'precise' at the end causes 7 bytes of padding. This patch packs 'frameno', 'subreg_def', and 'precise' into a single u32/s32 bitfield block: - frameno: 4 bits (sufficient for MAX_CALL_FRAMES=8) - subreg_def: 27 bits (sufficient for 1M insns limit) - precise: 1 bit This reduces the size of struct bpf_reg_state from 112 to 104 bytes, saving 8 bytes per register. This also reduces the size of struct bpf_stack_state. Overall, it reduces peak memory usage of the verifier for complex programs with millions of states. The patch also updates states_maybe_looping() to use a non-bitfield boundary for memcmp(), as offsetof() cannot be used on bitfields. Signed-off-by: wujing Signed-off-by: Qiliang Yuan --- include/linux/bpf_verifier.h | 6 +++--- kernel/bpf/verifier.c | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index 562f7e63be29..0f83360afb03 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -196,14 +196,14 @@ struct bpf_reg_state { * is used which is an index in bpf_verifier_state->frame[] array * pointing to bpf_func_state. */ - u32 frameno; + u32 frameno:4; /* Tracks subreg definition. The stored value is the insn_idx of the * writing insn. This is safe because subreg_def is used before any insn * patching which only happens after main verification finished. */ - s32 subreg_def; + s32 subreg_def:27; /* if (!precise && SCALAR_VALUE) min/max/tnum don't affect safety */ - bool precise; + bool precise:1; }; enum bpf_stack_slot_type { diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 378341e1177f..5e5b831a518c 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -19641,10 +19641,12 @@ static bool states_maybe_looping(struct bpf_verifier_state *old, fold = old->frame[fr]; fcur = cur->frame[fr]; - for (i = 0; i < MAX_BPF_REG; i++) + for (i = 0; i < MAX_BPF_REG; i++) { if (memcmp(&fold->regs[i], &fcur->regs[i], - offsetof(struct bpf_reg_state, frameno))) + offsetof(struct bpf_reg_state, ref_obj_id) + + sizeof(fold->regs[i].ref_obj_id))) return false; + } return true; } -- 2.39.5