Skip to content

Commit 1d25115

Browse files
committed
bpf: Fix state use-after-free on push_stack() err
Without this, `state->speculative` is used after the cleanup cycles in push_stack() or push_async_cb() freed `env->cur_state` (i.e., `state`). Avoid this by relying on the short-circuit logic to only access `state` if the error is recoverable (and make sure it never is after push_*() failed). push_*() callers must always return an error for which error_recoverable_with_nospec(err) is false if push_*() returns NULL, otherwise we try to recover and access the stale `state`. This is only violated by sanitize_ptr_alu(), thus also fix this case to return -ENOMEM. state->speculative does not make sense if the error path of push_*() ran. In that case, `state->speculative && error_recoverable_with_nospec(err)` as a whole should already never evaluate to true (because all cases where push_stack() fails must return -ENOMEM/-EFAULT). As mentioned, this is only violated by the push_stack() call in sanitize_speculative_path() which returns -EACCES without [1] (through REASON_STACK in sanitize_err() after sanitize_ptr_alu()). To fix this, return -ENOMEM for REASON_STACK (which is also the behavior we will have after [1]). Checked that it fixes the syzbot reproducer as expected. [1] https://lore.kernel.org/all/[email protected]/ Fixes: d6f1c85 ("bpf: Fall back to nospec for Spectre v1") Reported-by: [email protected] Reported-by: Eduard Zingerman <[email protected]> Link: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Luis Gerhorst <[email protected]>
1 parent 2d72dd1 commit 1d25115

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

kernel/bpf/verifier.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14229,7 +14229,7 @@ static int sanitize_err(struct bpf_verifier_env *env,
1422914229
case REASON_STACK:
1423014230
verbose(env, "R%d could not be pushed for speculative verification, %s\n",
1423114231
dst, err);
14232-
break;
14232+
return -ENOMEM;
1423314233
default:
1423414234
verbose(env, "verifier internal error: unknown reason (%d)\n",
1423514235
reason);
@@ -19753,7 +19753,7 @@ static int do_check(struct bpf_verifier_env *env)
1975319753
goto process_bpf_exit;
1975419754

1975519755
err = do_check_insn(env, &do_print_state);
19756-
if (state->speculative && error_recoverable_with_nospec(err)) {
19756+
if (error_recoverable_with_nospec(err) && state->speculative) {
1975719757
/* Prevent this speculative path from ever reaching the
1975819758
* insn that would have been unsafe to execute.
1975919759
*/

0 commit comments

Comments
 (0)