Thread (23 messages) 23 messages, 4 authors, 2022-07-27

Re: [PATCH 3/5] ARM: stacktrace: Allow stack trace saving for non-current tasks

From: Li Huafei <hidden>
Date: 2022-07-26 12:08:32
Also in: linux-perf-users, lkml


On 2022/7/26 17:49, Russell King (Oracle) wrote:
On Tue, Jul 26, 2022 at 05:12:39PM +0800, Li Huafei wrote:
quoted

On 2022/7/18 17:07, Linus Walleij wrote:
quoted
On Tue, Jul 12, 2022 at 4:18 AM Li Huafei [off-list ref] wrote:
quoted
The current ARM implementation of save_stack_trace_tsk() does not allow
saving stack trace for non-current tasks, which may limit the scenarios
in which stack_trace_save_tsk() can be used. Like other architectures,
or like ARM's unwind_backtrace(), we can leave it up to the caller to
ensure that the task that needs to be unwound is not running.

Signed-off-by: Li Huafei <redacted>
That sounds good, but:
quoted
        if (tsk != current) {
-#ifdef CONFIG_SMP
-               /*
-                * What guarantees do we have here that 'tsk' is not
-                * running on another CPU?  For now, ignore it as we
-                * can't guarantee we won't explode.
-                */
-               return;
-#else
+               /* task blocked in __switch_to */
The commit text is not consistent with the comment you are removing.

The commit is talking about "non-current" tasks which is one thing,
but the code is avoiding any tasks under SMP because they may be
running on another CPU. So you need to update the commit
message to say something like "non-current or running on another CPU".

If this condition will be checked at call sites in following patches,
then mention
that in the commit as well, so we know the end result is that we do
not break it,
The generic code stack_trace_save_tsk() does not have this check, and by
'caller' I mean the caller of stack_trace_save_tsk(), expecting the
'caller' to ensure that the task is not running. So in effect this check
has been dropped and there is no more guarantee. Sorry for not
clarifying the change here.
Can you prove in every case that the thread we're being asked to unwind
is not running? I don't think you can.

There are things like proc_pid_stack() in procfs and the stack traces
in sysrq-t which have attempted to unwind everything whether it's
running or not.

So no, there is no guarantee that the thread is blocked in
__switch_to().
Yes, I agree.
quoted
But can we assume that the user should know that the stacktrace is
unreliable for a task that is running on another CPU? If not, I should
remove this patch and keep the check.
It's not about "unreliable" stack traces, it's about the unwinder
killing the kernel.

The hint is this:

                frame.fp = thread_saved_fp(tsk);
                frame.sp = thread_saved_sp(tsk);
                frame.lr = 0;           /* recovered from the stack */
                frame.pc = thread_saved_pc(tsk);

These access the context saved by the scheduler when the task is
sleeping. When the thread is running, these saved values will be
the state when the thread last slept. However, with the thread
running, the stack could now contain any data what so ever, and
could change at any moment.
I get it. For example, since the data on the stack is changing,
'*(unsigned long *)fp' could access any illegal address and crash the
kernel.
Whether the unwind-table unwinder is truely safe in such a
situation is unknown - we try to ensure that it won't do anything
stupid, but proving that is a hard task, and we've recently had
issues with the unwinder even without that.

So, allowing this feels like we're opening the door to DoS attacks
from userspace, where userspace sits there reading /proc/*/stack of
some thread running on a different CPU waiting for the kernel to
oops itself, possibly holding a lock, resulting in the system
dying.

These decisions need to be made by architecture code not generic
code, particularly where the method of unwinding is architecture
specific and thus may have criteria defining when its safe to do so.
Thank you for your comments, I'll remove the patch and keep the check.

Thanks,
Huafei

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help