On Mon, Oct 12, 2020 at 05:31:54PM -0700, Sami Tolvanen wrote: > With LTO, the compiler can rename static functions to avoid global > naming collisions. As initcall functions are typically static, > renaming can break references to them in inline assembly. This > change adds a global stub with a stable name for each initcall to > fix the issue when PREL32 relocations are used. > > Signed-off-by: Sami Tolvanen <samitolvanen@xxxxxxxxxx> > Reviewed-by: Kees Cook <keescook@xxxxxxxxxxxx> This is another independent improvement... this could land before the other portions of the series. -Kees > --- > include/linux/init.h | 31 +++++++++++++++++++++++++++---- > 1 file changed, 27 insertions(+), 4 deletions(-) > > diff --git a/include/linux/init.h b/include/linux/init.h > index af638cd6dd52..cea63f7e7705 100644 > --- a/include/linux/init.h > +++ b/include/linux/init.h > @@ -209,26 +209,49 @@ extern bool initcall_debug; > */ > #define __initcall_section(__sec, __iid) \ > #__sec ".init.." #__iid > + > +/* > + * With LTO, the compiler can rename static functions to avoid > + * global naming collisions. We use a global stub function for > + * initcalls to create a stable symbol name whose address can be > + * taken in inline assembly when PREL32 relocations are used. > + */ > +#define __initcall_stub(fn, __iid, id) \ > + __initcall_name(initstub, __iid, id) > + > +#define __define_initcall_stub(__stub, fn) \ > + int __init __stub(void); \ > + int __init __stub(void) \ > + { \ > + return fn(); \ > + } \ > + __ADDRESSABLE(__stub) > #else > #define __initcall_section(__sec, __iid) \ > #__sec ".init" > + > +#define __initcall_stub(fn, __iid, id) fn > + > +#define __define_initcall_stub(__stub, fn) \ > + __ADDRESSABLE(fn) > #endif > > #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS > -#define ____define_initcall(fn, __name, __sec) \ > - __ADDRESSABLE(fn) \ > +#define ____define_initcall(fn, __stub, __name, __sec) \ > + __define_initcall_stub(__stub, fn) \ > asm(".section \"" __sec "\", \"a\" \n" \ > __stringify(__name) ": \n" \ > - ".long " #fn " - . \n" \ > + ".long " __stringify(__stub) " - . \n" \ > ".previous \n"); > #else > -#define ____define_initcall(fn, __name, __sec) \ > +#define ____define_initcall(fn, __unused, __name, __sec) \ > static initcall_t __name __used \ > __attribute__((__section__(__sec))) = fn; > #endif > > #define __unique_initcall(fn, id, __sec, __iid) \ > ____define_initcall(fn, \ > + __initcall_stub(fn, __iid, id), \ > __initcall_name(initcall, __iid, id), \ > __initcall_section(__sec, __iid)) > > -- > 2.28.0.1011.ga647a8990f-goog > -- Kees Cook