All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Rutland <mark.rutland@arm.com>
To: Ard Biesheuvel <ardb@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org, linux-efi@vger.kernel.org,
	will@kernel.org, catalin.marinas@arm.com
Subject: Re: [PATCH] arm64: efi: Account for the EFI runtime stack in stack unwinder
Date: Fri, 9 Dec 2022 14:37:41 +0000	[thread overview]
Message-ID: <Y5NINaentm954uix@FVFF77S0Q05N> (raw)
In-Reply-To: <20221209133414.3330761-1-ardb@kernel.org>

On Fri, Dec 09, 2022 at 02:34:14PM +0100, Ard Biesheuvel wrote:
> The EFI runtime services run from a dedicated stack now, and so the
> stack unwinder needs to be informed about this.
> 
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---
> 
> I realised while looking into this that comparing current_work() against
> efi_rts_work.work is not sufficient to decide whether current is running
> EFI code, given that the ACPI subsystem will call efi_call_virt_pointer()
> directly.
> 
> So instead, we can check whether the stashed thread stack pointer value
> matches current's thread stack if the EFI runtime stack is currently in
> use:
> 
> #define current_in_efi()                                               \
>        (!preemptible() && spin_is_locked(&efi_rt_lock) &&              \
>         on_task_stack(current, efi_rt_stack_top[-1], 1))

Unless you're overwriting task_struct::stack (which seems scary to me), that
doesn't look right; on_task_stack() checks whether a given base + size is on
the stack allocated for the task (i.e. task_struct::stack + THREAD_SIZE), not
the stack the task is currently using.

I would expect this to be something like:

#define current_in_efi()						\
	(!preemptible() && spin_is_locked(&efi_rt_lock) &&		\
	 stackinfo_on_stack(stackinfo_get_efi(), current_stack_pointer, 1))

... or an inline function given this is sufficiently painful as a macro.

... unless I've confused myself?

FWIW, the patch belows looks good to me!

Mark.

