[PATCH] x86/cpu: Add comment clarifying CRn pinning

Peter Zijlstra posted 1 patch 2 weeks ago
There is a newer version of this series
arch/x86/kernel/cpu/common.c |   13 +++++++++++++
1 file changed, 13 insertions(+)
[PATCH] x86/cpu: Add comment clarifying CRn pinning
Posted by Peter Zijlstra 2 weeks ago

Since Boris wanted a nice patch to just press 'apply' on, here goes :-)


---
Subject: x86/cpu: Add comment clarifying CRn pinning
From: Peter Zijlstra <peterz@infradead.org>
Date: Wed, 18 Mar 2026 23:09:39 +0100

To avoid future confusion on the purpose and design of the CRn pinning
code.

Also note that if the attacker controls page-tables, the CRn bits
loose much of the attraction anyway.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 arch/x86/kernel/cpu/common.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)

--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -434,6 +434,19 @@ static __always_inline void setup_lass(s
 /* These bits should not change their value after CPU init is finished. */
 static const unsigned long cr4_pinned_mask = X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP |
 					     X86_CR4_FSGSBASE | X86_CR4_CET | X86_CR4_FRED;
+
+/*
+ * The CR pinning protects against ROP on the 'mov %reg, %CRn' instruction(s).
+ * Since you can ROP directly to these instructions (barring shadow stack),
+ * any protection must follow immediately and unconditionally after that.
+ *
+ * Specifically, the CR[04] write functions below will have the value
+ * validation controlled by the @cr_pinning static_branch which is
+ * __ro_after_init, just like the cr4_pinned_bits value.
+ *
+ * Once set, an attacker will have to defeat page-tables to get around these
+ * restrictions. Which is a much bigger ask than 'simple' ROP.
+ */
 static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning);
 static unsigned long cr4_pinned_bits __ro_after_init;
Re: [PATCH] x86/cpu: Add comment clarifying CRn pinning
Posted by Borislav Petkov 2 weeks ago
On Fri, Mar 20, 2026 at 10:25:21AM +0100, Peter Zijlstra wrote:
> 
> Since Boris wanted a nice patch to just press 'apply' on, here goes :-)

/me presses that key!

Thanks man!

:-P

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
[tip: x86/urgent] x86/cpu: Add comment clarifying CRn pinning
Posted by tip-bot2 for Peter Zijlstra 1 week, 4 days ago
The following commit has been merged into the x86/urgent branch of tip:

Commit-ID:     a3e93cac25316aad03bf561e3c205f4ca0b8f452
Gitweb:        https://git.kernel.org/tip/a3e93cac25316aad03bf561e3c205f4ca0b8f452
Author:        Peter Zijlstra <peterz@infradead.org>
AuthorDate:    Fri, 20 Mar 2026 10:25:21 +01:00
Committer:     Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Mon, 23 Mar 2026 14:25:53 +01:00

x86/cpu: Add comment clarifying CRn pinning

To avoid future confusion on the purpose and design of the CRn pinning code.

Also note that if the attacker controls page-tables, the CRn bits lose much of
the attraction anyway.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://patch.msgid.link/20260320092521.GG3739106@noisy.programming.kicks-ass.net
---
 arch/x86/kernel/cpu/common.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index c57e897..ec06701 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -434,6 +434,19 @@ static __always_inline void setup_lass(struct cpuinfo_x86 *c)
 /* These bits should not change their value after CPU init is finished. */
 static const unsigned long cr4_pinned_mask = X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP |
 					     X86_CR4_FSGSBASE | X86_CR4_CET;
+
+/*
+ * The CR pinning protects against ROP on the 'mov %reg, %CRn' instruction(s).
+ * Since you can ROP directly to these instructions (barring shadow stack),
+ * any protection must follow immediately and unconditionally after that.
+ *
+ * Specifically, the CR[04] write functions below will have the value
+ * validation controlled by the @cr_pinning static_branch which is
+ * __ro_after_init, just like the cr4_pinned_bits value.
+ *
+ * Once set, an attacker will have to defeat page-tables to get around these
+ * restrictions. Which is a much bigger ask than 'simple' ROP.
+ */
 static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning);
 static unsigned long cr4_pinned_bits __ro_after_init;