* [PATCH 1/1] arm: get task_stack reference before dump_backtrace
[not found] <CGME20260305070534epcas5p378bb22ef9f1a895d7736ed2272c19ec6@epcas5p3.samsung.com>
@ 2026-03-05 7:05 ` Maninder Singh
2026-03-08 23:39 ` Linus Walleij
2026-03-08 23:52 ` Russell King (Oracle)
0 siblings, 2 replies; 5+ messages in thread
From: Maninder Singh @ 2026-03-05 7:05 UTC (permalink / raw)
To: linux, rmk+kernel, bigeasy, peterz, kees, ardb, keithpac, linusw
Cc: linux-arm-kernel, linux-kernel, Maninder Singh
With Support of THREAD_INFO_IN_TASK, stack of task can be
freed earlier than task (even if task's reference is taken),
and it needs separate reference with try_get_task_stack()
before using the stack.
Otherwise if someone calls show_stack() for task, it can oops
the kernel like below: (Tried with normal race of show_stack when
task still exists, but its stack is freed)
8<--- cut here ---
Unable to handle kernel paging request at virtual address f8aebec4 when read
[f8aebec4] *pgd=83c2c811, *pte=00000000, *ppte=00000000
Internal error: Oops: 7 [#1] SMP ARM
..
CPU: 0 UID: 0 PID: 70 Comm: cat Not tainted 7.0.0-rc2-next-20260302+ #26 VOLUNTARY
..
PC is at __read_once_word_nocheck+0x0/0x8
LR is at unwind_frame+0x6b0/0xa90
...
Call trace:
__read_once_word_nocheck from unwind_frame+0x6b0/0xa90
unwind_frame from unwind_backtrace+0x178/0x1e0
unwind_backtrace from show_stack+0x10/0x14
...
ARM64 also takes care of it in dump_backtrace(), so same logic
is added for ARM also.
Fixes: 18ed1c01a7dd ("ARM: smp: Enable THREAD_INFO_IN_TASK")
Signed-off-by: Maninder Singh <maninder1.s@samsung.com>
---
arch/arm/kernel/traps.c | 9 +++++++--
arch/arm/kernel/unwind.c | 10 ++++++++--
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index afbd2ebe5c39..770dcb1dc683 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -221,11 +221,14 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
unsigned int fp, mode;
int ok = 1;
- printk("%sCall trace: ", loglvl);
-
if (!tsk)
tsk = current;
+ if (!try_get_task_stack(tsk))
+ return;
+
+ printk("%sCall trace: ", loglvl);
+
if (regs) {
fp = frame_pointer(regs);
mode = processor_mode(regs);
@@ -249,6 +252,8 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
if (ok)
c_backtrace(fp, mode, loglvl);
+
+ put_task_stack(tsk);
}
#endif
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index c91cb0e1585e..990692714288 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -29,6 +29,7 @@
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/sched/task_stack.h>
#include <asm/stacktrace.h>
#include <asm/traps.h>
@@ -524,13 +525,16 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk,
{
struct stackframe frame;
- printk("%sCall trace: ", loglvl);
-
pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
if (!tsk)
tsk = current;
+ if (!try_get_task_stack(tsk))
+ return;
+
+ printk("%sCall trace: ", loglvl);
+
if (regs) {
arm_get_current_stackframe(regs, &frame);
/* PC might be corrupted, use LR in that case. */
@@ -567,6 +571,8 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk,
break;
dump_backtrace_entry(where, frame.pc, frame.sp - 4, loglvl);
}
+
+ put_task_stack(tsk);
}
struct unwind_table *unwind_table_add(unsigned long start, unsigned long size,
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/1] arm: get task_stack reference before dump_backtrace
2026-03-05 7:05 ` [PATCH 1/1] arm: get task_stack reference before dump_backtrace Maninder Singh
@ 2026-03-08 23:39 ` Linus Walleij
2026-03-08 23:52 ` Russell King (Oracle)
1 sibling, 0 replies; 5+ messages in thread
From: Linus Walleij @ 2026-03-08 23:39 UTC (permalink / raw)
To: Maninder Singh
Cc: linux, rmk+kernel, bigeasy, peterz, kees, ardb, keithpac,
linux-arm-kernel, linux-kernel
On Thu, Mar 5, 2026 at 8:05 AM Maninder Singh <maninder1.s@samsung.com> wrote:
> With Support of THREAD_INFO_IN_TASK, stack of task can be
> freed earlier than task (even if task's reference is taken),
> and it needs separate reference with try_get_task_stack()
> before using the stack.
> Otherwise if someone calls show_stack() for task, it can oops
> the kernel like below: (Tried with normal race of show_stack when
> task still exists, but its stack is freed)
>
> 8<--- cut here ---
> Unable to handle kernel paging request at virtual address f8aebec4 when read
> [f8aebec4] *pgd=83c2c811, *pte=00000000, *ppte=00000000
> Internal error: Oops: 7 [#1] SMP ARM
> ..
> CPU: 0 UID: 0 PID: 70 Comm: cat Not tainted 7.0.0-rc2-next-20260302+ #26 VOLUNTARY
> ..
> PC is at __read_once_word_nocheck+0x0/0x8
> LR is at unwind_frame+0x6b0/0xa90
> ...
> Call trace:
> __read_once_word_nocheck from unwind_frame+0x6b0/0xa90
> unwind_frame from unwind_backtrace+0x178/0x1e0
> unwind_backtrace from show_stack+0x10/0x14
> ...
>
> ARM64 also takes care of it in dump_backtrace(), so same logic
> is added for ARM also.
>
> Fixes: 18ed1c01a7dd ("ARM: smp: Enable THREAD_INFO_IN_TASK")
> Signed-off-by: Maninder Singh <maninder1.s@samsung.com>
Ard B should review this but it looks right to me:
Acked-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/1] arm: get task_stack reference before dump_backtrace
2026-03-05 7:05 ` [PATCH 1/1] arm: get task_stack reference before dump_backtrace Maninder Singh
2026-03-08 23:39 ` Linus Walleij
@ 2026-03-08 23:52 ` Russell King (Oracle)
2026-03-09 5:53 ` Maninder Singh
1 sibling, 1 reply; 5+ messages in thread
From: Russell King (Oracle) @ 2026-03-08 23:52 UTC (permalink / raw)
To: Maninder Singh
Cc: bigeasy, peterz, kees, ardb, keithpac, linusw, linux-arm-kernel,
linux-kernel
On Thu, Mar 05, 2026 at 12:35:27PM +0530, Maninder Singh wrote:
> With Support of THREAD_INFO_IN_TASK, stack of task can be
> freed earlier than task (even if task's reference is taken),
> and it needs separate reference with try_get_task_stack()
> before using the stack.
> Otherwise if someone calls show_stack() for task, it can oops
> the kernel like below: (Tried with normal race of show_stack when
> task still exists, but its stack is freed)
Looking at x86, it also has THREAD_INFO_IN_TASK, but I see nothing like
this in show_stack(). How come x86 isn't similarly buggy?
>
> 8<--- cut here ---
> Unable to handle kernel paging request at virtual address f8aebec4 when read
> [f8aebec4] *pgd=83c2c811, *pte=00000000, *ppte=00000000
> Internal error: Oops: 7 [#1] SMP ARM
> ..
> CPU: 0 UID: 0 PID: 70 Comm: cat Not tainted 7.0.0-rc2-next-20260302+ #26 VOLUNTARY
> ..
> PC is at __read_once_word_nocheck+0x0/0x8
> LR is at unwind_frame+0x6b0/0xa90
> ...
> Call trace:
> __read_once_word_nocheck from unwind_frame+0x6b0/0xa90
> unwind_frame from unwind_backtrace+0x178/0x1e0
> unwind_backtrace from show_stack+0x10/0x14
> ...
"otherwise if someone calls show_stack() for task" ... and the stack
trace given stops at show_stack() and doesn't show the "someone".
I'd like to know _how_ this happens, and why ARM64 and now 32-bit ARM
are different from x86.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 5+ messages in thread
* RE: [PATCH 1/1] arm: get task_stack reference before dump_backtrace
2026-03-08 23:52 ` Russell King (Oracle)
@ 2026-03-09 5:53 ` Maninder Singh
2026-03-09 5:55 ` Maninder Singh
0 siblings, 1 reply; 5+ messages in thread
From: Maninder Singh @ 2026-03-09 5:53 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: bigeasy@linutronix.de, peterz@infradead.org, kees@kernel.org,
ardb@kernel.org, keithpac@amazon.com, linusw@kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Hi,
>> With Support of THREAD_INFO_IN_TASK, stack of task can be
>> freed earlier than task (even if task's reference is taken),
>> and it needs separate reference with try_get_task_stack()
>> before using the stack.
>> Otherwise if someone calls show_stack() for task, it can oops
>> the kernel like below: (Tried with normal race of show_stack when
>> task still exists, but its stack is freed)
>
> Looking at x86, it also has THREAD_INFO_IN_TASK, but I see nothing like
> this in show_stack(). How come x86 isn't similarly buggy?
I think x86 also has same issue, some of other architectures which supports
THREAD_INFO_IN_TASK has added try_get_task_stack() in show_stack(), but not *all*
8 2293 arch/powerpc/kernel/process.c <<show_stack>>
if (!try_get_task_stack(tsk))
4 488 arch/arm64/kernel/stacktrace.c <<dump_backtrace>>
if (!try_get_task_stack(tsk))
>>
>> ...
>
>"otherwise if someone calls show_stack() for task" ... and the stack
>trace given stops at show_stack() and doesn't show the "someone".
>
>I'd like to know _how_ this happens, and why ARM64 and now 32-bit ARM
>are different from x86.
I tried to simulate same thing on x86_64, it is also crashing.
Just a dummy code to save task_struct to reproduce the race:
+ rcu_read_lock();
+ for_each_process(p) {
+ if (!strcmp(p->comm, "sleep")) {
+ check_task = p;
+ get_task_struct(p);
+ pr_emerg("get done for %s %d\n", p->comm, p->pid);
+ }
+ }
+ rcu_read_unlock();
// in mean time here sleep binary will be exited.
+ show_stack(check_task, NULL, KERN_EMERG);
//OOPs
/ # cat /proc/meminfo
[ 49.885891] Call Trace:
[ 49.887151] BUG: unable to handle page fault for address: ffffb57400213de8
[ 49.887563] #PF: supervisor read access in kernel mode
[ 49.887737] #PF: error_code(0x0000) - not-present page
[ 49.887999] PGD 1000067 P4D 1000067 PUD 113b067 PMD 1bcb067 PTE 0
[ 49.888588] Oops: Oops: 0000 [#1] SMP NOPTI
[ 49.889329] CPU: 0 UID: 0 PID: 68 Comm: cat Not tainted 7.0.0-rc2-next-20260302-00003-gb7e059f3a5ae-dirty #49 PREEMPT(lazy)
[ 49.889789] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[ 49.890204] RIP: 0010:__unwind_start+0x118/0x1c0
[ 49.890471] Code: 75 28 48 8d b8 ff 0f 00 00 48 81 e7 00 f0 ff ff e8 ed ce fb ff 85 c0 75 ae eb 9c 48 8b 86 08 0c 00 00 48 8d 78 38 48 89 7d 48 <48> 8b 50 28 48 89 55 50 48 8b 4c
[ 49.891163] RSP: 0018:ffffb57400207b00 EFLAGS: 00000246
[ 49.891385] RAX: ffffb57400213dc0 RBX: ffffb57400213dc0 RCX: 0000000000000000
[ 49.891615] RDX: 0000000000000000 RSI: ffff99ec41b6cc40 RDI: ffffb57400213df8
[ 49.891867] RBP: ffffb57400207b68 R08: ffffffffae53e908 R09: 00000000ffffdfff
[ 49.892101] R10: ffffffffae45e920 R11: ffffffffae50e920 R12: 0000000000000000
[ 49.892332] R13: ffff99ec41b6f298 R14: ffffb57400207b68 R15: ffffffffae24615e
[ 49.892670] FS: 00000000081ed3c0(0000) GS:ffff99ec9887b000(0000) knlGS:0000000000000000
[ 49.892950] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 49.893147] CR2: ffffb57400213de8 CR3: 0000000001d2d000 CR4: 00000000000006f0
[ 49.893485] Call Trace:
[ 49.893700] <TASK>
[ 49.893810] __show_trace_log_lvl+0x31f/0x360
[ 49.893988] ? mas_store_prealloc+0x99/0x2c0
[ 49.894169] meminfo_proc_show+0xdd/0x9a0
[ 49.894312] ? seq_open+0x3b/0x60
[ 49.894435] ? __pfx_meminfo_proc_show+0x10/0x10
[ 49.894568] ? file_ra_state_init+0x10/0x30
[ 49.894731] ? __pte_offset_map+0x16/0xd0
[ 49.894871] ? seq_read_iter+0x38e/0x4b0
[ 49.895004] seq_read_iter+0x109/0x4b0
[ 49.895125] copy_splice_read+0x18f/0x330
[ 49.895272] splice_direct_to_actor+0xb4/0x250
[ 49.895420] ? __pfx_direct_splice_actor+0x10/0x10
[ 49.895582] do_splice_direct+0x71/0xb0
[ 49.895730] ? __pfx_direct_file_splice_eof+0x10/0x10
[ 49.895908] do_sendfile+0x361/0x420
[ 49.896049] do_syscall_64+0xf1/0x520
[ 49.896197] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 49.896375] RIP: 0033:0x4a8d3e
[ 49.896634] Code: c3 0f 1f 00 4c 89 d2 4c 89 c6 e9 fd fd ff ff 0f 1f 44 00 00 31 c0 c3 0f 1f 44 00 00 f3 0f 1e fa 49 89 ca b8 28 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c8
[ 49.897221] RSP: 002b:00007ffe75342478 EFLAGS: 00000246 ORIG_RAX: 0000000000000028
[ 49.897486] RAX: ffffffffffffffda RBX: 0000000001000000 RCX: 00000000004a8d3e
[ 49.897747] RDX: 0000000000000000 RSI: 0000000000000003 RDI: 0000000000000001
[ 49.897977] RBP: 0000000000000003 R08: 0000000000000001 R09: 0000000000000000
[ 49.898221] R10: 0000000001000000 R11: 0000000000000246 R12: 0000000000000003
[ 49.898489] R13: 0000000000000001 R14: 0000000000000000 R15: 0000000000000001
[ 49.898764] </TASK>
[ 49.898898] Modules linked in:
[ 49.899259] CR2: ffffb57400213de8
[ 49.899762] ---[ end trace 0000000000000000 ]---
[ 49.900187] RIP: 0010:__unwind_start+0x118/0x1c0
[ 49.900391] Code: 75 28 48 8d b8 ff 0f 00 00 48 81 e7 00 f0 ff ff e8 ed ce fb ff 85 c0 75 ae eb 9c 48 8b 86 08 0c 00 00 48 8d 78 38 48 89 7d 48 <48> 8b 50 28 48 89 55 50 48 8b 4c
[ 49.901001] RSP: 0018:ffffb57400207b00 EFLAGS: 00000246
[ 49.901188] RAX: ffffb57400213dc0 RBX: ffffb57400213dc0 RCX: 0000000000000000
[ 49.901431] RDX: 0000000000000000 RSI: ffff99ec41b6cc40 RDI: ffffb57400213df8
[ 49.901680] RBP: ffffb57400207b68 R08: ffffffffae53e908 R09: 00000000ffffdfff
[ 49.901918] R10: ffffffffae45e920 R11: ffffffffae50e920 R12: 0000000000000000
[ 49.902182] R13: ffff99ec41b6f298 R14: ffffb57400207b68 R15: ffffffffae24615e
[ 49.902417] FS: 00000000081ed3c0(0000) GS:ffff99ec9887b000(0000) knlGS:0000000000000000
[ 49.902694] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 49.902896] CR2: ffffb57400213de8 CR3: 0000000001d2d000 CR4: 00000000000006f0
So It has to be same way for all archs, as mentioned in Help of THREAD_INFO_IN_TASK
config THREAD_INFO_IN_TASK
bool
help
Select this to move thread_info off the stack into task_struct. To
make this work, an arch will need to remove all thread_info fields
except flags and fix any runtime bugs.
One subtle change that will be needed is to use try_get_task_stack()
and put_task_stack() in save_thread_stack_tsk() and save_thread_stack_tsk().
alongwith save_thread_stack_tsk and save_thread_stack_tsk, same thing shall be done for show_stack also.
Thanks & Regards,
Maninder Singh
^ permalink raw reply [flat|nested] 5+ messages in thread
* RE: [PATCH 1/1] arm: get task_stack reference before dump_backtrace
2026-03-09 5:53 ` Maninder Singh
@ 2026-03-09 5:55 ` Maninder Singh
0 siblings, 0 replies; 5+ messages in thread
From: Maninder Singh @ 2026-03-09 5:55 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: bigeasy@linutronix.de, peterz@infradead.org, kees@kernel.org,
ardb@kernel.org, keithpac@amazon.com, linusw@kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
> So It has to be same way for all archs, as mentioned in Help of THREAD_INFO_IN_TASK
>
> config THREAD_INFO_IN_TASK
> bool
> help
> Select this to move thread_info off the stack into task_struct. To
> make this work, an arch will need to remove all thread_info fields
> except flags and fix any runtime bugs.
>
> One subtle change that will be needed is to use try_get_task_stack()
> and put_task_stack() in save_thread_stack_tsk() and save_thread_stack_tsk().
>
> alongwith save_thread_stack_tsk and save_thread_stack_tsk, same thing shall be done for show_stack also.
Typo error:
config THREAD_INFO_IN_TASK
bool
help
Select this to move thread_info off the stack into task_struct. To
make this work, an arch will need to remove all thread_info fields
except flags and fix any runtime bugs.
One subtle change that will be needed is to use try_get_task_stack()
and put_task_stack() in save_thread_stack_tsk() and get_wchan().
alongwith save_thread_stack_tsk() and get_wchan(), same thing shall be done for show_stack() also.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-03-09 5:56 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CGME20260305070534epcas5p378bb22ef9f1a895d7736ed2272c19ec6@epcas5p3.samsung.com>
2026-03-05 7:05 ` [PATCH 1/1] arm: get task_stack reference before dump_backtrace Maninder Singh
2026-03-08 23:39 ` Linus Walleij
2026-03-08 23:52 ` Russell King (Oracle)
2026-03-09 5:53 ` Maninder Singh
2026-03-09 5:55 ` Maninder Singh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox