Skip to content

Commit fbc0b02

Browse files
author
Alexei Starovoitov
committed
Merge branch 'Add precision propagation for subprogs and callbacks'
Andrii Nakryiko says: ==================== As more and more real-world BPF programs become more complex and increasingly use subprograms (both static and global), scalar precision tracking and its (previously weak) support for BPF subprograms (and callbacks as a special case of that) is becoming more and more of an issue and limitation. Couple that with increasing reliance on state equivalence (BPF open-coded iterators have a hard requirement for state equivalence to converge and successfully validate loops), and it becomes pretty critical to address this limitation and make precision tracking universally supported for BPF programs of any complexity and composition. This patch set teaches BPF verifier to support SCALAR precision backpropagation across multiple frames (for subprogram calls and callback simulations) and addresses most practical situations (SCALAR stack loads/stores using registers other than r10 being the last remaining limitation, though thankfully rarely used in practice). Main logic is explained in details in patch #8. The rest are preliminary preparations, refactorings, clean ups, and fixes. See respective patches for details. Patch #8 has also veristat comparison of results for selftests, Cilium, and some of Meta production BPF programs before and after these changes. v2->v3: - drop bitcnt and ifs from bt_xxx() helpers (Alexei); v1->v2: - addressed review feedback form Alexei, adjusted commit messages, comments, added verbose(), WARN_ONCE(), etc; - re-ran all the tests and veristat on selftests, cilium, and meta-internal code: no new changes and no kernel warnings. ==================== Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2 parents 7866fc6 + c91ab90 commit fbc0b02

8 files changed

Lines changed: 1111 additions & 222 deletions

File tree

include/linux/bpf_verifier.h

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@
1818
* that converting umax_value to int cannot overflow.
1919
*/
2020
#define BPF_MAX_VAR_SIZ (1 << 29)
21-
/* size of type_str_buf in bpf_verifier. */
22-
#define TYPE_STR_BUF_LEN 128
21+
/* size of tmp_str_buf in bpf_verifier.
22+
* we need at least 306 bytes to fit full stack mask representation
23+
* (in the "-8,-16,...,-512" form)
24+
*/
25+
#define TMP_STR_BUF_LEN 320
2326

2427
/* Liveness marks, used for registers and spilled-regs (in stack slots).
2528
* Read marks propagate upwards until they find a write mark; they record that
@@ -238,6 +241,10 @@ enum bpf_stack_slot_type {
238241

239242
#define BPF_REG_SIZE 8 /* size of eBPF register in bytes */
240243

244+
#define BPF_REGMASK_ARGS ((1 << BPF_REG_1) | (1 << BPF_REG_2) | \
245+
(1 << BPF_REG_3) | (1 << BPF_REG_4) | \
246+
(1 << BPF_REG_5))
247+
241248
#define BPF_DYNPTR_SIZE sizeof(struct bpf_dynptr_kern)
242249
#define BPF_DYNPTR_NR_SLOTS (BPF_DYNPTR_SIZE / BPF_REG_SIZE)
243250

@@ -541,6 +548,15 @@ struct bpf_subprog_info {
541548
bool is_async_cb;
542549
};
543550

551+
struct bpf_verifier_env;
552+
553+
struct backtrack_state {
554+
struct bpf_verifier_env *env;
555+
u32 frame;
556+
u32 reg_masks[MAX_CALL_FRAMES];
557+
u64 stack_masks[MAX_CALL_FRAMES];
558+
};
559+
544560
/* single container for all structs
545561
* one verifier_env per bpf_check() call
546562
*/
@@ -578,6 +594,7 @@ struct bpf_verifier_env {
578594
int *insn_stack;
579595
int cur_stack;
580596
} cfg;
597+
struct backtrack_state bt;
581598
u32 pass_cnt; /* number of times do_check() was called */
582599
u32 subprog_cnt;
583600
/* number of instructions analyzed by the verifier */
@@ -606,8 +623,10 @@ struct bpf_verifier_env {
606623
/* Same as scratched_regs but for stack slots */
607624
u64 scratched_stack_slots;
608625
u64 prev_log_pos, prev_insn_print_pos;
609-
/* buffer used in reg_type_str() to generate reg_type string */
610-
char type_str_buf[TYPE_STR_BUF_LEN];
626+
/* buffer used to generate temporary string representations,
627+
* e.g., in reg_type_str() to generate reg_type string
628+
*/
629+
char tmp_str_buf[TMP_STR_BUF_LEN];
611630
};
612631

613632
__printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log,

0 commit comments

Comments
 (0)