Factor out the code that fills the stack with the stackleak poison value
in order to allow architectures to provide a faster implementation.
Acked-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
---
kernel/stackleak.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/kernel/stackleak.c b/kernel/stackleak.c
index c2c33d2202e9..34c9d81eea94 100644
--- a/kernel/stackleak.c
+++ b/kernel/stackleak.c
@@ -70,6 +70,18 @@ late_initcall(stackleak_sysctls_init);
#define skip_erasing() false
#endif /* CONFIG_STACKLEAK_RUNTIME_DISABLE */
+#ifndef __stackleak_poison
+static __always_inline void __stackleak_poison(unsigned long erase_low,
+ unsigned long erase_high,
+ unsigned long poison)
+{
+ while (erase_low < erase_high) {
+ *(unsigned long *)erase_low = poison;
+ erase_low += sizeof(unsigned long);
+ }
+}
+#endif
+
static __always_inline void __stackleak_erase(bool on_task_stack)
{
const unsigned long task_stack_low = stackleak_task_low_bound(current);
@@ -101,10 +113,7 @@ static __always_inline void __stackleak_erase(bool on_task_stack)
else
erase_high = task_stack_high;
- while (erase_low < erase_high) {
- *(unsigned long *)erase_low = STACKLEAK_POISON;
- erase_low += sizeof(unsigned long);
- }
+ __stackleak_poison(erase_low, erase_high, STACKLEAK_POISON);
/* Reset the 'lowest_stack' value for the next syscall */
current->lowest_stack = task_stack_high;
--
2.37.2
On Wed, Apr 05, 2023 at 03:08:40PM +0200, Heiko Carstens wrote:
> Factor out the code that fills the stack with the stackleak poison value
> in order to allow architectures to provide a faster implementation.
>
> Acked-by: Vasily Gorbik <gor@linux.ibm.com>
> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
As on patch 2, it might be nicer to have a noinstr-safe memset64() and use that
directly, but I don't have strong feelings either way, and I'll defer to Kees's
judgement:
Acked-by: Mark Rutland <mark.rutland@arm.com>
Thanks,
Mark.
> ---
> kernel/stackleak.c | 17 +++++++++++++----
> 1 file changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/kernel/stackleak.c b/kernel/stackleak.c
> index c2c33d2202e9..34c9d81eea94 100644
> --- a/kernel/stackleak.c
> +++ b/kernel/stackleak.c
> @@ -70,6 +70,18 @@ late_initcall(stackleak_sysctls_init);
> #define skip_erasing() false
> #endif /* CONFIG_STACKLEAK_RUNTIME_DISABLE */
>
> +#ifndef __stackleak_poison
> +static __always_inline void __stackleak_poison(unsigned long erase_low,
> + unsigned long erase_high,
> + unsigned long poison)
> +{
> + while (erase_low < erase_high) {
> + *(unsigned long *)erase_low = poison;
> + erase_low += sizeof(unsigned long);
> + }
> +}
> +#endif
> +
> static __always_inline void __stackleak_erase(bool on_task_stack)
> {
> const unsigned long task_stack_low = stackleak_task_low_bound(current);
> @@ -101,10 +113,7 @@ static __always_inline void __stackleak_erase(bool on_task_stack)
> else
> erase_high = task_stack_high;
>
> - while (erase_low < erase_high) {
> - *(unsigned long *)erase_low = STACKLEAK_POISON;
> - erase_low += sizeof(unsigned long);
> - }
> + __stackleak_poison(erase_low, erase_high, STACKLEAK_POISON);
>
> /* Reset the 'lowest_stack' value for the next syscall */
> current->lowest_stack = task_stack_high;
> --
> 2.37.2
>
On Wed, Apr 12, 2023 at 10:03:46AM +0100, Mark Rutland wrote: > On Wed, Apr 05, 2023 at 03:08:40PM +0200, Heiko Carstens wrote: > > Factor out the code that fills the stack with the stackleak poison value > > in order to allow architectures to provide a faster implementation. > > > > Acked-by: Vasily Gorbik <gor@linux.ibm.com> > > Signed-off-by: Heiko Carstens <hca@linux.ibm.com> > > As on patch 2, it might be nicer to have a noinstr-safe memset64() and use that > directly, but I don't have strong feelings either way, and I'll defer to Kees's > judgement: Wouldn't that enforce that memset64() wouldn't be allowed to have an own stackframe, since otherwise it would write poison values to it, since we have if (on_task_stack) erase_high = current_stack_pointer; in __stackleak_erase()? That was actually my motiviation to make this s390 optimization an always inline asm. Besides that this wouldn't be a problem for at least s390, since memset64() is an asm function which comes whithout the need for a stackframe, but on the other hand this would add a quite subtle requirement to memset64(), if I'm not mistaken.
On Wed, Apr 12, 2023 at 11:58:07AM +0200, Heiko Carstens wrote: > On Wed, Apr 12, 2023 at 10:03:46AM +0100, Mark Rutland wrote: > > On Wed, Apr 05, 2023 at 03:08:40PM +0200, Heiko Carstens wrote: > > > Factor out the code that fills the stack with the stackleak poison value > > > in order to allow architectures to provide a faster implementation. > > > > > > Acked-by: Vasily Gorbik <gor@linux.ibm.com> > > > Signed-off-by: Heiko Carstens <hca@linux.ibm.com> > > > > As on patch 2, it might be nicer to have a noinstr-safe memset64() and use that > > directly, but I don't have strong feelings either way, and I'll defer to Kees's > > judgement: > > Wouldn't that enforce that memset64() wouldn't be allowed to have an own > stackframe, since otherwise it would write poison values to it, since we > have > > if (on_task_stack) > erase_high = current_stack_pointer; > > in __stackleak_erase()? Yes, sorry -- I was implicitly assuming that a noinstr-safe version would be __always_inline. > That was actually my motiviation to make this s390 optimization an always > inline asm. > > Besides that this wouldn't be a problem for at least s390, since memset64() > is an asm function which comes whithout the need for a stackframe, but on > the other hand this would add a quite subtle requirement to memset64(), if > I'm not mistaken. That's a fair enough justification, I think. Thanks for the details! Thanks, Mark.
© 2016 - 2026 Red Hat, Inc.