From: Eduard Zingerman <eddyz87@gmail.com>
To: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>,
Andrew Werner <awerner32@gmail.com>, bpf <bpf@vger.kernel.org>,
Andrei Matei <andreimatei1@gmail.com>,
Tamir Duberstein <tamird@gmail.com>,
Joanne Koong <joannelkoong@gmail.com>,
kernel-team@dataexmachina.dev, Song Liu <song@kernel.org>,
Kumar Kartikeya Dwivedi <memxor@gmail.com>
Subject: Re: [BUG] verifier escape with iteration helpers (bpf_loop, ...)
Date: Wed, 04 Oct 2023 14:52:33 +0300 [thread overview]
Message-ID: <4d6faf13143da0722de17f8c551c481222c3cb50.camel@gmail.com> (raw)
In-Reply-To: <20231004025731.ft7xjnr2nxdhxjq5@MacBook-Pro-49.local>
On Tue, 2023-10-03 at 19:57 -0700, Alexei Starovoitov wrote:
> > Yes. This may be an issue. I'll try to hack a layered variant I talked
> > before to see what are the underlying issues. The idea is to verify
> > every child state of the loop entry before moving to any branches of
> > loop's parent states.
>
> Isn't that what current DFS logic does?
With a twist: it should wait for local loop convergence before
declaring loop entry state safe. I described it in [1].
Upon entry to a top level loop state E:
1. do DFS for E, disallow switching to any branches that are not
children of E, collect all loop states generated by E's DFS;
3. reschedule loop states;
4. do DFS for rescheduled states, collect all loop states generated in
the process;
5. repeat from 3 until no loop state could be rescheduled;
6. mark E safe, proceed from regular states stack.
[1] https://lore.kernel.org/bpf/8b75e01d27696cd6661890e49bdc06b1e96092c7.camel@gmail.com/
> > The idea is that when `env->stack.size == 0` all V's non-delayed
> > children states are explored and relevant precision marks are
> > propagated to V.
>
> But that is not true.
> if (is_iter_next_insn(env, insn_idx)) {
> if (states_equal(env, &sl->state, cur)) {
> with sl->state.branches > 0
> will prevent exploration of all children.
Yes, it would postpone exploration of some children, but it would be
given a chance to reschedule.
> Hence I still believe that fine tunning this equavalence check is
> the first step in any fix.
Maybe, but so far states_equal(V, C) seems ok:
1. values read by V are defined in C;
2. non-precise scalars are equivalent unconditionally;
3. precise scalars in C are sub-ranges of precise scalars in V;
4. non-scalar values are compared exactly (modulo idmap).
Which of these points are overly optimistic in your opinion?
> > If at this point some states_equal(V, C') is false it
> > is necessary to schedule C' for one more exploration round as it might
> > visit some code blocks that were not visited on the path from V to C'
> > (as different predictions decisions could be made).
>
> exactly my point above,
> but because of broken double 'if' above the 2nd pass might be hitting
> the same issues as the first. Because some path wasn't explored
> the precision marks might still be wrong.
>
> More loop states can be created and delayed again into loop_stack?
Yes, and new reschedule would be done and so on.
> > If a point is reached when for all loop states C' there are some
> > states V such that states_equal(V, C'), there are no more
> > configurations that can visit code blocks not visited on the path from
> > V to C', as prediction decisions would be the same.
>
> and it not, we can repeat loop_stack->stack->loop_stack potentially forever?
It might be the case that such logic would not converge, e.g. as in
the following simple example:
it = iter_new();
i = 0;
while (iter_next(it)) {
if (i & 0x1 == 0)
printk("'i' is precise and different in each state");
++i;
}
iter_destroy(it);
However:
- we have such limitation already;
- examples like this don't play well with current states pruning logic
in general (I think that doing some opportunistic widening of
precise values is an interesting idea (loosing or worsening precision
with ability to backtrack on failure), but this is a different topic).
If loop logic would not converge verifier would report an error:
either instruction or jump limit would be reached.
For the cases when this logic does converge we end up in a state when
no new read or precision marks could be gained, thus it is safe to
accept states_equal == true verdicts.
> Did you look at my broken patch? yes. it's buggy, but it demonstrates
> the idea where it removes above problematic double 'if' and uses
> states_equal() on states where st->branches==0 && st->looping_states==1
<replied in a different email>
> meaning that in those states all paths were explored except the one
> forked by iter_next kfunc.
> So precision and liveness is correct,
That's probably true.
> while doing states_equal on V with branches=2+ is broken.
Not that it is broken, but it's meaning is "maybe a sub-state" instead
of "definitely a sub-state".
next prev parent reply other threads:[~2023-10-04 11:52 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-07 14:04 [BUG] verifier escape with iteration helpers (bpf_loop, ...) Andrew Werner
2023-07-07 16:44 ` Alexei Starovoitov
2023-07-07 18:08 ` Andrii Nakryiko
2023-07-07 18:21 ` Andrew Werner
2023-09-17 21:37 ` Eduard Zingerman
2023-09-17 22:09 ` Kumar Kartikeya Dwivedi
2023-09-18 13:06 ` Eduard Zingerman
2023-09-19 16:28 ` Eduard Zingerman
2023-09-19 23:02 ` Andrii Nakryiko
2023-09-20 0:19 ` Eduard Zingerman
2023-09-20 16:20 ` Eduard Zingerman
2023-09-20 16:57 ` Andrii Nakryiko
2023-09-21 9:14 ` Alexei Starovoitov
2023-09-21 11:03 ` Eduard Zingerman
2023-09-21 12:56 ` Alexei Starovoitov
2023-09-21 16:23 ` Eduard Zingerman
2023-09-21 16:35 ` Andrii Nakryiko
2023-09-21 18:16 ` Eduard Zingerman
2023-09-22 1:01 ` Eduard Zingerman
2023-09-22 2:48 ` Andrii Nakryiko
2023-09-22 18:36 ` Eduard Zingerman
2023-09-22 20:52 ` Andrii Nakryiko
2023-09-25 1:01 ` Eduard Zingerman
2023-09-26 0:33 ` Andrii Nakryiko
2023-09-26 15:55 ` Eduard Zingerman
2023-09-26 16:25 ` Andrii Nakryiko
2023-09-28 1:09 ` Eduard Zingerman
2023-09-28 18:30 ` Andrii Nakryiko
2023-10-02 3:26 ` Eduard Zingerman
2023-09-30 0:41 ` Alexei Starovoitov
2023-10-02 1:40 ` Eduard Zingerman
2023-10-02 16:29 ` Alexei Starovoitov
2023-10-02 17:18 ` Eduard Zingerman
2023-10-03 0:05 ` Alexei Starovoitov
2023-10-03 2:00 ` Alexei Starovoitov
2023-10-03 15:33 ` Eduard Zingerman
2023-10-03 16:07 ` Alexei Starovoitov
2023-10-03 18:50 ` Alexei Starovoitov
2023-10-03 21:52 ` Eduard Zingerman
2023-10-03 22:03 ` Eduard Zingerman
2023-10-03 23:08 ` Alexei Starovoitov
2023-10-03 23:14 ` Eduard Zingerman
2023-10-04 0:22 ` Andrii Nakryiko
2023-10-04 1:05 ` Eduard Zingerman
2023-10-04 2:57 ` Alexei Starovoitov
2023-10-04 5:50 ` Alexei Starovoitov
2023-10-04 9:49 ` Eduard Zingerman
2023-10-04 11:52 ` Eduard Zingerman [this message]
2023-09-19 23:14 ` Andrii Nakryiko
2023-09-20 0:06 ` Eduard Zingerman
2023-09-20 16:37 ` Andrii Nakryiko
2023-09-20 17:13 ` Eduard Zingerman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4d6faf13143da0722de17f8c551c481222c3cb50.camel@gmail.com \
--to=eddyz87@gmail.com \
--cc=alexei.starovoitov@gmail.com \
--cc=andreimatei1@gmail.com \
--cc=andrii.nakryiko@gmail.com \
--cc=awerner32@gmail.com \
--cc=bpf@vger.kernel.org \
--cc=joannelkoong@gmail.com \
--cc=kernel-team@dataexmachina.dev \
--cc=memxor@gmail.com \
--cc=song@kernel.org \
--cc=tamird@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox