[PATCH] x86/kcfi: Require FRED for FineIBT

Kees Cook posted 1 patch 10 months, 1 week ago
There is a newer version of this series
arch/x86/Kconfig              | 9 +++++----
arch/x86/include/asm/cfi.h    | 2 +-
arch/x86/kernel/alternative.c | 4 +++-
3 files changed, 9 insertions(+), 6 deletions(-)
[PATCH] x86/kcfi: Require FRED for FineIBT
Posted by Kees Cook 10 months, 1 week ago
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(-)

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;
 	}
 
-- 
2.34.1
Re: [PATCH] x86/kcfi: Require FRED for FineIBT
Posted by Andrew Cooper 10 months, 1 week ago
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
Re: [PATCH] x86/kcfi: Require FRED for FineIBT
Posted by Kees Cook 10 months, 1 week ago
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

-- 
Kees Cook
Re: [PATCH] x86/kcfi: Require FRED for FineIBT
Posted by Andrew Cooper 10 months, 1 week ago
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
Re: [PATCH] x86/kcfi: Require FRED for FineIBT
Posted by Kees Cook 10 months ago
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. :)

-- 
Kees Cook
[tip: x86/cpu] x86/kcfi: Require FRED for FineIBT
Posted by tip-bot2 for Kees Cook 10 months ago
The following commit has been merged into the x86/cpu branch of tip:

Commit-ID:     f12315780faf1cbfe00991077a1e8c8e4c201f3b
Gitweb:        https://git.kernel.org/tip/f12315780faf1cbfe00991077a1e8c8e4c201f3b
Author:        Kees Cook <kees@kernel.org>
AuthorDate:    Fri, 14 Feb 2025 11:22:21 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Fri, 21 Feb 2025 15:38:11 +01:00

x86/kcfi: Require FRED for 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:

  https://lore.kernel.org/linux-hardening/Z60NwR4w%2F28Z7XUa@ubun/ [1]

Require FRED for FineIBT:

  https://lore.kernel.org/linux-hardening/c46f5614-a82e-42fc-91eb-05e483a7df9c@citrix.com/

(and probably should also require eXecute-Only memory too), and default
to kCFI when CFI is built in.

Signed-off-by: Kees Cook <kees@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20250214192210.work.253-kees@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(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 87198d9..754bcd6 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2427,12 +2427,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 31d19c8..547377e 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 c71b575..42f8184 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -1302,7 +1302,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;
 	}
Re: [tip: x86/cpu] x86/kcfi: Require FRED for FineIBT
Posted by Peter Zijlstra 10 months ago
On Fri, Feb 21, 2025 at 03:08:05PM -0000, tip-bot2 for Kees Cook wrote:
> The following commit has been merged into the x86/cpu branch of tip:
> 
> Commit-ID:     f12315780faf1cbfe00991077a1e8c8e4c201f3b
> Gitweb:        https://git.kernel.org/tip/f12315780faf1cbfe00991077a1e8c8e4c201f3b
> Author:        Kees Cook <kees@kernel.org>
> AuthorDate:    Fri, 14 Feb 2025 11:22:21 -08:00
> Committer:     Ingo Molnar <mingo@kernel.org>
> CommitterDate: Fri, 21 Feb 2025 15:38:11 +01:00

Ingo, seriously NO!
Re: [tip: x86/cpu] x86/kcfi: Require FRED for FineIBT
Posted by Peter Zijlstra 10 months ago
On Fri, Feb 21, 2025 at 08:00:24PM +0100, Peter Zijlstra wrote:
> On Fri, Feb 21, 2025 at 03:08:05PM -0000, tip-bot2 for Kees Cook wrote:
> > The following commit has been merged into the x86/cpu branch of tip:
> > 
> > Commit-ID:     f12315780faf1cbfe00991077a1e8c8e4c201f3b
> > Gitweb:        https://git.kernel.org/tip/f12315780faf1cbfe00991077a1e8c8e4c201f3b
> > Author:        Kees Cook <kees@kernel.org>
> > AuthorDate:    Fri, 14 Feb 2025 11:22:21 -08:00
> > Committer:     Ingo Molnar <mingo@kernel.org>
> > CommitterDate: Fri, 21 Feb 2025 15:38:11 +01:00
> 
> Ingo, seriously NO!

I've zapped the commit.
Re: [tip: x86/cpu] x86/kcfi: Require FRED for FineIBT
Posted by Ingo Molnar 10 months ago
* Peter Zijlstra <peterz@infradead.org> wrote:

> On Fri, Feb 21, 2025 at 08:00:24PM +0100, Peter Zijlstra wrote:
> > On Fri, Feb 21, 2025 at 03:08:05PM -0000, tip-bot2 for Kees Cook wrote:
> > > The following commit has been merged into the x86/cpu branch of tip:
> > > 
> > > Commit-ID:     f12315780faf1cbfe00991077a1e8c8e4c201f3b
> > > Gitweb:        https://git.kernel.org/tip/f12315780faf1cbfe00991077a1e8c8e4c201f3b
> > > Author:        Kees Cook <kees@kernel.org>
> > > AuthorDate:    Fri, 14 Feb 2025 11:22:21 -08:00
> > > Committer:     Ingo Molnar <mingo@kernel.org>
> > > CommitterDate: Fri, 21 Feb 2025 15:38:11 +01:00
> > 
> > Ingo, seriously NO!
> 
> I've zapped the commit.

I've also re-integrated tip:master to make sure it doesn't go out to -next.
Sorry about that ...

Thanks,

	Ingo