Re: [PATCH v2] sched: move stack_canary to the start of the randomizable region

Charles Mirabile <[email protected]>
Newsgroups org.infradead.lists.linux-riscv,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Hi Ruidong, Valentin, (+ copying in RISC-V list/maintainers)—

On Tue, May 12, 2026 at 06:16:43PM +0200, Valentin Schneider wrote:
> On 09/05/26 11:50, Ruidong Tian wrote:
> > task_struct keeps growing over time.  On architectures that compute the
> > per-task stack canary offset from asm-offsets.h and pass it to the
> > compiler via -mstack-protector-guard-offset=, this growth eventually
> > pushes stack_canary beyond what the target ISA can encode.
> >
> > On RISC-V, canary loads are emitted as
> >
> >     ld	t0, TSK_STACK_CANARY(tp)
> >
> > where TSK_STACK_CANARY must fit into a 12-bit signed immediate, i.e.
> > [-2048, 2047].  Once stack_canary sits past byte 2047 of task_struct,
> > the build fails with
> >
> >     cc1: error: '<N>' is not a valid offset in
> >         '-mstack-protector-guard-offset='

Thanks for this patch. We just ran into this exact issue during a CKI build
https://datawarehouse.cki-project.org/kcidb/builds/1639782 and this seems
like exactly the fix we need.

> >
> >   * On RISC-V, CONFIG_STACKPROTECTOR_PER_TASK depends on !RANDSTRUCT,
> >     so randomized_struct_fields_start/end always expand to nothing and
> >     stack_canary lands at a small, stable offset well within the
> >     12-bit signed immediate range.  The build error goes away.
> >
> >   * On architectures that enable RANDSTRUCT for hardening, stack_canary
> >     stays inside the randomized region and is still shuffled together
> >     with the other fields by the layout randomization, so its hardening
> >     coverage is preserved.  asm-offsets-based architectures read the
> >     shuffled offset at build time, so the generated canary accesses
> >     remain correct.
> >
> > pahole on a typical 64-bit config shows that the area around the
> > wakee_* fields already contains a usable hole:
> >
> >     struct __call_single_node  wake_entry;           /*    56    16 */
> >     /* --- cacheline 1 boundary (64 bytes) ---       */
> >     unsigned int               wakee_flips;          /*    72     4 */
> >     /* XXX 4 bytes hole, try to pack */
> >     unsigned long int          wakee_flip_decay_ts;  /*    80     8 */
> >     struct task_struct *       last_wakee;           /*    88     8 */
> >
> > Move wakee_flips to sit after last_wakee.  That opens up a clean
> > 8-byte slot at offset 72 into which stack_canary fits exactly:
> >
> >     struct __call_single_node  wake_entry;           /*    56    16 */
> >     /* --- cacheline 1 boundary (64 bytes) ---       */
> >     unsigned long              stack_canary;         /*    72     8 */
> >     unsigned long int          wakee_flip_decay_ts;  /*    80     8 */
> >     struct task_struct *       last_wakee;           /*    88     8 */
> >     unsigned int               wakee_flips;          /*    96     4 */
> >
> > Suggested-by: K Prateek Nayak <[email protected]>
> > Signed-off-by: Ruidong Tian <[email protected]>
> 
> Reviewed-by: Valentin Schneider <[email protected]>
> 

Thanks for the review, is there any hope of this patch going in during
the 7.3 merge window?

I have also copied the RISC-V list as well, maybe if it is ok with the
sched folks, the RISC-V maintainers could take it through their tree as
a RISC-V specific urgent fix?

Best—Charlie


_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.