On Wed, Feb 05, 2020 at 10:19:32AM -0800, Yu-cheng Yu wrote: > Check an ELF file's .note.gnu.property, and setup Shadow Stack if the > application supports it. > > v9: > - Change cpu_feature_enabled() to static_cpu_has(). > > Signed-off-by: Yu-cheng Yu <yu-cheng.yu@xxxxxxxxx> > --- > arch/x86/Kconfig | 2 ++ > arch/x86/include/asm/elf.h | 13 +++++++++++++ > arch/x86/kernel/process_64.c | 31 +++++++++++++++++++++++++++++++ > 3 files changed, 46 insertions(+) > > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig > index 6c34b701c588..d1447380e02e 100644 > --- a/arch/x86/Kconfig > +++ b/arch/x86/Kconfig > @@ -1987,6 +1987,8 @@ config X86_INTEL_SHADOW_STACK_USER > select ARCH_USES_HIGH_VMA_FLAGS > select X86_INTEL_CET > select ARCH_HAS_SHSTK > + select ARCH_USE_GNU_PROPERTY > + select ARCH_BINFMT_ELF_STATE > ---help--- > Shadow Stack (SHSTK) provides protection against program > stack corruption. It is active when the kernel has this > diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h > index 69c0f892e310..fac79b621e0a 100644 > --- a/arch/x86/include/asm/elf.h > +++ b/arch/x86/include/asm/elf.h > @@ -367,6 +367,19 @@ extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm, > int uses_interp); > #define compat_arch_setup_additional_pages compat_arch_setup_additional_pages > > +#ifdef CONFIG_ARCH_BINFMT_ELF_STATE > +struct arch_elf_state { > + unsigned int gnu_property; > +}; > + > +#define INIT_ARCH_ELF_STATE { \ > + .gnu_property = 0, \ > +} > + > +#define arch_elf_pt_proc(ehdr, phdr, elf, interp, state) (0) > +#define arch_check_elf(ehdr, interp, interp_ehdr, state) (0) > +#endif > + > /* Do not change the values. See get_align_mask() */ > enum align_flags { > ALIGN_VA_32 = BIT(0), > diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c > index 506d66830d4d..99548cde0cc6 100644 > --- a/arch/x86/kernel/process_64.c > +++ b/arch/x86/kernel/process_64.c > @@ -732,3 +732,34 @@ unsigned long KSTK_ESP(struct task_struct *task) > { > return task_pt_regs(task)->sp; > } > + > +#ifdef CONFIG_ARCH_USE_GNU_PROPERTY > +int arch_parse_elf_property(u32 type, const void *data, size_t datasz, > + bool compat, struct arch_elf_state *state) > +{ > + if (type != GNU_PROPERTY_X86_FEATURE_1_AND) > + return 0; > + > + if (datasz != sizeof(unsigned int)) > + return -ENOEXEC; > + > + state->gnu_property = *(unsigned int *)data; > + return 0; > +} > + > +int arch_setup_elf_property(struct arch_elf_state *state) > +{ > + int r = 0; > + > + memset(¤t->thread.cet, 0, sizeof(struct cet_status)); > + > + if (static_cpu_has(X86_FEATURE_SHSTK)) { > + if (state->gnu_property & GNU_PROPERTY_X86_FEATURE_1_SHSTK) > + r = cet_setup_shstk(); > + if (r < 0) > + return r; This test is redundant; there's no loop. This can just fall through to the final return. -Kees > + } > + > + return r; > +} > +#endif > -- > 2.21.0 > -- Kees Cook