Re: [PATCH -tip] x86/stackprotector: Move stack canary to struct pcpu_hot
From: Brian Gerst
Date: Fri Feb 21 2025 - 11:54:52 EST
On Fri, Feb 21, 2025 at 11:02 AM Uros Bizjak <ubizjak@xxxxxxxxx> wrote:
>
> On Fri, Feb 21, 2025 at 4:54 PM Brian Gerst <brgerst@xxxxxxxxx> wrote:
> >
> > On Fri, Feb 21, 2025 at 9:38 AM Ard Biesheuvel <ardb@xxxxxxxxxx> wrote:
> > >
> > > On Fri, 21 Feb 2025 at 15:33, Uros Bizjak <ubizjak@xxxxxxxxx> wrote:
> > > >
> > > > On Fri, Feb 21, 2025 at 3:13 PM Ard Biesheuvel <ardb@xxxxxxxxxx> wrote:
> > > >
> > > > > > > I got a warning from the relocs tool, but not a hard error. What
> > > > > > > compiler/linker are you using?
> > > > > > >
> > > > > > > Does the attached patch build in your configuration?
> > > > > >
> > > > > > Ah, the attached patch is similar to my previous approach, where the
> > > > > > build system *warned* on an offset (the patch was abandoned due to
> > > > > > Ard's request to put stack_canary to the *beginning* of struct
> > > > > > pcpu_hot, and this allowed for a simplified patch).
> > > > > >
> > > > > > The attached patch builds for me without warning/error for both, SMP
> > > > > > and !SMP build.
> > > > > >
> > > > >
> > > > > Did you try building modules too?
> > > >
> > > > make -j 24 olddefconfig prepare modules_prepare bzImage modules
> > > >
> > > > for defconfig, SMP and !SMP.
> > > >
> > >
> > > OK.
> > >
> > > I think I prefer Brian's approach - the only nit is that the placement
> > > of stack_canary creates a padding hole in struct pcpu_hot. However,
> > > that does not actually matter until we run out of space so I think it
> > > is fine as is.
> >
> > Going off on a tangent, as struct pcpu_hot grows I think it can be
> > done better as a subsection of percpu data (".data..percpu..hot").
> > That way each variable has its own symbol again and it reduces header
> > dependencies.
>
> Please note an optimization in common.h:
>
> /* const-qualified alias to pcpu_hot, aliased by linker. */
> DECLARE_PER_CPU_ALIGNED(const struct pcpu_hot __percpu_seg_override,
> const_pcpu_hot);
>
> struct pcpu_hot has its const alias, so we are able to use:
>
> if (IS_ENABLED(CONFIG_USE_X86_SEG_SUPPORT))
> return this_cpu_read_const(const_pcpu_hot.current_task);
>
> where the compiler is able to eliminate a sequence of reads to the
> const_pcpu_hot.current_task.
>
> LTO does not like the approach, though, but clang does not use x86 seg
> support, and gcc does not perform LTO.
Noted.
I'll look into this over the weekend.
Brian Gerst