Andrii Nakryiko <andrii.nakryiko@xxxxxxxxx> 于2022年12月30日周五 06:16写道:
On Tue, Dec 27, 2022 at 9:24 PM Yonghong Song <yhs@xxxxxxxx> wrote:
On 12/20/22 4:30 PM, Andrii Nakryiko wrote:
On Mon, Dec 19, 2022 at 11:13 AM <sdf@xxxxxxxxxx> wrote:
On 12/19, Hao Sun wrote:
Hi,
The following backtracking bug can be triggered on the latest bpf-next and
Linux 6.1 with the C prog provided. I don't have enough knowledge about
this part in the verifier, don't know how to fix this.
Maybe something related to commit be2ef8161572 ("bpf: allow precision
tracking
for programs with subprogs") and/or the related ones?
This can be reproduced on:
HEAD commit: 0e43662e61f2 tools/resolve_btfids: Use pkg-config to locate
libelf
git tree: bpf-next
console log: https://pastebin.com/raw/45hZ7iqm
kernel config: https://pastebin.com/raw/0pu1CHRm
C reproducer: https://pastebin.com/raw/tqsiezvT
func#0 @0
0: R1=ctx(off=0,imm=0) R10=fp0
0: (18) r2 = 0x8000000000000 ; R2_w=2251799813685248
2: (18) r6 = 0xffff888027358000 ;
R6_w=map_ptr(off=0,ks=3032,vs=3664,imm=0)
4: (18) r7 = 0xffff88802735a000 ;
R7_w=map_ptr(off=0,ks=156,vs=2624,imm=0)
6: (18) r8 = 0xffff88802735e000 ;
R8_w=map_ptr(off=0,ks=2396,vs=76,imm=0)
8: (18) r9 = 0x8e9700000000 ; R9_w=156779191205888
10: (36) if w9 >= 0xffffffe3 goto pc+1
last_idx 10 first_idx 0
regs=200 stack=0 before 8: (18) r9 = 0x8e9700000000
11: R9_w=156779191205888
11: (85) call #0
12: (cc) w2 s>>= w7
w2 should have been set to NOT_INIT (because r1-r5 are clobbered by
calls) and rejected here as !read_ok (see check_reg_arg()) before
attempting to mark precision for r2. Can you please try to debug and
understand why that didn't happen here?
The verifier is doing the right thing here and the 'call #0' does
implicitly cleared r1-r5.
So for 'w2 s>>= w7', since w2 is used, the verifier tries to find
its definition by backtracing. It encountered 'call #0', which clears
and that's what I'm saying is incorrect. Normally we'd get !read_ok
error because s>>= is both READ and WRITE on w2, which is
uninitialized after call instruction according to BPF ABI. And that's
what actually seems to happen correctly in my (simpler) tests locally.
But something is special about this specific repro that somehow either
bypasses this logic, or attempts to mark precision before we get to
that test. That's what we should investigate. I haven't tried to run
this specific repro locally yet, so can't tell for sure.
So, the reason why w2 is not marked as uninit is that the kfunc call in
the BPF program is invalid, "call #0", imm is zero, right?
In check_kfunc_call(), it skips this error temporarily:
/* skip for now, but return error when we find this in fixup_kfunc_call */
if (!insn->imm)
return 0;
So the kfunc call is the previous instruction before "w2 s>>= w7", this
leads to the warning in backtrack_insn():
/* regular helper call sets R0 */
*reg_mask &= ~1;
if (*reg_mask & 0x3f) {
/* if backtracing was looking for registers R1-R5
* they should have been found already.
*/
verbose(env, "BUG regs %x\n", *reg_mask);
WARN_ONCE(1, "verifier backtracking bug”);
return -EFAULT;
}
Any idea or hint on how to fix this?