> but this will be folded into the preceding patch, which I am not
> reproducing here.
> 
>  arch/arm64/include/asm/stacktrace.h | 15 +++++++++++++++
>  arch/arm64/kernel/stacktrace.c      | 12 ++++++++++++
>  2 files changed, 27 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
> index 5a0edb064ea478bb..327cdcfcb1db0ad5 100644
> --- a/arch/arm64/include/asm/stacktrace.h
> +++ b/arch/arm64/include/asm/stacktrace.h
> @@ -104,4 +104,19 @@ static inline struct stack_info stackinfo_get_sdei_critical(void)
>  #define stackinfo_get_sdei_critical()	stackinfo_get_unknown()
>  #endif
>  
> +#ifdef CONFIG_EFI
> +extern u64 *efi_rt_stack_top;
> +
> +static inline struct stack_info stackinfo_get_efi(void)
> +{
> +	unsigned long high = (u64)efi_rt_stack_top;
> +	unsigned long low = high - THREAD_SIZE;
> +
> +	return (struct stack_info) {
> +		.low = low,
> +		.high = high,
> +	};
> +}
> +#endif
> +
>  #endif	/* __ASM_STACKTRACE_H */
> diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
> index 634279b3b03d1b07..ee9fd2018cd75ed2 100644
> --- a/arch/arm64/kernel/stacktrace.c
> +++ b/arch/arm64/kernel/stacktrace.c
> @@ -5,6 +5,7 @@
>   * Copyright (C) 2012 ARM Ltd.
>   */
>  #include <linux/kernel.h>
> +#include <linux/efi.h>
>  #include <linux/export.h>
>  #include <linux/ftrace.h>
>  #include <linux/sched.h>
> @@ -12,6 +13,7 @@
>  #include <linux/sched/task_stack.h>
>  #include <linux/stacktrace.h>
>  
> +#include <asm/efi.h>
>  #include <asm/irq.h>
>  #include <asm/stack_pointer.h>
>  #include <asm/stacktrace.h>
> @@ -186,6 +188,13 @@ void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl)
>  			: stackinfo_get_unknown();		\
>  	})
>  
> +#define STACKINFO_EFI						\
> +	({							\
> +		((task == current) && current_in_efi())		\
> +			? stackinfo_get_efi()			\
> +			: stackinfo_get_unknown();		\
> +	})
> +
>  noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry,
>  			      void *cookie, struct task_struct *task,
>  			      struct pt_regs *regs)
> @@ -199,6 +208,9 @@ noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry,
>  #if defined(CONFIG_VMAP_STACK) && defined(CONFIG_ARM_SDE_INTERFACE)
>  		STACKINFO_SDEI(normal),
>  		STACKINFO_SDEI(critical),
> +#endif
> +#ifdef CONFIG_EFI
> +		STACKINFO_EFI,
>  #endif
>  	};
>  	struct unwind_state state = {
> -- 
> 2.35.1
> 

WARNING: multiple messages have this Message-ID (diff)
From: Mark Rutland <mark.rutland@arm.com>
To: Ard Biesheuvel <ardb@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org, linux-efi@vger.kernel.org,
	will@kernel.org, catalin.marinas@arm.com
Subject: Re: [PATCH] arm64: efi: Account for the EFI runtime stack in stack unwinder
Date: Fri, 9 Dec 2022 14:37:41 +0000	[thread overview]
Message-ID: <Y5NINaentm954uix@FVFF77S0Q05N> (raw)
In-Reply-To: <20221209133414.3330761-1-ardb@kernel.org>

On Fri, Dec 09, 2022 at 02:34:14PM +0100, Ard Biesheuvel wrote:
> The EFI runtime services run from a dedicated stack now, and so the
> stack unwinder needs to be informed about this.
> 
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---
> 
> I realised while looking into this that comparing current_work() against
> efi_rts_work.work is not sufficient to decide whether current is running
> EFI code, given that the ACPI subsystem will call efi_call_virt_pointer()
> directly.
> 
> So instead, we can check whether the stashed thread stack pointer value
> matches current's thread stack if the EFI runtime stack is currently in
> use:
> 
> #define current_in_efi()                                               \
>        (!preemptible() && spin_is_locked(&efi_rt_lock) &&              \
>         on_task_stack(current, efi_rt_stack_top[-1], 1))

Unless you're overwriting task_struct::stack (which seems scary to me), that
doesn't look right; on_task_stack() checks whether a given base + size is on
the stack allocated for the task (i.e. task_struct::stack + THREAD_SIZE), not
the stack the task is currently using.

I would expect this to be something like:

#define current_in_efi()						\
	(!preemptible() && spin_is_locked(&efi_rt_lock) &&		\
	 stackinfo_on_stack(stackinfo_get_efi(), current_stack_pointer, 1))

... or an inline function given this is sufficiently painful as a macro.

... unless I've confused myself?

FWIW, the patch belows looks good to me!

Mark.

> but this will be folded into the preceding patch, which I am not
> reproducing here.
> 
>  arch/arm64/include/asm/stacktrace.h | 15 +++++++++++++++
>  arch/arm64/kernel/stacktrace.c      | 12 ++++++++++++
>  2 files changed, 27 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
> index 5a0edb064ea478bb..327cdcfcb1db0ad5 100644
> --- a/arch/arm64/include/asm/stacktrace.h
> +++ b/arch/arm64/include/asm/stacktrace.h
> @@ -104,4 +104,19 @@ static inline struct stack_info stackinfo_get_sdei_critical(void)
>  #define stackinfo_get_sdei_critical()	stackinfo_get_unknown()
>  #endif
>  
> +#ifdef CONFIG_EFI
> +extern u64 *efi_rt_stack_top;
> +
> +static inline struct stack_info stackinfo_get_efi(void)
> +{
> +	unsigned long high = (u64)efi_rt_stack_top;
> +	unsigned long low = high - THREAD_SIZE;
> +
> +	return (struct stack_info) {
> +		.low = low,
> +		.high = high,
> +	};
> +}
> +#endif
> +
>  #endif	/* __ASM_STACKTRACE_H */
> diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
> index 634279b3b03d1b07..ee9fd2018cd75ed2 100644
> --- a/arch/arm64/kernel/stacktrace.c
> +++ b/arch/arm64/kernel/stacktrace.c
> @@ -5,6 +5,7 @@
>   * Copyright (C) 2012 ARM Ltd.
>   */
>  #include <linux/kernel.h>
> +#include <linux/efi.h>
>  #include <linux/export.h>
>  #include <linux/ftrace.h>
>  #include <linux/sched.h>
> @@ -12,6 +13,7 @@
>  #include <linux/sched/task_stack.h>
>  #include <linux/stacktrace.h>
>  
> +#include <asm/efi.h>
>  #include <asm/irq.h>
>  #include <asm/stack_pointer.h>
>  #include <asm/stacktrace.h>
> @@ -186,6 +188,13 @@ void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl)
>  			: stackinfo_get_unknown();		\
>  	})
>  
> +#define STACKINFO_EFI						\
> +	({							\
> +		((task == current) && current_in_efi())		\
> +			? stackinfo_get_efi()			\
> +			: stackinfo_get_unknown();		\
> +	})
> +
>  noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry,
>  			      void *cookie, struct task_struct *task,
>  			      struct pt_regs *regs)
> @@ -199,6 +208,9 @@ noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry,
>  #if defined(CONFIG_VMAP_STACK) && defined(CONFIG_ARM_SDE_INTERFACE)
>  		STACKINFO_SDEI(normal),
>  		STACKINFO_SDEI(critical),
> +#endif
> +#ifdef CONFIG_EFI
> +		STACKINFO_EFI,
>  #endif
>  	};
>  	struct unwind_state state = {
> -- 
> 2.35.1
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2022-12-09 14:37 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-09 13:34 [PATCH] arm64: efi: Account for the EFI runtime stack in stack unwinder Ard Biesheuvel
2022-12-09 13:34 ` Ard Biesheuvel
2022-12-09 14:37 ` Mark Rutland [this message]
2022-12-09 14:37   ` Mark Rutland
2022-12-09 14:46   ` Ard Biesheuvel
2022-12-09 14:46     ` Ard Biesheuvel
2022-12-09 15:00     ` Mark Rutland
2022-12-09 15:00       ` Mark Rutland
2022-12-09 15:10       ` Ard Biesheuvel
2022-12-09 15:10         ` Ard Biesheuvel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Y5NINaentm954uix@FVFF77S0Q05N \
    --to=mark.rutland@arm.com \
    --cc=ardb@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-efi@vger.kernel.org \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.