In order to link a user space executable we will need access to a few section that are not normally used when linking the kernel. Add these sections when we have selected CONFIG_UNIKERNEL_LINUX. Add case to not throw warnings for COMMON symbols from application code. Make the KBUILD_VMLINUX_OBJS contain the application library when UKL is enabled. Cc: Jonathan Corbet <corbet@xxxxxxx> Cc: Masahiro Yamada <masahiroy@xxxxxxxxxx> Cc: Michal Marek <michal.lkml@xxxxxxxxxxx> Cc: Nick Desaulniers <ndesaulniers@xxxxxxxxxx> Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxxxxx> Cc: Borislav Petkov <bp@xxxxxxxxx> Cc: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx> Cc: "H. Peter Anvin" <hpa@xxxxxxxxx> Cc: Andy Lutomirski <luto@xxxxxxxxxx> Cc: Eric Biederman <ebiederm@xxxxxxxxxxxx> Cc: Kees Cook <keescook@xxxxxxxxxxxx> Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx> Cc: Alexander Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: Arnd Bergmann <arnd@xxxxxxxx> Cc: Juri Lelli <juri.lelli@xxxxxxxxxx> Cc: Vincent Guittot <vincent.guittot@xxxxxxxxxx> Cc: Dietmar Eggemann <dietmar.eggemann@xxxxxxx> Cc: Steven Rostedt <rostedt@xxxxxxxxxxx> Cc: Ben Segall <bsegall@xxxxxxxxxx> Cc: Mel Gorman <mgorman@xxxxxxx> Cc: Daniel Bristot de Oliveira <bristot@xxxxxxxxxx> Cc: Valentin Schneider <vschneid@xxxxxxxxxx> Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx> Cc: Josh Poimboeuf <jpoimboe@xxxxxxxxxx> Co-developed-by: Thomas Unger <tommyu@xxxxxx> Signed-off-by: Thomas Unger <tommyu@xxxxxx> Co-developed-by: Matthew Boyd <mboydmcse@xxxxxxxxx> Signed-off-by: Matthew Boyd <mboydmcse@xxxxxxxxx> Co-developed-by: Eric B Munson <munsoner@xxxxxx> Signed-off-by: Eric B Munson <munsoner@xxxxxx> Co-developed-by: Ali Raza <aliraza@xxxxxx> Signed-off-by: Ali Raza <aliraza@xxxxxx> --- Makefile | 4 ++ arch/x86/kernel/vmlinux.lds.S | 98 +++++++++++++++++++++++++++++++ include/asm-generic/sections.h | 4 ++ include/asm-generic/vmlinux.lds.h | 32 +++++++++- scripts/mod/modpost.c | 4 ++ 5 files changed, 141 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8478e13e9424..d072a52ed856 100644 --- a/Makefile +++ b/Makefile @@ -1129,6 +1129,10 @@ KBUILD_VMLINUX_LIBS := $(patsubst %/,%/lib.a, $(libs-y)) endif KBUILD_VMLINUX_OBJS += $(patsubst %/,%/built-in.a, $(drivers-y)) +ifdef CONFIG_UNIKERNEL_LINUX +KBUILD_VMLINUX_OBJS += $(CONFIG_UKL_ARCHIVE_PATH) +endif + export KBUILD_VMLINUX_OBJS KBUILD_VMLINUX_LIBS export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds # used by scripts/Makefile.package diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 15f29053cec4..cb8b33955969 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -101,6 +101,9 @@ jiffies = jiffies_64; PHDRS { text PT_LOAD FLAGS(5); /* R_E */ +#if defined(CONFIG_UNIKERNEL_LINUX) && defined(CONFIG_UKL_TLS) + tls PT_TLS FLAGS(6); /* RW_ */ +#endif data PT_LOAD FLAGS(6); /* RW_ */ #ifdef CONFIG_X86_64 #ifdef CONFIG_SMP @@ -146,6 +149,71 @@ SECTIONS #endif } :text =0xcccc +#ifdef CONFIG_UNIKERNEL_LINUX + /* Added to preserve page alignment */ + . = ALIGN(PAGE_SIZE); + + /* */ + .rela.plt : + { + *(.rela.plt) + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } :text =0xcccc + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } :text =0xcccc + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o + *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } :text =0xcccc + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o + *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } :text =0xcccc + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } :text =0xcccc + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } :text =0xcccc +#endif + /* End of text section, which should occupy whole number of pages */ _etext = .; . = ALIGN(PAGE_SIZE); @@ -208,6 +276,29 @@ SECTIONS . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE); +#ifdef CONFIG_UNIKERNEL_LINUX +#ifdef CONFIG_UKL_TLS + /* Thread Local Storage sections */ + . = ALIGN(PAGE_SIZE); + .tdata : ALIGN(0x200000){ + __tls_data_start = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __tls_data_end = .; + } :tls + .tbss : { + __tls_bss_start = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __tls_bss_end = .; + } :tls +#else + . = ALIGN(PAGE_SIZE); + __tls_data_start = .; + __tls_data_end = .; + __tls_bss_start = .; + __tls_bss_end = .; +#endif +#endif + /* Init code and data - will be freed after init */ . = ALIGN(PAGE_SIZE); .init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) { @@ -380,8 +471,13 @@ SECTIONS *(BSS_MAIN) BSS_DECRYPTED . = ALIGN(PAGE_SIZE); +#ifdef CONFIG_UNIKERNEL_LINUX + } + __bss_stop = .; +#else __bss_stop = .; } +#endif /* * The memory occupied from _text to here, __end_of_kernel_reserve, is @@ -446,6 +542,7 @@ SECTIONS #endif "Unexpected GOT/PLT entries detected!") +#ifndef CONFIG_UNIKERNEL_LINUX /* * Sections that should stay zero sized, which is safer to * explicitly check instead of blindly discarding. @@ -469,6 +566,7 @@ SECTIONS *(.rela.*) *(.rela_*) } ASSERT(SIZEOF(.rela.dyn) == 0, "Unexpected run-time relocations (.rela) detected!") +#endif } /* diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index db13bb620f52..42ebf251903c 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -35,6 +35,10 @@ extern char _text[], _stext[], _etext[]; extern char _data[], _sdata[], _edata[]; extern char __bss_start[], __bss_stop[]; +#ifdef CONFIG_UNIKERNEL_LINUX +extern char __tls_data_start[], __tls_data_end[]; +extern char __tls_bss_start[], __tls_bss_end[]; +#endif extern char __init_begin[], __init_end[]; extern char _sinittext[], _einittext[]; extern char __start_ro_after_init[], __end_ro_after_init[]; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 7c90b1ab3e00..4b0e4f3d4c39 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -568,6 +568,24 @@ * code elimination is enabled, so these sections should be converted * to use ".." first. */ +#ifdef CONFIG_UNIKERNEL_LINUX +#define TEXT_TEXT \ + ALIGN_FUNCTION(); \ + *(.text.hot .text.hot.*) \ + *(TEXT_MAIN .text.fixup) \ + *(.stub .text.* .gnu.linkonce.t.*) \ + *(.text.unlikely .text.*_unlikely .text.unlikely.*) \ + *(.text.exit .text.exit.*) \ + *(.text.startup .text.startup.*) \ + *(.text.unknown .text.unknown.*) \ + NOINSTR_TEXT \ + *(.text..refcount) \ + *(.ref.text) \ + *(.text.asan.* .text.tsan.*) \ + TEXT_CFI_JT \ + MEM_KEEP(init.text*) \ + MEM_KEEP(exit.text*) +#else #define TEXT_TEXT \ ALIGN_FUNCTION(); \ *(.text.hot .text.hot.*) \ @@ -580,7 +598,8 @@ *(.text.asan.* .text.tsan.*) \ TEXT_CFI_JT \ MEM_KEEP(init.text*) \ - MEM_KEEP(exit.text*) \ + MEM_KEEP(exit.text*) +#endif /* sched.text is aling to function alignment to secure we have same @@ -1029,12 +1048,23 @@ /* ld.bfd warns about .gnu.version* even when not emitted */ \ *(.gnu.version*) \ +#ifdef CONFIG_UNIKERNEL_LINUX +#define DISCARDS \ + /DISCARD/ : { \ + EXIT_DISCARDS \ + EXIT_CALL \ + COMMON_DISCARDS \ + *(.gnu.glibc-stub.*) \ + *(.gnu.warning.*) \ + } +#else #define DISCARDS \ /DISCARD/ : { \ EXIT_DISCARDS \ EXIT_CALL \ COMMON_DISCARDS \ } +#endif /** * PERCPU_INPUT - the percpu input sections diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 2c80da0220c3..a6023db6b630 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -626,6 +626,8 @@ static void handle_symbol(struct module *mod, struct elf_info *info, case SHN_COMMON: if (strstarts(symname, "__gnu_lto_")) { /* Should warn here, but modpost runs before the linker */ + } else if (strstarts(symname, "ukl_")) { + /* User code can have common symbols */ } else warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name); break; @@ -774,6 +776,8 @@ static const char *const section_white_list[] = ".fmt_slot*", /* EZchip */ ".gnu.lto*", ".discard.*", + ".gnu.warning.*", + ".gnu.glibc-stub.*", NULL }; -- 2.21.3