Skip to content

Commit 18644ce

Browse files
Alexei Starovoitovborkmann
authored andcommitted
bpf: Fix use-after-free in fmod_ret check
Fix the following issue: [ 436.749342] BUG: KASAN: use-after-free in bpf_trampoline_put+0x39/0x2a0 [ 436.749995] Write of size 4 at addr ffff8881ef38b8a0 by task kworker/3:5/2243 [ 436.750712] [ 436.752677] Workqueue: events bpf_prog_free_deferred [ 436.753183] Call Trace: [ 436.756483] bpf_trampoline_put+0x39/0x2a0 [ 436.756904] bpf_prog_free_deferred+0x16d/0x3d0 [ 436.757377] process_one_work+0x94a/0x15b0 [ 436.761969] [ 436.762130] Allocated by task 2529: [ 436.763323] bpf_trampoline_lookup+0x136/0x540 [ 436.763776] bpf_check+0x2872/0xa0a8 [ 436.764144] bpf_prog_load+0xb6f/0x1350 [ 436.764539] __do_sys_bpf+0x16d7/0x3720 [ 436.765825] [ 436.765988] Freed by task 2529: [ 436.767084] kfree+0xc6/0x280 [ 436.767397] bpf_trampoline_put+0x1fd/0x2a0 [ 436.767826] bpf_check+0x6832/0xa0a8 [ 436.768197] bpf_prog_load+0xb6f/0x1350 [ 436.768594] __do_sys_bpf+0x16d7/0x3720 prog->aux->trampoline = tr should be set only when prog is valid. Otherwise prog freeing will try to put trampoline via prog->aux->trampoline, but it may not point to a valid trampoline. Fixes: 6ba43b7 ("bpf: Attachment verification for BPF_MODIFY_RETURN") Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: KP Singh <kpsingh@google.com> Link: https://lore.kernel.org/bpf/20200529043839.15824-2-alexei.starovoitov@gmail.com
1 parent d195b1d commit 18644ce

File tree

1 file changed

+11
-13
lines changed

1 file changed

+11
-13
lines changed

kernel/bpf/verifier.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10428,22 +10428,13 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env)
1042810428
}
1042910429
#define SECURITY_PREFIX "security_"
1043010430

10431-
static int check_attach_modify_return(struct bpf_verifier_env *env)
10431+
static int check_attach_modify_return(struct bpf_prog *prog, unsigned long addr)
1043210432
{
10433-
struct bpf_prog *prog = env->prog;
10434-
unsigned long addr = (unsigned long) prog->aux->trampoline->func.addr;
10435-
10436-
/* This is expected to be cleaned up in the future with the KRSI effort
10437-
* introducing the LSM_HOOK macro for cleaning up lsm_hooks.h.
10438-
*/
1043910433
if (within_error_injection_list(addr) ||
1044010434
!strncmp(SECURITY_PREFIX, prog->aux->attach_func_name,
1044110435
sizeof(SECURITY_PREFIX) - 1))
1044210436
return 0;
1044310437

10444-
verbose(env, "fmod_ret attach_btf_id %u (%s) is not modifiable\n",
10445-
prog->aux->attach_btf_id, prog->aux->attach_func_name);
10446-
1044710438
return -EINVAL;
1044810439
}
1044910440

@@ -10654,11 +10645,18 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
1065410645
goto out;
1065510646
}
1065610647
}
10648+
10649+
if (prog->expected_attach_type == BPF_MODIFY_RETURN) {
10650+
ret = check_attach_modify_return(prog, addr);
10651+
if (ret)
10652+
verbose(env, "%s() is not modifiable\n",
10653+
prog->aux->attach_func_name);
10654+
}
10655+
10656+
if (ret)
10657+
goto out;
1065710658
tr->func.addr = (void *)addr;
1065810659
prog->aux->trampoline = tr;
10659-
10660-
if (prog->expected_attach_type == BPF_MODIFY_RETURN)
10661-
ret = check_attach_modify_return(env);
1066210660
out:
1066310661
mutex_unlock(&tr->mutex);
1066410662
if (ret)

0 commit comments

Comments
 (0)