Message ID | 20250214192210.work.253-kees@kernel.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | x86/kcfi: Require FRED for FineIBT | expand |
On 14/02/2025 7:22 pm, Kees Cook wrote: > diff --git a/arch/x86/include/asm/cfi.h b/arch/x86/include/asm/cfi.h > index ef5e0a698253..dfa2ba4cceca 100644 > --- a/arch/x86/include/asm/cfi.h > +++ b/arch/x86/include/asm/cfi.h > @@ -93,7 +93,7 @@ > * > */ > enum cfi_mode { > - CFI_AUTO, /* FineIBT if hardware has IBT, otherwise kCFI */ > + CFI_AUTO, /* FineIBT if hardware has IBT, FRED, and XOM */ You discuss XOM in the commit message, but there's no check ... > CFI_OFF, /* Taditional / IBT depending on .config */ > CFI_KCFI, /* Optionally CALL_PADDING, IBT, RETPOLINE */ > CFI_FINEIBT, /* see arch/x86/kernel/alternative.c */ > diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c > index 97422292b609..acc12a6efc18 100644 > --- a/arch/x86/kernel/alternative.c > +++ b/arch/x86/kernel/alternative.c > @@ -1323,7 +1323,9 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, > > if (cfi_mode == CFI_AUTO) { > cfi_mode = CFI_KCFI; > - if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT)) > + /* FineIBT requires IBT and will only be safe with FRED */ > + if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT) && > + cpu_feature_enabled(X86_FEATURE_FRED)) ... here. Is this meant to be "/* TODO: wire up XOM */" or is that accounted for somewhere else? Also, while I hate to come back and contradict myself from earlier... Architecturally, FineIBT without FRED seems to be no improvement over simple IBT. (I'd love to find some way of hardening the entrypoints, but I can't see a robust way of doing so.) However, micro-architecturally, FineIBT is still far better than simple IBT for speculation issue, seeing as Intel keep on staunchly refusing to turn off the indirect predictors by default like AMD do. A security conscious user ought to be using FineIBT for this, given a choice, even if it's not perfect in other regards. ~Andrew
On Fri, Feb 14, 2025 at 07:39:20PM +0000, Andrew Cooper wrote: > On 14/02/2025 7:22 pm, Kees Cook wrote: > > diff --git a/arch/x86/include/asm/cfi.h b/arch/x86/include/asm/cfi.h > > index ef5e0a698253..dfa2ba4cceca 100644 > > --- a/arch/x86/include/asm/cfi.h > > +++ b/arch/x86/include/asm/cfi.h > > @@ -93,7 +93,7 @@ > > * > > */ > > enum cfi_mode { > > - CFI_AUTO, /* FineIBT if hardware has IBT, otherwise kCFI */ > > + CFI_AUTO, /* FineIBT if hardware has IBT, FRED, and XOM */ > > You discuss XOM in the commit message, but there's no check ... > > > CFI_OFF, /* Taditional / IBT depending on .config */ > > CFI_KCFI, /* Optionally CALL_PADDING, IBT, RETPOLINE */ > > CFI_FINEIBT, /* see arch/x86/kernel/alternative.c */ > > diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c > > index 97422292b609..acc12a6efc18 100644 > > --- a/arch/x86/kernel/alternative.c > > +++ b/arch/x86/kernel/alternative.c > > @@ -1323,7 +1323,9 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, > > > > if (cfi_mode == CFI_AUTO) { > > cfi_mode = CFI_KCFI; > > - if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT)) > > + /* FineIBT requires IBT and will only be safe with FRED */ > > + if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT) && > > + cpu_feature_enabled(X86_FEATURE_FRED)) > > ... here. > > Is this meant to be "/* TODO: wire up XOM */" or is that accounted for > somewhere else? Yeah, I wasn't sure how to best capture that in here. XOM doesn't exist yet for x86... I could add a TODO like that? > Also, while I hate to come back and contradict myself from earlier... > > Architecturally, FineIBT without FRED seems to be no improvement over > simple IBT. (I'd love to find some way of hardening the entrypoints, > but I can't see a robust way of doing so.) If you're just looking at IBT, yes. But kCFI (with or without IBT, but without FineIBT) will do hash checking at the call site, which should make it impossible to reach the entrypoints from an indirect call in the first place, as they have no hash preceding them. > However, micro-architecturally, FineIBT is still far better than simple > IBT for speculation issue, seeing as Intel keep on staunchly refusing to > turn off the indirect predictors by default like AMD do. > > A security conscious user ought to be using FineIBT for this, given a > choice, even if it's not perfect in other regards. A security conscious user should use kCFI without FineIBT. :) But I think we might be thinking about different elements of security. I am focusing on control flow, and I think you're considering speculation? -Kees
On 14/02/2025 9:54 pm, Kees Cook wrote: > On Fri, Feb 14, 2025 at 07:39:20PM +0000, Andrew Cooper wrote: >> On 14/02/2025 7:22 pm, Kees Cook wrote: >>> diff --git a/arch/x86/include/asm/cfi.h b/arch/x86/include/asm/cfi.h >>> index ef5e0a698253..dfa2ba4cceca 100644 >>> --- a/arch/x86/include/asm/cfi.h >>> +++ b/arch/x86/include/asm/cfi.h >>> @@ -93,7 +93,7 @@ >>> * >>> */ >>> enum cfi_mode { >>> - CFI_AUTO, /* FineIBT if hardware has IBT, otherwise kCFI */ >>> + CFI_AUTO, /* FineIBT if hardware has IBT, FRED, and XOM */ >> You discuss XOM in the commit message, but there's no check ... >> >>> CFI_OFF, /* Taditional / IBT depending on .config */ >>> CFI_KCFI, /* Optionally CALL_PADDING, IBT, RETPOLINE */ >>> CFI_FINEIBT, /* see arch/x86/kernel/alternative.c */ >>> diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c >>> index 97422292b609..acc12a6efc18 100644 >>> --- a/arch/x86/kernel/alternative.c >>> +++ b/arch/x86/kernel/alternative.c >>> @@ -1323,7 +1323,9 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, >>> >>> if (cfi_mode == CFI_AUTO) { >>> cfi_mode = CFI_KCFI; >>> - if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT)) >>> + /* FineIBT requires IBT and will only be safe with FRED */ >>> + if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT) && >>> + cpu_feature_enabled(X86_FEATURE_FRED)) >> ... here. >> >> Is this meant to be "/* TODO: wire up XOM */" or is that accounted for >> somewhere else? > Yeah, I wasn't sure how to best capture that in here. XOM doesn't exist > yet for x86... I could add a TODO like that? I get the feeling that the PKS series would have an easier time starting with XOM (even if it hard-codes pkey1=xom and avoids the allocator in the short term, seeing as Linux does have a good grasp of where it's executable pages are, and how they're accessed) rather than trying to do general page hiding. The capability is in 3 generations of Intel CPU now. > >> Also, while I hate to come back and contradict myself from earlier... >> >> Architecturally, FineIBT without FRED seems to be no improvement over >> simple IBT. (I'd love to find some way of hardening the entrypoints, >> but I can't see a robust way of doing so.) > If you're just looking at IBT, yes. But kCFI (with or without IBT, > but without FineIBT) will do hash checking at the call site, which > should make it impossible to reach the entrypoints from an indirect call > in the first place, as they have no hash preceding them. > >> However, micro-architecturally, FineIBT is still far better than simple >> IBT for speculation issue, seeing as Intel keep on staunchly refusing to >> turn off the indirect predictors by default like AMD do. >> >> A security conscious user ought to be using FineIBT for this, given a >> choice, even if it's not perfect in other regards. > A security conscious user should use kCFI without FineIBT. :) But I > think we might be thinking about different elements of security. I am > focusing on control flow, and I think you're considering speculation? True. The security realist knows they're dammed either way, and gets a stiff drink instead. ~Andrew
On Fri, Feb 14, 2025 at 10:40:28PM +0000, Andrew Cooper wrote: > On 14/02/2025 9:54 pm, Kees Cook wrote: > > On Fri, Feb 14, 2025 at 07:39:20PM +0000, Andrew Cooper wrote: > >> Architecturally, FineIBT without FRED seems to be no improvement over > >> simple IBT. (I'd love to find some way of hardening the entrypoints, > >> but I can't see a robust way of doing so.) > > If you're just looking at IBT, yes. But kCFI (with or without IBT, > > but without FineIBT) will do hash checking at the call site, which > > should make it impossible to reach the entrypoints from an indirect call > > in the first place, as they have no hash preceding them. > > > >> However, micro-architecturally, FineIBT is still far better than simple > >> IBT for speculation issue, seeing as Intel keep on staunchly refusing to > >> turn off the indirect predictors by default like AMD do. > >> > >> A security conscious user ought to be using FineIBT for this, given a > >> choice, even if it's not perfect in other regards. > > A security conscious user should use kCFI without FineIBT. :) But I > > think we might be thinking about different elements of security. I am > > focusing on control flow, and I think you're considering speculation? > > True. The security realist knows they're dammed either way, and gets a > stiff drink instead. I don't know how any of our livers survive. :)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c94dae634176..47aec3a497f6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2432,12 +2432,13 @@ config STRICT_SIGALTSTACK_SIZE config CFI_AUTO_DEFAULT bool "Attempt to use FineIBT by default at boot time" - depends on FINEIBT + depends on FINEIBT && X86_FRED default y help - Attempt to use FineIBT by default at boot time. If enabled, - this is the same as booting with "cfi=auto". If disabled, - this is the same as booting with "cfi=kcfi". + Attempt to use FineIBT by default at boot time if supported + and sensible for the hardware. If enabled, this is the same + as booting with "cfi=auto". If disabled, this is the same as + booting with "cfi=kcfi". source "kernel/livepatch/Kconfig" diff --git a/arch/x86/include/asm/cfi.h b/arch/x86/include/asm/cfi.h index ef5e0a698253..dfa2ba4cceca 100644 --- a/arch/x86/include/asm/cfi.h +++ b/arch/x86/include/asm/cfi.h @@ -93,7 +93,7 @@ * */ enum cfi_mode { - CFI_AUTO, /* FineIBT if hardware has IBT, otherwise kCFI */ + CFI_AUTO, /* FineIBT if hardware has IBT, FRED, and XOM */ CFI_OFF, /* Taditional / IBT depending on .config */ CFI_KCFI, /* Optionally CALL_PADDING, IBT, RETPOLINE */ CFI_FINEIBT, /* see arch/x86/kernel/alternative.c */ diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 97422292b609..acc12a6efc18 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -1323,7 +1323,9 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, if (cfi_mode == CFI_AUTO) { cfi_mode = CFI_KCFI; - if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT)) + /* FineIBT requires IBT and will only be safe with FRED */ + if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT) && + cpu_feature_enabled(X86_FEATURE_FRED)) cfi_mode = CFI_FINEIBT; }
With what appears to be an unavoidable pivot gadget always present in the kernel (the entry code), FineIBT's lack of caller-side CFI hash validation leaves it critically flawed[1]. Require FRED for FineIBT[2] (and probably should also require eXecute-Only memory too), and default to kCFI when CFI is built in. Link: https://lore.kernel.org/linux-hardening/Z60NwR4w%2F28Z7XUa@ubun/ [1] Link: https://lore.kernel.org/linux-hardening/c46f5614-a82e-42fc-91eb-05e483a7df9c@citrix.com/ [2] Signed-off-by: Kees Cook <kees@kernel.org> --- Cc: Peter Zijlstra <peterz@infradead.org> Cc: Jennifer Miller <jmill@asu.edu> Cc: Andrew Cooper <andrew.cooper3@citrix.com> Cc: Sami Tolvanen <samitolvanen@google.com> Cc: Jann Horn <jannh@google.com> Cc: Nathan Chancellor <nathan@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: x86@kernel.org Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Alexei Starovoitov <ast@kernel.org> Cc: Josh Poimboeuf <jpoimboe@kernel.org> Cc: "Mike Rapoport (Microsoft)" <rppt@kernel.org> --- arch/x86/Kconfig | 9 +++++---- arch/x86/include/asm/cfi.h | 2 +- arch/x86/kernel/alternative.c | 4 +++- 3 files changed, 9 insertions(+), 6 deletions(-)