]> git.baikalelectronics.ru Git - kernel.git/commitdiff
bpf: Clear zext_dst of dead insns
authorIlya Leoshkevich <iii@linux.ibm.com>
Thu, 12 Aug 2021 15:18:10 +0000 (17:18 +0200)
committerDaniel Borkmann <daniel@iogearbox.net>
Fri, 13 Aug 2021 15:43:43 +0000 (17:43 +0200)
"access skb fields ok" verifier test fails on s390 with the "verifier
bug. zext_dst is set, but no reg is defined" message. The first insns
of the test prog are ...

   0: 61 01 00 00 00 00 00 00  ldxw %r0,[%r1+0]
   8: 35 00 00 01 00 00 00 00  jge %r0,0,1
  10: 61 01 00 08 00 00 00 00  ldxw %r0,[%r1+8]

... and the 3rd one is dead (this does not look intentional to me, but
this is a separate topic).

sanitize_dead_code() converts dead insns into "ja -1", but keeps
zext_dst. When opt_subreg_zext_lo32_rnd_hi32() tries to parse such
an insn, it sees this discrepancy and bails. This problem can be seen
only with JITs whose bpf_jit_needs_zext() returns true.

Fix by clearning dead insns' zext_dst.

The commits that contributed to this problem are:

1. 6fd67e868e4a ("bpf: add initial suite for selftests"), which
   introduced the test with the dead code.
2. a30208ede390 ("bpf: verifier: mark verified-insn with
   sub-register zext flag"), which introduced the zext_dst flag.
3. 79655c26f1b6 ("bpf: Account for BPF_FETCH in
   insn_has_def32()"), which introduced the sanity check.
4. 91bfb42a9136 ("bpf: Fix leakage under speculation on
   mispredicted branches"), which bisect points to.

It's best to fix this on stable branches that contain the second one,
since that's the point where the inconsistency was introduced.

Fixes: a30208ede390 ("bpf: verifier: mark verified-insn with sub-register zext flag")
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20210812151811.184086-2-iii@linux.ibm.com
kernel/bpf/verifier.c

index f9bda5476ea55c5823c97c83488c42325d65388b..381d3d6f24bcb18efbf60a96bd74e05fc774ae66 100644 (file)
@@ -11663,6 +11663,7 @@ static void sanitize_dead_code(struct bpf_verifier_env *env)
                if (aux_data[i].seen)
                        continue;
                memcpy(insn + i, &trap, sizeof(trap));
+               aux_data[i].zext_dst = false;
        }
 }