From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 36280CCF2D9 for ; Mon, 19 Jan 2026 10:24:03 +0000 (UTC) Received: from boromir.ozlabs.org (localhost [127.0.0.1]) by lists.ozlabs.org (Postfix) with ESMTP id 4dvmlP4l36z2xSZ; Mon, 19 Jan 2026 21:24:01 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; arc=none smtp.remote-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=lists.ozlabs.org; s=201707; t=1768818241; cv=none; b=SJBoJsy+v0NKAKpfjeERNANOZ0ZYi9kl2lvnDthrNA/iinldQJqFjOyDvkmZ2zzqO33/BvccZQxRVal9OMxyeQEuI6Y42ztUfFG7tNJtqWHhKhSL0kbIFzXpZzC/eCBBgDMrFr45PrVZe9XaIZHlJ4oAcgHsJki8KZqvoBFTmHCOT0aKGwj309ifWaPC0/aEbQWCUi8WgzKYA6er54d82YNBnzcL7AOEUz2e08omX1ViLBnPpVhR3zzCF159hgR198V4ROoBONl8kOaLgwDnsfBCL2T1eos8OF0VVbe0Kn6T1KZvrNfoJRnL22VR5V0yxobauvyZW8N+Qusd5EyWGw== ARC-Message-Signature: i=1; a=rsa-sha256; d=lists.ozlabs.org; s=201707; t=1768818241; c=relaxed/relaxed; bh=6rGknulicpb/N5ZHwBgsBvsJXwGZS09gxBTT+qK+3Ww=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=fDRQdTklfxdGjImVmyxsNVv3d0KoLL0yAKH/s55KesXZ+3+jQE1dFcv8Zzdc9KWJD7zB7GvD9Y2j3juC0Y0VZ+R4Me2qOxTSgcHR0v5+z4bQpTBr7XMePzhkF/a1+IYGDblMxxzgeObH0dem4dYBgv9E8q7H4CUQ1CCJhU/o6+xUBKApGcnKsPGSfvcwEwfC17PE3+DT01px3ugpiCdTwATstyoEWFtOOHP/bG9/EdAE6/0K5CyZhEkRDukvX1DkYW7EgIMOZKxqd/jr0wqZNMiH3jeDRBK9Y+Ypmbt9dOhjlQI7kwVGY0+oidoXkEsAcrArWE92e6LlSuQlSZsdVg== ARC-Authentication-Results: i=1; lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass (client-ip=217.140.110.172; helo=foss.arm.com; envelope-from=mark.rutland@arm.com; receiver=lists.ozlabs.org) smtp.mailfrom=arm.com Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=arm.com (client-ip=217.140.110.172; helo=foss.arm.com; envelope-from=mark.rutland@arm.com; receiver=lists.ozlabs.org) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lists.ozlabs.org (Postfix) with ESMTP id 4dvmlN2RTnz2xHW for ; Mon, 19 Jan 2026 21:23:58 +1100 (AEDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9ABCC1517; Mon, 19 Jan 2026 02:23:18 -0800 (PST) Received: from J2N7QTR9R3 (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2614E3F632; Mon, 19 Jan 2026 02:23:19 -0800 (PST) Date: Mon, 19 Jan 2026 10:23:14 +0000 From: Mark Rutland To: Ryan Roberts Cc: Catalin Marinas , Will Deacon , Huacai Chen , Madhavan Srinivasan , Michael Ellerman , Paul Walmsley , Palmer Dabbelt , Albert Ou , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , Kees Cook , "Gustavo A. R. Silva" , Arnd Bergmann , "Jason A. Donenfeld" , Ard Biesheuvel , Jeremy Linton , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, loongarch@lists.linux.dev, linuxppc-dev@lists.ozlabs.org, linux-riscv@lists.infradead.org, linux-s390@vger.kernel.org, linux-hardening@vger.kernel.org, stable@vger.kernel.org Subject: Re: [PATCH v3 1/3] randomize_kstack: Maintain kstack_offset per task Message-ID: References: <20260102131156.3265118-1-ryan.roberts@arm.com> <20260102131156.3265118-2-ryan.roberts@arm.com> X-Mailing-List: linuxppc-dev@lists.ozlabs.org List-Id: List-Help: List-Owner: List-Post: List-Archive: , List-Subscribe: , , List-Unsubscribe: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20260102131156.3265118-2-ryan.roberts@arm.com> On Fri, Jan 02, 2026 at 01:11:52PM +0000, Ryan Roberts wrote: > kstack_offset was previously maintained per-cpu, but this caused a > couple of issues. So let's instead make it per-task. > > Issue 1: add_random_kstack_offset() and choose_random_kstack_offset() > expected and required to be called with interrupts and preemption > disabled so that it could manipulate per-cpu state. But arm64, loongarch > and risc-v are calling them with interrupts and preemption enabled. I > don't _think_ this causes any functional issues, but it's certainly > unexpected and could lead to manipulating the wrong cpu's state, which > could cause a minor performance degradation due to bouncing the cache > lines. By maintaining the state per-task those functions can safely be > called in preemptible context. > > Issue 2: add_random_kstack_offset() is called before executing the > syscall and expands the stack using a previously chosen rnadom offset. > choose_random_kstack_offset() is called after executing the syscall and > chooses and stores a new random offset for the next syscall. With > per-cpu storage for this offset, an attacker could force cpu migration > during the execution of the syscall and prevent the offset from being > updated for the original cpu such that it is predictable for the next > syscall on that cpu. By maintaining the state per-task, this problem > goes away because the per-task random offset is updated after the > syscall regardless of which cpu it is executing on. > > Fixes: 39218ff4c625 ("stack: Optionally randomize kernel stack offset each syscall") > Closes: https://lore.kernel.org/all/dd8c37bc-795f-4c7a-9086-69e584d8ab24@arm.com/ > Cc: stable@vger.kernel.org > Signed-off-by: Ryan Roberts Acked-by: Mark Rutland Mark. > --- > include/linux/randomize_kstack.h | 26 +++++++++++++++----------- > include/linux/sched.h | 4 ++++ > init/main.c | 1 - > kernel/fork.c | 2 ++ > 4 files changed, 21 insertions(+), 12 deletions(-) > > diff --git a/include/linux/randomize_kstack.h b/include/linux/randomize_kstack.h > index 1d982dbdd0d0..5d3916ca747c 100644 > --- a/include/linux/randomize_kstack.h > +++ b/include/linux/randomize_kstack.h > @@ -9,7 +9,6 @@ > > DECLARE_STATIC_KEY_MAYBE(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, > randomize_kstack_offset); > -DECLARE_PER_CPU(u32, kstack_offset); > > /* > * Do not use this anywhere else in the kernel. This is used here because > @@ -50,15 +49,14 @@ DECLARE_PER_CPU(u32, kstack_offset); > * add_random_kstack_offset - Increase stack utilization by previously > * chosen random offset > * > - * This should be used in the syscall entry path when interrupts and > - * preempt are disabled, and after user registers have been stored to > - * the stack. For testing the resulting entropy, please see: > - * tools/testing/selftests/lkdtm/stack-entropy.sh > + * This should be used in the syscall entry path after user registers have been > + * stored to the stack. Preemption may be enabled. For testing the resulting > + * entropy, please see: tools/testing/selftests/lkdtm/stack-entropy.sh > */ > #define add_random_kstack_offset() do { \ > if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \ > &randomize_kstack_offset)) { \ > - u32 offset = raw_cpu_read(kstack_offset); \ > + u32 offset = current->kstack_offset; \ > u8 *ptr = __kstack_alloca(KSTACK_OFFSET_MAX(offset)); \ > /* Keep allocation even after "ptr" loses scope. */ \ > asm volatile("" :: "r"(ptr) : "memory"); \ > @@ -69,9 +67,9 @@ DECLARE_PER_CPU(u32, kstack_offset); > * choose_random_kstack_offset - Choose the random offset for the next > * add_random_kstack_offset() > * > - * This should only be used during syscall exit when interrupts and > - * preempt are disabled. This position in the syscall flow is done to > - * frustrate attacks from userspace attempting to learn the next offset: > + * This should only be used during syscall exit. Preemption may be enabled. This > + * position in the syscall flow is done to frustrate attacks from userspace > + * attempting to learn the next offset: > * - Maximize the timing uncertainty visible from userspace: if the > * offset is chosen at syscall entry, userspace has much more control > * over the timing between choosing offsets. "How long will we be in > @@ -85,14 +83,20 @@ DECLARE_PER_CPU(u32, kstack_offset); > #define choose_random_kstack_offset(rand) do { \ > if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \ > &randomize_kstack_offset)) { \ > - u32 offset = raw_cpu_read(kstack_offset); \ > + u32 offset = current->kstack_offset; \ > offset = ror32(offset, 5) ^ (rand); \ > - raw_cpu_write(kstack_offset, offset); \ > + current->kstack_offset = offset; \ > } \ > } while (0) > + > +static inline void random_kstack_task_init(struct task_struct *tsk) > +{ > + tsk->kstack_offset = 0; > +} > #else /* CONFIG_RANDOMIZE_KSTACK_OFFSET */ > #define add_random_kstack_offset() do { } while (0) > #define choose_random_kstack_offset(rand) do { } while (0) > +#define random_kstack_task_init(tsk) do { } while (0) > #endif /* CONFIG_RANDOMIZE_KSTACK_OFFSET */ > > #endif > diff --git a/include/linux/sched.h b/include/linux/sched.h > index d395f2810fac..9e0080ed1484 100644 > --- a/include/linux/sched.h > +++ b/include/linux/sched.h > @@ -1591,6 +1591,10 @@ struct task_struct { > unsigned long prev_lowest_stack; > #endif > > +#ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET > + u32 kstack_offset; > +#endif > + > #ifdef CONFIG_X86_MCE > void __user *mce_vaddr; > __u64 mce_kflags; > diff --git a/init/main.c b/init/main.c > index b84818ad9685..27fcbbde933e 100644 > --- a/init/main.c > +++ b/init/main.c > @@ -830,7 +830,6 @@ static inline void initcall_debug_enable(void) > #ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET > DEFINE_STATIC_KEY_MAYBE_RO(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, > randomize_kstack_offset); > -DEFINE_PER_CPU(u32, kstack_offset); > > static int __init early_randomize_kstack_offset(char *buf) > { > diff --git a/kernel/fork.c b/kernel/fork.c > index b1f3915d5f8e..b061e1edbc43 100644 > --- a/kernel/fork.c > +++ b/kernel/fork.c > @@ -95,6 +95,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -2231,6 +2232,7 @@ __latent_entropy struct task_struct *copy_process( > if (retval) > goto bad_fork_cleanup_io; > > + random_kstack_task_init(p); > stackleak_task_init(p); > > if (pid != &init_struct_pid) { > -- > 2.43.0 >