@@ -1787,6 +1787,8 @@ static struct bpf_scc_info *insn_scc(struct bpf_verifier_env *env, int insn_idx)
1787
1787
return scc ? &env->scc_info[scc] : NULL;
1788
1788
}
1789
1789
1790
+ static u32 frame_insn_idx(struct bpf_verifier_state *st, u32 frame);
1791
+
1790
1792
/* Returns true iff:
1791
1793
* - verifier is currently exploring states with origins in some CFG SCCs;
1792
1794
* - st->insn_idx belongs to one of these SCCs;
@@ -1803,12 +1805,19 @@ static bool incomplete_read_marks(struct bpf_verifier_env *env,
1803
1805
struct bpf_verifier_state *st)
1804
1806
{
1805
1807
struct bpf_scc_info *scc_info;
1808
+ u32 insn_idx, i;
1806
1809
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;
1812
1821
}
1813
1822
1814
1823
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,
1821
1830
scc_info->state_loops_possible = 1;
1822
1831
}
1823
1832
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
-
1856
1833
static void update_branch_counts(struct bpf_verifier_env *env, struct bpf_verifier_state *st)
1857
1834
{
1858
1835
struct bpf_verifier_state_list *sl = NULL, *parent_sl;
1859
1836
struct bpf_verifier_state *parent;
1837
+ struct bpf_scc_info *scc_info;
1838
+ u32 insn_idx, i;
1860
1839
1861
1840
while (st) {
1862
1841
u32 br = --st->branches;
@@ -1869,7 +1848,17 @@ static void update_branch_counts(struct bpf_verifier_env *env, struct bpf_verifi
1869
1848
br);
1870
1849
if (br)
1871
1850
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
+ }
1873
1862
parent = st->parent;
1874
1863
parent_sl = state_parent_as_list(st);
1875
1864
if (sl)
@@ -1947,7 +1936,6 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
1947
1936
* which might have large 'branches' count.
1948
1937
*/
1949
1938
}
1950
- parent_scc_enter(env, &elem->st);
1951
1939
return &elem->st;
1952
1940
err:
1953
1941
free_verifier_state(env->cur_state, true);
@@ -18240,7 +18228,7 @@ static void mark_all_regs_read_and_precise(struct bpf_verifier_env *env,
18240
18228
18241
18229
for (i = 0; i <= st->curframe; i++) {
18242
18230
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;
18244
18232
func = st->frame[i];
18245
18233
for (j = 0; j < BPF_REG_FP; j++) {
18246
18234
reg = &func->regs[j];
@@ -18298,8 +18286,8 @@ static void clean_live_states(struct bpf_verifier_env *env, int insn,
18298
18286
struct bpf_verifier_state_list *sl;
18299
18287
struct bpf_scc_info *scc_info;
18300
18288
struct list_head *pos, *head;
18289
+ u32 insn_idx, i;
18301
18290
18302
- scc_info = insn_scc(env, insn);
18303
18291
head = explored_state(env, insn);
18304
18292
list_for_each(pos, head) {
18305
18293
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,
18312
18300
continue;
18313
18301
if (incomplete_read_marks(env, &sl->state))
18314
18302
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
+ }
18319
18322
clean_verifier_state(env, &sl->state);
18320
18323
}
18321
18324
}
@@ -19044,13 +19047,27 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
19044
19047
19045
19048
clean_live_states(env, insn_idx, cur);
19046
19049
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
+
19047
19056
head = explored_state(env, insn_idx);
19048
19057
list_for_each_safe(pos, tmp, head) {
19049
19058
sl = container_of(pos, struct bpf_verifier_state_list, node);
19050
19059
states_cnt++;
19051
19060
if (sl->state.insn_idx != insn_idx)
19052
19061
continue;
19053
19062
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
+
19054
19071
if (sl->state.branches) {
19055
19072
struct bpf_func_state *frame = sl->state.frame[sl->state.curframe];
19056
19073
@@ -19275,8 +19292,11 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
19275
19292
}
19276
19293
new->insn_idx = insn_idx;
19277
19294
scc_info = insn_scc(env, insn_idx);
19278
- if (scc_info)
19295
+ if (scc_info) {
19279
19296
new->scc_epoch = scc_info->scc_epoch;
19297
+ if (!scc_info->entry_state)
19298
+ scc_info->entry_state = new;
19299
+ }
19280
19300
WARN_ONCE(new->branches != 1,
19281
19301
"BUG is_state_visited:branches_to_explore=%d insn %d\n", new->branches, insn_idx);
19282
19302
@@ -19285,7 +19305,6 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
19285
19305
cur->insn_hist_start = cur->insn_hist_end;
19286
19306
cur->dfs_depth = new->dfs_depth + 1;
19287
19307
list_add(&new_sl->node, head);
19288
- parent_scc_enter(env, env->cur_state);
19289
19308
19290
19309
/* connect new state to parentage chain. Current frame needs all
19291
19310
* registers connected. Only r6 - r9 of the callers are alive (pushed
0 commit comments