* [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