Skip to content

Commit 0ce57f0

Browse files
committed
extend algo wip
1 parent 34aa2e8 commit 0ce57f0

File tree

2 files changed

+68
-54
lines changed

2 files changed

+68
-54
lines changed

include/linux/bpf_verifier.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -714,19 +714,14 @@ struct bpf_scc_info {
714714
* Indicates that read and precision marks are incomplete for
715715
* states with insn_idx in this SCC.
716716
*/
717-
u32 state_loops_possible:1;
718-
/* Number of verifier states with .branches > 0 that have
719-
* state->parent->insn_idx within this SCC.
720-
* In other words, the number of states originating from this
721-
* SCC that have not yet been fully explored.
722-
*/
723-
u32 branches:31;
717+
bool state_loops_possible;
724718
/* Number of times this SCC was entered by some verifier state
725719
* and that state was fully explored.
726720
* In other words, number of times .branches became non-zero
727721
* and then zero again.
728722
*/
729723
u32 scc_epoch;
724+
struct bpf_verifier_state *entry_state;
730725
};
731726

732727
/* single container for all structs

kernel/bpf/verifier.c

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,6 +1787,8 @@ static struct bpf_scc_info *insn_scc(struct bpf_verifier_env *env, int insn_idx)
17871787
return scc ? &env->scc_info[scc] : NULL;
17881788
}
17891789

1790+
static u32 frame_insn_idx(struct bpf_verifier_state *st, u32 frame);
1791+
17901792
/* Returns true iff:
17911793
* - verifier is currently exploring states with origins in some CFG SCCs;
17921794
* - st->insn_idx belongs to one of these SCCs;
@@ -1803,12 +1805,19 @@ static bool incomplete_read_marks(struct bpf_verifier_env *env,
18031805
struct bpf_verifier_state *st)
18041806
{
18051807
struct bpf_scc_info *scc_info;
1808+
u32 insn_idx, i;
18061809

1807-
scc_info = insn_scc(env, st->insn_idx);
1808-
return scc_info &&
1809-
scc_info->state_loops_possible &&
1810-
scc_info->scc_epoch == st->scc_epoch &&
1811-
scc_info->branches > 0;
1810+
for (i = 0; i <= st->curframe; i++) {
1811+
insn_idx = frame_insn_idx(st, i);
1812+
scc_info = insn_scc(env, st->insn_idx);
1813+
if (scc_info &&
1814+
scc_info->state_loops_possible &&
1815+
scc_info->scc_epoch == st->scc_epoch &&
1816+
scc_info->entry_state)
1817+
return true;
1818+
}
1819+
1820+
return false;
18121821
}
18131822

18141823
static void mark_state_loops_possible(struct bpf_verifier_env *env,
@@ -1821,42 +1830,12 @@ static void mark_state_loops_possible(struct bpf_verifier_env *env,
18211830
scc_info->state_loops_possible = 1;
18221831
}
18231832

1824-
/* See comments for bpf_scc_info->{branches,visit_count} and
1825-
* mark_all_regs_read_and_precise().
1826-
*/
1827-
static void parent_scc_enter(struct bpf_verifier_env *env, struct bpf_verifier_state *st)
1828-
{
1829-
struct bpf_scc_info *scc_info;
1830-
1831-
if (!st->parent)
1832-
return;
1833-
scc_info = insn_scc(env, st->parent->insn_idx);
1834-
if (scc_info)
1835-
scc_info->branches++;
1836-
}
1837-
1838-
/* See comments for bpf_scc_info->{branches,visit_count} and
1839-
* mark_all_regs_read_and_precise().
1840-
*/
1841-
static void parent_scc_exit(struct bpf_verifier_env *env, struct bpf_verifier_state *st)
1842-
{
1843-
struct bpf_scc_info *scc_info;
1844-
1845-
if (!st->parent)
1846-
return;
1847-
scc_info = insn_scc(env, st->parent->insn_idx);
1848-
if (scc_info) {
1849-
WARN_ON_ONCE(scc_info->branches == 0);
1850-
scc_info->branches--;
1851-
if (scc_info->branches == 0)
1852-
scc_info->scc_epoch++;
1853-
}
1854-
}
1855-
18561833
static void update_branch_counts(struct bpf_verifier_env *env, struct bpf_verifier_state *st)
18571834
{
18581835
struct bpf_verifier_state_list *sl = NULL, *parent_sl;
18591836
struct bpf_verifier_state *parent;
1837+
struct bpf_scc_info *scc_info;
1838+
u32 insn_idx, i;
18601839

18611840
while (st) {
18621841
u32 br = --st->branches;
@@ -1869,7 +1848,17 @@ static void update_branch_counts(struct bpf_verifier_env *env, struct bpf_verifi
18691848
br);
18701849
if (br)
18711850
break;
1872-
parent_scc_exit(env, st);
1851+
for (i = 0; i <= st->curframe; i++) {
1852+
insn_idx = frame_insn_idx(st, i);
1853+
scc_info = insn_scc(env, insn_idx);
1854+
if (scc_info && scc_info->entry_state == st) {
1855+
scc_info->entry_state = NULL;
1856+
scc_info->scc_epoch++;
1857+
if (env->log.level & BPF_LOG_LEVEL2)
1858+
verbose(env, "insn #%d, scc #%ld new epoch %d\n",
1859+
st->insn_idx, scc_info - env->scc_info, scc_info->scc_epoch);
1860+
}
1861+
}
18731862
parent = st->parent;
18741863
parent_sl = state_parent_as_list(st);
18751864
if (sl)
@@ -1947,7 +1936,6 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
19471936
* which might have large 'branches' count.
19481937
*/
19491938
}
1950-
parent_scc_enter(env, &elem->st);
19511939
return &elem->st;
19521940
err:
19531941
free_verifier_state(env->cur_state, true);
@@ -18240,7 +18228,7 @@ static void mark_all_regs_read_and_precise(struct bpf_verifier_env *env,
1824018228

1824118229
for (i = 0; i <= st->curframe; i++) {
1824218230
insn_idx = frame_insn_idx(st, i);
18243-
live_regs = env->insn_aux_data[st->insn_idx].live_regs_before;
18231+
live_regs = env->insn_aux_data[insn_idx].live_regs_before;
1824418232
func = st->frame[i];
1824518233
for (j = 0; j < BPF_REG_FP; j++) {
1824618234
reg = &func->regs[j];
@@ -18298,8 +18286,8 @@ static void clean_live_states(struct bpf_verifier_env *env, int insn,
1829818286
struct bpf_verifier_state_list *sl;
1829918287
struct bpf_scc_info *scc_info;
1830018288
struct list_head *pos, *head;
18289+
u32 insn_idx, i;
1830118290

18302-
scc_info = insn_scc(env, insn);
1830318291
head = explored_state(env, insn);
1830418292
list_for_each(pos, head) {
1830518293
sl = container_of(pos, struct bpf_verifier_state_list, node);
@@ -18312,10 +18300,25 @@ static void clean_live_states(struct bpf_verifier_env *env, int insn,
1831218300
continue;
1831318301
if (incomplete_read_marks(env, &sl->state))
1831418302
continue;
18315-
if (scc_info &&
18316-
scc_info->state_loops_possible &&
18317-
scc_info->scc_epoch > sl->state.scc_epoch)
18318-
mark_all_regs_read_and_precise(env, &sl->state);
18303+
for (i = 0; i <= sl->state.curframe; i++) {
18304+
insn_idx = frame_insn_idx(&sl->state, i);
18305+
scc_info = insn_scc(env, insn_idx);
18306+
if (env->log.level & BPF_LOG_LEVEL2)
18307+
verbose(env, "clean_live_states: insn #%d, scc #%ld epoch %d vs %d, loops possible? %d\n",
18308+
insn,
18309+
scc_info ? scc_info - env->scc_info : -1,
18310+
sl->state.scc_epoch,
18311+
scc_info ? scc_info->scc_epoch : -1,
18312+
scc_info ? scc_info->state_loops_possible : -1);
18313+
if (scc_info &&
18314+
scc_info->state_loops_possible &&
18315+
scc_info->scc_epoch > sl->state.scc_epoch) {
18316+
if (env->log.level & BPF_LOG_LEVEL2)
18317+
verbose(env, "mark_all_regs_read_and_precise\n");
18318+
mark_all_regs_read_and_precise(env, &sl->state);
18319+
break;
18320+
}
18321+
}
1831918322
clean_verifier_state(env, &sl->state);
1832018323
}
1832118324
}
@@ -19044,13 +19047,27 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
1904419047

1904519048
clean_live_states(env, insn_idx, cur);
1904619049

19050+
if (env->log.level & BPF_LOG_LEVEL2) {
19051+
verbose(env, "is_state_visited: cur_state: ");
19052+
for (i = cur->curframe; i >= 0; i--)
19053+
print_verifier_state(env, cur, i, true);
19054+
}
19055+
1904719056
head = explored_state(env, insn_idx);
1904819057
list_for_each_safe(pos, tmp, head) {
1904919058
sl = container_of(pos, struct bpf_verifier_state_list, node);
1905019059
states_cnt++;
1905119060
if (sl->state.insn_idx != insn_idx)
1905219061
continue;
1905319062

19063+
if (env->log.level & BPF_LOG_LEVEL2) {
19064+
verbose(env, "is_state_visited: candidate: ");
19065+
if (!same_callsites(cur, &sl->state))
19066+
continue;
19067+
for (i = cur->curframe; i >= 0; i--)
19068+
print_verifier_state(env, &sl->state, i, true);
19069+
}
19070+
1905419071
if (sl->state.branches) {
1905519072
struct bpf_func_state *frame = sl->state.frame[sl->state.curframe];
1905619073

@@ -19275,8 +19292,11 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
1927519292
}
1927619293
new->insn_idx = insn_idx;
1927719294
scc_info = insn_scc(env, insn_idx);
19278-
if (scc_info)
19295+
if (scc_info) {
1927919296
new->scc_epoch = scc_info->scc_epoch;
19297+
if (!scc_info->entry_state)
19298+
scc_info->entry_state = new;
19299+
}
1928019300
WARN_ONCE(new->branches != 1,
1928119301
"BUG is_state_visited:branches_to_explore=%d insn %d\n", new->branches, insn_idx);
1928219302

@@ -19285,7 +19305,6 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
1928519305
cur->insn_hist_start = cur->insn_hist_end;
1928619306
cur->dfs_depth = new->dfs_depth + 1;
1928719307
list_add(&new_sl->node, head);
19288-
parent_scc_enter(env, env->cur_state);
1928919308

1929019309
/* connect new state to parentage chain. Current frame needs all
1929119310
* registers connected. Only r6 - r9 of the callers are alive (pushed

0 commit comments

Comments
 (0)