diff options
author | Alexei Starovoitov <ast@kernel.org> | 2024-06-12 18:38:13 -0700 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2024-06-14 21:52:39 +0200 |
commit | 98d7ca374ba4b39e7535613d40e159f09ca14da2 (patch) | |
tree | cc45a92aa7645787141a5f250bc085c9f815fbc3 /kernel/bpf/log.c | |
parent | 124e8c2b1b5d08a10d3a44ed082eaaf98a78c91f (diff) |
bpf: Track delta between "linked" registers.
Compilers can generate the code
r1 = r2
r1 += 0x1
if r2 < 1000 goto ...
use knowledge of r2 range in subsequent r1 operations
So remember constant delta between r2 and r1 and update r1 after 'if' condition.
Unfortunately LLVM still uses this pattern for loops with 'can_loop' construct:
for (i = 0; i < 1000 && can_loop; i++)
The "undo" pass was introduced in LLVM
https://reviews.llvm.org/D121937
to prevent this optimization, but it cannot cover all cases.
Instead of fighting middle end optimizer in BPF backend teach the verifier
about this pattern.
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20240613013815.953-3-alexei.starovoitov@gmail.com
Diffstat (limited to 'kernel/bpf/log.c')
-rw-r--r-- | kernel/bpf/log.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c index 4bd8f17a9f24..3f4ae92e549f 100644 --- a/kernel/bpf/log.c +++ b/kernel/bpf/log.c @@ -708,7 +708,9 @@ static void print_reg_state(struct bpf_verifier_env *env, verbose(env, "%s", btf_type_name(reg->btf, reg->btf_id)); verbose(env, "("); if (reg->id) - verbose_a("id=%d", reg->id); + verbose_a("id=%d", reg->id & ~BPF_ADD_CONST); + if (reg->id & BPF_ADD_CONST) + verbose(env, "%+d", reg->off); if (reg->ref_obj_id) verbose_a("ref_obj_id=%d", reg->ref_obj_id); if (type_is_non_owning_ref(reg->type)) |