mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 01:32:21 +02:00
bpf,fork: wipe ->bpf_storage before bailouts that access it
Currently, copy_process() can bail out to free_task() before p->bpf_storage
has been initialized, with this call graph (shown here for the
!CONFIG_MEMCG case):
copy_process
dup_task_struct
arch_dup_task_struct
[copies the entire task_struct, including ->bpf_storage member]
[RLIMIT_NPROC check fails]
delayed_free_task
free_task
bpf_task_storage_free
rcu_dereference(task->bpf_storage)
bpf_local_storage_destroy
In this case, the nascent task's ->bpf_storage member that
bpf_local_storage_destroy() operates on is a plain copy of the parent's
->bpf_storage pointer, not a real initialized pointer.
This leads to badness (kernel hangs, UAF).
This is reachable as long as the process calling fork() has been inserted
into a task storage map.
Cc: stable@kernel.org
Fixes: a10787e6d5 ("bpf: Enable task local storage for tracing programs")
Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
This commit is contained in:
parent
26490a375c
commit
9b51a6155d
|
|
@ -1009,6 +1009,11 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
|
||||||
tsk->mm_cid.active = 0;
|
tsk->mm_cid.active = 0;
|
||||||
INIT_HLIST_NODE(&tsk->mm_cid.node);
|
INIT_HLIST_NODE(&tsk->mm_cid.node);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_BPF_SYSCALL
|
||||||
|
RCU_INIT_POINTER(tsk->bpf_storage, NULL);
|
||||||
|
tsk->bpf_ctx = NULL;
|
||||||
|
#endif
|
||||||
return tsk;
|
return tsk;
|
||||||
|
|
||||||
free_stack:
|
free_stack:
|
||||||
|
|
@ -2247,10 +2252,6 @@ __latent_entropy struct task_struct *copy_process(
|
||||||
p->sequential_io = 0;
|
p->sequential_io = 0;
|
||||||
p->sequential_io_avg = 0;
|
p->sequential_io_avg = 0;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_BPF_SYSCALL
|
|
||||||
RCU_INIT_POINTER(p->bpf_storage, NULL);
|
|
||||||
p->bpf_ctx = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unwind_task_init(p);
|
unwind_task_init(p);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user