]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
bpf: Fix a kernel verifier crash in stacksafe()
authorYonghong Song <yonghong.song@linux.dev>
Mon, 12 Aug 2024 21:48:47 +0000 (14:48 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 13 Aug 2024 01:09:48 +0000 (18:09 -0700)
Daniel Hodges reported a kernel verifier crash when playing with sched-ext.
Further investigation shows that the crash is due to invalid memory access
in stacksafe(). More specifically, it is the following code:

    if (exact != NOT_EXACT &&
        old->stack[spi].slot_type[i % BPF_REG_SIZE] !=
        cur->stack[spi].slot_type[i % BPF_REG_SIZE])
            return false;

The 'i' iterates old->allocated_stack.
If cur->allocated_stack < old->allocated_stack the out-of-bound
access will happen.

To fix the issue add 'i >= cur->allocated_stack' check such that if
the condition is true, stacksafe() should fail. Otherwise,
cur->stack[spi].slot_type[i % BPF_REG_SIZE] memory access is legal.

Fixes: 2793a8b015f7 ("bpf: exact states comparison for iterator convergence checks")
Cc: Eduard Zingerman <eddyz87@gmail.com>
Reported-by: Daniel Hodges <hodgesd@meta.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20240812214847.213612-1-yonghong.song@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c

index 4cb5441ad75fc5e0bec630d4f527a21b722cb874..d8520095ca030e1b578a5f3d329a4536e1183516 100644 (file)
@@ -16884,8 +16884,9 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old,
                spi = i / BPF_REG_SIZE;
 
                if (exact != NOT_EXACT &&
-                   old->stack[spi].slot_type[i % BPF_REG_SIZE] !=
-                   cur->stack[spi].slot_type[i % BPF_REG_SIZE])
+                   (i >= cur->allocated_stack ||
+                    old->stack[spi].slot_type[i % BPF_REG_SIZE] !=
+                    cur->stack[spi].slot_type[i % BPF_REG_SIZE]))
                        return false;
 
                if (!(old->stack[spi].spilled_ptr.live & REG_LIVE_READ)