Message ID | 20210427204315.24153-27-yu-cheng.yu@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Control-flow Enforcement: Shadow Stack | expand |
On Tue, Apr 27, 2021 at 01:43:11PM -0700, Yu-cheng Yu wrote: > @@ -1951,6 +1951,8 @@ config X86_SHADOW_STACK > depends on AS_WRUSS > depends on ARCH_HAS_SHADOW_STACK > select ARCH_USES_HIGH_VMA_FLAGS > + select ARCH_USE_GNU_PROPERTY > + select ARCH_BINFMT_ELF_STATE ^^^^^^^^ What's that for? Isn't ARCH_USE_GNU_PROPERTY enough? > +int arch_setup_elf_property(struct arch_elf_state *state) > +{ > + int r = 0; > + > + if (!IS_ENABLED(CONFIG_X86_SHADOW_STACK)) > + return r; > + > + memset(¤t->thread.cet, 0, sizeof(struct cet_status)); > + > + if (static_cpu_has(X86_FEATURE_SHSTK)) { cpu_feature_enabled > + if (state->gnu_property & GNU_PROPERTY_X86_FEATURE_1_SHSTK) > + r = shstk_setup(); > + } > + > + return r; > +} > +#endif ... > diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h > index 30f68b42eeb5..24ba55ba8278 100644 > --- a/include/uapi/linux/elf.h > +++ b/include/uapi/linux/elf.h > @@ -455,4 +455,13 @@ typedef struct elf64_note { > /* Bits for GNU_PROPERTY_AARCH64_FEATURE_1_BTI */ > #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) > > +/* .note.gnu.property types for x86: */ > +#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 Why not 0xc0000001? ARM64 is 0xc0000000...
On 5/19/2021 11:10 AM, Borislav Petkov wrote: > On Tue, Apr 27, 2021 at 01:43:11PM -0700, Yu-cheng Yu wrote: >> @@ -1951,6 +1951,8 @@ config X86_SHADOW_STACK >> depends on AS_WRUSS >> depends on ARCH_HAS_SHADOW_STACK >> select ARCH_USES_HIGH_VMA_FLAGS >> + select ARCH_USE_GNU_PROPERTY >> + select ARCH_BINFMT_ELF_STATE > ^^^^^^^^ > > What's that for? Isn't ARCH_USE_GNU_PROPERTY enough? > ARCH_USE_GNU_PROPERTY is for defining parsing functions, e.g. arch_parse_elf_property(), arch_setup_property(). ARCH_BINFMT_ELF_STATE is for defining "struct arch_elf_state". However, those parsing functions take (struct arch_elf_state *) as an input. It probably makes sense to have ARCH_USE_GNU_PROPERTY dependent on ARCH_BINFMT_ELF_STATE. It would be ok as-is too. ARM people might have other plans in mind. [...] > >> diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h >> index 30f68b42eeb5..24ba55ba8278 100644 >> --- a/include/uapi/linux/elf.h >> +++ b/include/uapi/linux/elf.h >> @@ -455,4 +455,13 @@ typedef struct elf64_note { >> /* Bits for GNU_PROPERTY_AARCH64_FEATURE_1_BTI */ >> #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) >> >> +/* .note.gnu.property types for x86: */ >> +#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 > > Why not 0xc0000001? ARM64 is 0xc0000000... > I just looked at the ABI document. ARM has GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 X86 has: GNU_PROPERTY_X86_ISA_1_USED 0xc0000000 GNU_PROPERTY_X86_ISA_1_NEEDED 0xc0000001 GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 Yu-cheng
On Wed, May 19, 2021 at 03:14:58PM -0700, Yu, Yu-cheng wrote: > However, those parsing functions take (struct arch_elf_state *) as an input. Exactly. > It probably makes sense to have ARCH_USE_GNU_PROPERTY dependent on > ARCH_BINFMT_ELF_STATE. It would be ok as-is too. ARM people might have > other plans in mind. Well, let's look at ARM, ARM64 in particular. They have defined struct arch_elf_state without the ifdeffery in arch/arm64/include/asm/elf.h and are using that struct in arch_parse_elf_property(). And they have selected ARCH_BINFMT_ELF_STATE just so that they disable those dummy accessors in fs/binfmt_elf.c And you're practically glueing together ARCH_BINFMT_ELF_STATE and ARCH_USE_GNU_PROPERTY. However, all the functionality is for adding the gnu property note so I think you should select both but only use ARCH_USE_GNU_PROPERTY in all the ifdeffery in your patch to at least have this as simple as possible. > I just looked at the ABI document. Which document is that? Link? > ARM has GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 > > X86 has: > GNU_PROPERTY_X86_ISA_1_USED 0xc0000000 > GNU_PROPERTY_X86_ISA_1_NEEDED 0xc0000001 > GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 Our defines should at least have a comment pointing to that document. Thx.
On 5/20/2021 2:26 AM, Borislav Petkov wrote: > On Wed, May 19, 2021 at 03:14:58PM -0700, Yu, Yu-cheng wrote: >> However, those parsing functions take (struct arch_elf_state *) as an input. > > Exactly. > >> It probably makes sense to have ARCH_USE_GNU_PROPERTY dependent on >> ARCH_BINFMT_ELF_STATE. It would be ok as-is too. ARM people might have >> other plans in mind. > > Well, let's look at ARM, ARM64 in particular. They have defined struct > arch_elf_state without the ifdeffery in > > arch/arm64/include/asm/elf.h > > and are using that struct in arch_parse_elf_property(). > > And they have selected ARCH_BINFMT_ELF_STATE just so that they disable > those dummy accessors in fs/binfmt_elf.c > > And you're practically glueing together ARCH_BINFMT_ELF_STATE and > ARCH_USE_GNU_PROPERTY. However, all the functionality is for adding > the gnu property note so I think you should select both but only use > ARCH_USE_GNU_PROPERTY in all the ifdeffery in your patch to at least > have this as simple as possible. > ARM64 has ARCH_USE_GNU_PROPERTY and ARCH_BINFMT_ELF_STATE selected unconditionally. We will do the same for X86_64 and remove the ifdeffery. >> I just looked at the ABI document. > > Which document is that? Link? > >> ARM has GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 >> >> X86 has: >> GNU_PROPERTY_X86_ISA_1_USED 0xc0000000 >> GNU_PROPERTY_X86_ISA_1_NEEDED 0xc0000001 >> GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 > > Our defines should at least have a comment pointing to that document. > > Thx. > The latest pdf's are posted here. https://gitlab.com/x86-psABIs/x86-64-ABI/-/wikis/x86-64-psABI Thanks, Yu-cheng
On Thu, May 20, 2021 at 10:18:10AM -0700, Yu, Yu-cheng wrote: > The latest pdf's are posted here. > > https://gitlab.com/x86-psABIs/x86-64-ABI/-/wikis/x86-64-psABI Ah, that document. Please make sure it is specified over those defines from which document they're coming from. Thx.
On Wed, May 19, 2021 at 03:14:58PM -0700, Yu, Yu-cheng wrote: > > > +++ b/include/uapi/linux/elf.h > > > @@ -455,4 +455,13 @@ typedef struct elf64_note { > > > /* Bits for GNU_PROPERTY_AARCH64_FEATURE_1_BTI */ > > > #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) > > > +/* .note.gnu.property types for x86: */ > > > +#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 > > > > Why not 0xc0000001? ARM64 is 0xc0000000... > > > > I just looked at the ABI document. > > ARM has GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 > > X86 has: > GNU_PROPERTY_X86_ISA_1_USED 0xc0000000 > GNU_PROPERTY_X86_ISA_1_NEEDED 0xc0000001 > GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 Please add all three, not just the last one.
On 5/20/2021 10:35 AM, Borislav Petkov wrote: > On Thu, May 20, 2021 at 10:18:10AM -0700, Yu, Yu-cheng wrote: >> The latest pdf's are posted here. >> >> https://gitlab.com/x86-psABIs/x86-64-ABI/-/wikis/x86-64-psABI > > Ah, that document. > > Please make sure it is specified over those defines from which document > they're coming from. > I will do that.
On 5/20/2021 10:38 AM, Matthew Wilcox wrote: > On Wed, May 19, 2021 at 03:14:58PM -0700, Yu, Yu-cheng wrote: >>>> +++ b/include/uapi/linux/elf.h >>>> @@ -455,4 +455,13 @@ typedef struct elf64_note { >>>> /* Bits for GNU_PROPERTY_AARCH64_FEATURE_1_BTI */ >>>> #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) >>>> +/* .note.gnu.property types for x86: */ >>>> +#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 >>> >>> Why not 0xc0000001? ARM64 is 0xc0000000... >>> >> >> I just looked at the ABI document. >> >> ARM has GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 >> >> X86 has: >> GNU_PROPERTY_X86_ISA_1_USED 0xc0000000 >> GNU_PROPERTY_X86_ISA_1_NEEDED 0xc0000001 >> GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 > > Please add all three, not just the last one. > Ok!
On 5/20/2021 10:52 AM, Yu, Yu-cheng wrote: > On 5/20/2021 10:38 AM, Matthew Wilcox wrote: >> On Wed, May 19, 2021 at 03:14:58PM -0700, Yu, Yu-cheng wrote: >>>>> +++ b/include/uapi/linux/elf.h >>>>> @@ -455,4 +455,13 @@ typedef struct elf64_note { >>>>> /* Bits for GNU_PROPERTY_AARCH64_FEATURE_1_BTI */ >>>>> #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) >>>>> +/* .note.gnu.property types for x86: */ >>>>> +#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 >>>> >>>> Why not 0xc0000001? ARM64 is 0xc0000000... >>>> >>> >>> I just looked at the ABI document. >>> >>> ARM has GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 >>> >>> X86 has: >>> GNU_PROPERTY_X86_ISA_1_USED 0xc0000000 >>> GNU_PROPERTY_X86_ISA_1_NEEDED 0xc0000001 >>> GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 >> >> Please add all three, not just the last one. >> > > Ok! Just found out, I have been reading an older version. Now 0xc0000000 and 0xc0000001 have become reserved/not-used. Maybe I will just put a note about that along with the link to the ABI document. Yu-cheng
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 8d1c8dcb87fd..d37bc7915935 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -281,6 +281,11 @@ static inline int arch_parse_elf_property(u32 type, const void *data, return 0; } +static inline int arch_setup_elf_property(struct arch_elf_state *arch) +{ + return 0; +} + static inline int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *f, bool is_interp, struct arch_elf_state *state) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 41283f82fd87..77d2e44995d7 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1951,6 +1951,8 @@ config X86_SHADOW_STACK depends on AS_WRUSS depends on ARCH_HAS_SHADOW_STACK select ARCH_USES_HIGH_VMA_FLAGS + select ARCH_USE_GNU_PROPERTY + select ARCH_BINFMT_ELF_STATE help Shadow Stack protection is a hardware feature that detects function return address corruption. This helps mitigate ROP attacks. diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 9224d40cdefe..6a131047be8a 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -390,6 +390,19 @@ extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm, extern bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs); +#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 d08307df69ad..d71045b29475 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -835,3 +835,35 @@ 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; + + if (!IS_ENABLED(CONFIG_X86_SHADOW_STACK)) + return r; + + 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 = shstk_setup(); + } + + return r; +} +#endif diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index b12ba98ae9f5..fa665eceba04 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1248,6 +1248,10 @@ static int load_elf_binary(struct linux_binprm *bprm) set_binfmt(&elf_format); + retval = arch_setup_elf_property(&arch_state); + if (retval < 0) + goto out; + #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES retval = ARCH_SETUP_ADDITIONAL_PAGES(bprm, elf_ex, !!interpreter); if (retval < 0) diff --git a/include/linux/elf.h b/include/linux/elf.h index c9a46c4e183b..be04d15e937f 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -92,9 +92,15 @@ static inline int arch_parse_elf_property(u32 type, const void *data, { return 0; } + +static inline int arch_setup_elf_property(struct arch_elf_state *arch) +{ + return 0; +} #else extern int arch_parse_elf_property(u32 type, const void *data, size_t datasz, bool compat, struct arch_elf_state *arch); +extern int arch_setup_elf_property(struct arch_elf_state *arch); #endif #ifdef CONFIG_ARCH_HAVE_ELF_PROT diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h index 30f68b42eeb5..24ba55ba8278 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -455,4 +455,13 @@ typedef struct elf64_note { /* Bits for GNU_PROPERTY_AARCH64_FEATURE_1_BTI */ #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) +/* .note.gnu.property types for x86: */ +#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 + +/* Bits for GNU_PROPERTY_X86_FEATURE_1_AND */ +#define GNU_PROPERTY_X86_FEATURE_1_IBT 0x00000001 +#define GNU_PROPERTY_X86_FEATURE_1_SHSTK 0x00000002 +#define GNU_PROPERTY_X86_FEATURE_1_VALID (GNU_PROPERTY_X86_FEATURE_1_IBT | \ + GNU_PROPERTY_X86_FEATURE_1_SHSTK) + #endif /* _UAPI_LINUX_ELF_H */