Skip to content

Commit 654765b

Browse files
author
Alexei Starovoitov
committed
Merge branch 'bpf-copy_verifier_state-should-copy-loop_entry-field'
Eduard Zingerman says: ==================== This patch set fixes a bug in copy_verifier_state() where the loop_entry field was not copied. This omission led to incorrect loop_entry fields remaining in env->cur_state, causing incorrect decisions about loop entry assignments in update_loop_entry(). An example of an unsafe program accepted by the verifier due to this bug can be found in patch #2. This bug can also cause an infinite loop in the verifier, see patch #5. Structure of the patch set: - Patch #1 fixes the bug but has a significant negative impact on verification performance for sched_ext programs. - Patch #3 mitigates the verification performance impact of patch #1 by avoiding clean_live_states() for states whose loop_entry is still being verified. This reduces the number of processed instructions for sched_ext programs by 28–92% in some cases. - Patches #5-6 simplify {get,update}_loop_entry() logic (and are not strictly necessary). - Patches #7–10 mitigate the memory overhead introduced by patch #1 when a program with iterator-based loop hits the 1M instruction limit. This is achieved by freeing states in env->free_list when their branches and used_as_loop_entry counts reach zero. Patches #1-4 were previously sent as a part of [1]. [1] https://lore.kernel.org/bpf/[email protected]/ ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents 0fc6025 + 574078b commit 654765b

File tree

3 files changed

+296
-97
lines changed

3 files changed

+296
-97
lines changed

include/linux/bpf_verifier.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -427,11 +427,6 @@ struct bpf_verifier_state {
427427
bool active_rcu_lock;
428428

429429
bool speculative;
430-
/* If this state was ever pointed-to by other state's loop_entry field
431-
* this flag would be set to true. Used to avoid freeing such states
432-
* while they are still in use.
433-
*/
434-
bool used_as_loop_entry;
435430
bool in_sleepable;
436431

437432
/* first and last insn idx of this verifier state */
@@ -458,6 +453,11 @@ struct bpf_verifier_state {
458453
u32 dfs_depth;
459454
u32 callback_unroll_depth;
460455
u32 may_goto_depth;
456+
/* If this state was ever pointed-to by other state's loop_entry field
457+
* this flag would be set to true. Used to avoid freeing such states
458+
* while they are still in use.
459+
*/
460+
u32 used_as_loop_entry;
461461
};
462462

463463
#define bpf_get_spilled_reg(slot, frame, mask) \
@@ -498,8 +498,10 @@ struct bpf_verifier_state {
498498
/* linked list of verifier states used to prune search */
499499
struct bpf_verifier_state_list {
500500
struct bpf_verifier_state state;
501-
struct bpf_verifier_state_list *next;
502-
int miss_cnt, hit_cnt;
501+
struct list_head node;
502+
u32 miss_cnt;
503+
u32 hit_cnt:31;
504+
u32 in_free_list:1;
503505
};
504506

505507
struct bpf_loop_inline_state {
@@ -710,8 +712,11 @@ struct bpf_verifier_env {
710712
bool test_state_freq; /* test verifier with different pruning frequency */
711713
bool test_reg_invariants; /* fail verification on register invariants violations */
712714
struct bpf_verifier_state *cur_state; /* current verifier state */
713-
struct bpf_verifier_state_list **explored_states; /* search pruning optimization */
714-
struct bpf_verifier_state_list *free_list;
715+
/* Search pruning optimization, array of list_heads for
716+
* lists of struct bpf_verifier_state_list.
717+
*/
718+
struct list_head *explored_states;
719+
struct list_head free_list; /* list of struct bpf_verifier_state_list */
715720
struct bpf_map *used_maps[MAX_USED_MAPS]; /* array of map's used by eBPF program */
716721
struct btf_mod_pair used_btfs[MAX_USED_BTFS]; /* array of BTF's used by BPF program */
717722
u32 used_map_cnt; /* number of used maps */
@@ -767,6 +772,8 @@ struct bpf_verifier_env {
767772
u32 peak_states;
768773
/* longest register parentage chain walked for liveness marking */
769774
u32 longest_mark_read_walk;
775+
u32 free_list_size;
776+
u32 explored_states_size;
770777
bpfptr_t fd_array;
771778

772779
/* bit mask to keep track of whether a register has been accessed

0 commit comments

Comments
 (0)