FAILED: patch "[PATCH] bpf,fork: wipe ->bpf_storage before bailouts that access it" failed to apply to 5.15-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 9b51a6155d14389876916726430da30eabb1d4ed
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026072029-trend-escalator-b641@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 9b51a6155d14389876916726430da30eabb1d4ed Mon Sep 17 00:00:00 2001
From: Jann Horn <[email protected]>
Date: Fri, 26 Jun 2026 17:52:52 +0200
Subject: [PATCH] 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_destroyIn 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.
kernel/fork.c +5 -4
@@ -1009,6 +1009,11 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) tsk->mm_cid.active =0 ;INIT_HLIST_NODE (&tsk->mm_cid.node);#endif + +#ifdef CONFIG_BPF_SYSCALL +RCU_INIT_POINTER (tsk->bpf_storage,NULL ); + tsk->bpf_ctx =NULL ; +#endif return tsk; free_stack:
@@ -2247,10 +2252,6 @@ __latent_entropy struct task_struct *copy_process( p->sequential_io =0 ; p->sequential_io_avg =0 ;#endif -#ifdef CONFIG_BPF_SYSCALL -RCU_INIT_POINTER (p->bpf_storage,NULL ); - p->bpf_ctx =NULL ; -#endif unwind_task_init (p);
Sasha Levin
maintainerPATCH 1/1 bpf,fork: wipe ->bpf_storage before bailouts that access it
From: Jann Horn <[email protected]>
[ Upstream commit 9b51a6155d14389876916726430da30eabb1d4ed ]
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_destroyIn 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.
--- kernel/fork.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
kernel/fork.c +5 -4
@@ -983,6 +983,11 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)#ifdef CONFIG_MEMCG tsk->active_memcg =NULL ;#endif + +#ifdef CONFIG_BPF_SYSCALL +RCU_INIT_POINTER (tsk->bpf_storage,NULL ); + tsk->bpf_ctx =NULL ; +#endif return tsk; free_stack:
@@ -2252,10 +2257,6 @@ static __latent_entropy struct task_struct *copy_process( p->sequential_io =0 ; p->sequential_io_avg =0 ;#endif -#ifdef CONFIG_BPF_SYSCALL -RCU_INIT_POINTER (p->bpf_storage,NULL ); - p->bpf_ctx =NULL ; -#endif /* Perform scheduler related setup. Assign this task to a CPU. */ retval =sched_fork (clone_flags, p);
Signature · 1 line
2.53.0