Skip to content

Commit 0f79bb8

Browse files
committed
Merge branch 'bpf-introduce-may_goto-and-cond_break'
Alexei Starovoitov says: ==================== bpf: Introduce may_goto and cond_break From: Alexei Starovoitov <ast@kernel.org> v5 -> v6: - Rename BPF_JMA to BPF_JCOND - Addressed Andrii's review comments v4 -> v5: - rewrote patch 1 to avoid fake may_goto_reg and use 'u32 may_goto_cnt' instead. This way may_goto handling is similar to bpf_loop() processing. - fixed bug in patch 2 that RANGE_WITHIN should not use rold->type == NOT_INIT as a safe signal. - patch 3 fixed negative offset computation in cond_break macro - using bpf_arena and cond_break recompiled lib/glob.c as bpf prog and it works! It will be added as a selftest to arena series. v3 -> v4: - fix drained issue reported by John. may_goto insn could be implemented with sticky state (once reaches 0 it stays 0), but the verifier shouldn't assume that. It has to explore both branches. Arguably drained iterator state shouldn't be there at all. bpf_iter_css_next() is not sticky. Can be fixed, but auditing all iterators for stickiness. That's an orthogonal discussion. - explained JMA name reasons in patch 1 - fixed test_progs-no_alu32 issue and added another test v2 -> v3: Major change - drop bpf_can_loop() kfunc and introduce may_goto instruction instead kfunc is a function call while may_goto doesn't consume any registers and LLVM can produce much better code due to less register pressure. - instead of counting from zero to BPF_MAX_LOOPS start from it instead and break out of the loop when count reaches zero - use may_goto instruction in cond_break macro - recognize that 'exact' state comparison doesn't need to be truly exact. regsafe() should ignore precision and liveness marks, but range_within logic is safe to use while evaluating open coded iterators. ==================== Link: https://lore.kernel.org/r/20240306031929.42666-1-alexei.starovoitov@gmail.com Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
2 parents 9a9d1d3 + 0c8bbf9 commit 0f79bb8

9 files changed

Lines changed: 292 additions & 53 deletions

File tree

include/linux/bpf_verifier.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ struct bpf_verifier_state {
449449
u32 jmp_history_cnt;
450450
u32 dfs_depth;
451451
u32 callback_unroll_depth;
452+
u32 may_goto_depth;
452453
};
453454

454455
#define bpf_get_spilled_reg(slot, frame, mask) \
@@ -619,6 +620,7 @@ struct bpf_subprog_info {
619620
u32 start; /* insn idx of function entry point */
620621
u32 linfo_idx; /* The idx to the main_prog->aux->linfo */
621622
u16 stack_depth; /* max. stack depth used by this function */
623+
u16 stack_extra;
622624
bool has_tail_call: 1;
623625
bool tail_call_reachable: 1;
624626
bool has_ld_abs: 1;

include/uapi/linux/bpf.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
4343
#define BPF_JSLT 0xc0 /* SLT is signed, '<' */
4444
#define BPF_JSLE 0xd0 /* SLE is signed, '<=' */
45+
#define BPF_JCOND 0xe0 /* conditional pseudo jumps: may_goto, goto_or_nop */
4546
#define BPF_CALL 0x80 /* function call */
4647
#define BPF_EXIT 0x90 /* function return */
4748

@@ -50,6 +51,10 @@
5051
#define BPF_XCHG (0xe0 | BPF_FETCH) /* atomic exchange */
5152
#define BPF_CMPXCHG (0xf0 | BPF_FETCH) /* atomic compare-and-write */
5253

54+
enum bpf_cond_pseudo_jmp {
55+
BPF_MAY_GOTO = 0,
56+
};
57+
5358
/* Register numbers */
5459
enum {
5560
BPF_REG_0 = 0,

kernel/bpf/core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,6 +1675,7 @@ bool bpf_opcode_in_insntable(u8 code)
16751675
[BPF_LD | BPF_IND | BPF_B] = true,
16761676
[BPF_LD | BPF_IND | BPF_H] = true,
16771677
[BPF_LD | BPF_IND | BPF_W] = true,
1678+
[BPF_JMP | BPF_JCOND] = true,
16781679
};
16791680
#undef BPF_INSN_3_TBL
16801681
#undef BPF_INSN_2_TBL

kernel/bpf/disasm.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,10 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,
322322
} else if (insn->code == (BPF_JMP | BPF_JA)) {
323323
verbose(cbs->private_data, "(%02x) goto pc%+d\n",
324324
insn->code, insn->off);
325+
} else if (insn->code == (BPF_JMP | BPF_JCOND) &&
326+
insn->src_reg == BPF_MAY_GOTO) {
327+
verbose(cbs->private_data, "(%02x) may_goto pc%+d\n",
328+
insn->code, insn->off);
325329
} else if (insn->code == (BPF_JMP32 | BPF_JA)) {
326330
verbose(cbs->private_data, "(%02x) gotol pc%+d\n",
327331
insn->code, insn->imm);

0 commit comments

Comments
 (0)