mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode
@ 2026-03-05 21:40 Sohil Mehta
  2026-03-05 21:40 ` [PATCH v2 1/5] x86/vsyscall: Reorganize the page fault emulation code Sohil Mehta
                   ` (6 more replies)
  0 siblings, 7 replies; 21+ messages in thread
From: Sohil Mehta @ 2026-03-05 21:40 UTC (permalink / raw)
  To: Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	H . Peter Anvin, Peter Zijlstra, Sohil Mehta, Kiryl Shutsemau,
	Brendan Jackman, Sean Christopherson, Nam Cao, Cedric Xing,
	Rick Edgecombe, Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

Linear Address Space Separation (LASS) is currently disabled [1] when
support for vsyscall emulation is configured. This series extends LASS
support specifically to the default XONLY mode (vsyscall=xonly).

Changes in v2
-------------
- Pick up review tags from Dave.
- Improve commit messages based on feedback from Dave and Peter.
- Minor change in patch 4 to avoid unnecessary clearing of CR4.LASS.

v1: https://lore.kernel.org/lkml/20260219233600.154313-1-sohil.mehta@intel.com/

Patches
-------
These patches were originally part of the v10 LASS series [2] before
being split out into a smaller series to make it easier to review and
merge. The overall approach to enable vsyscall support was okayed by
Andy Lutomirski [3].

The patches are based on the tip x86/cpu branch which has the recently
merged LASS-EFI series [4].

Issue
-----
Userspace attempts to access any kernel address generate a #GP when LASS
is enabled. Legacy vsyscall functions are located in the address range
0xffffffffff600000 - 0xffffffffff601000. Prior to LASS, default access
(XONLY) to the vsyscall page would generate a page fault and the access
would be emulated in the kernel. Currently, as the #GP handler lacks any
emulation support, LASS is disabled when config X86_VSYSCALL_EMULATION
is set.

Solution
--------
These patches primarily update the #GP handler to reuse the existing
vsyscall emulation code for #PF. In XONLY mode, the faulting RIP is
readily available and can be used to determine if the #GP was triggered
due to a vsyscall access.

In contrast, the vsyscall EMULATE mode is deprecated and not expected to
be used by anyone. Supporting EMULATE mode with LASS would require
complex instruction decoding in the #GP fault handler, which is not
worth the effort. So, LASS is disabled in the rare case when someone
absolutely needs to enable vsyscall=emulate via the command line.

Please find more details in the individual commit messages.

Links
-----
[1]: https://lore.kernel.org/lkml/20251118182911.2983253-1-sohil.mehta@intel.com/
[2]: https://lore.kernel.org/lkml/20251007065119.148605-1-sohil.mehta@intel.com/
[3]: https://lore.kernel.org/lkml/f4ae0030-9bc2-4675-ae43-e477cd894750@app.fastmail.com/
[4]: https://lore.kernel.org/lkml/20260120234730.2215498-1-sohil.mehta@intel.com/

Sohil Mehta (5):
  x86/vsyscall: Reorganize the page fault emulation code
  x86/traps: Consolidate user fixups in the #GP handler
  x86/vsyscall: Restore vsyscall=xonly mode under LASS
  x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE
  x86/cpu: Remove LASS restriction on vsyscall emulation

 .../admin-guide/kernel-parameters.txt         |  4 +-
 arch/x86/entry/vsyscall/vsyscall_64.c         | 89 +++++++++++--------
 arch/x86/include/asm/vsyscall.h               | 13 ++-
 arch/x86/kernel/cpu/common.c                  | 15 ----
 arch/x86/kernel/traps.c                       | 12 +--
 arch/x86/kernel/umip.c                        |  3 +
 arch/x86/mm/fault.c                           |  2 +-
 7 files changed, 77 insertions(+), 61 deletions(-)


base-commit: 68400c1aaf02636a97c45ba198110b66feb270a9
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 1/5] x86/vsyscall: Reorganize the page fault emulation code
  2026-03-05 21:40 [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode Sohil Mehta
@ 2026-03-05 21:40 ` Sohil Mehta
  2026-03-05 22:36   ` H. Peter Anvin
  2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
  2026-03-05 21:40 ` [PATCH v2 2/5] x86/traps: Consolidate user fixups in the #GP handler Sohil Mehta
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 21+ messages in thread
From: Sohil Mehta @ 2026-03-05 21:40 UTC (permalink / raw)
  To: Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	H . Peter Anvin, Peter Zijlstra, Sohil Mehta, Kiryl Shutsemau,
	Brendan Jackman, Sean Christopherson, Nam Cao, Cedric Xing,
	Rick Edgecombe, Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

With LASS, vsyscall page accesses will cause a #GP instead of a #PF.
Separate out the core vsyscall emulation code from the #PF specific
handling in preparation for the upcoming #GP emulation.

No functional change intended.

Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
---
v2:
 - No change
---
 arch/x86/entry/vsyscall/vsyscall_64.c | 64 ++++++++++++++-------------
 arch/x86/include/asm/vsyscall.h       |  7 ++-
 arch/x86/mm/fault.c                   |  2 +-
 3 files changed, 37 insertions(+), 36 deletions(-)

diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
index 4bd1e271bb22..5c6559c37c5b 100644
--- a/arch/x86/entry/vsyscall/vsyscall_64.c
+++ b/arch/x86/entry/vsyscall/vsyscall_64.c
@@ -111,43 +111,13 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size)
 	}
 }
 
-bool emulate_vsyscall(unsigned long error_code,
-		      struct pt_regs *regs, unsigned long address)
+static bool __emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 {
 	unsigned long caller;
 	int vsyscall_nr, syscall_nr, tmp;
 	long ret;
 	unsigned long orig_dx;
 
-	/* Write faults or kernel-privilege faults never get fixed up. */
-	if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER)
-		return false;
-
-	/*
-	 * Assume that faults at regs->ip are because of an
-	 * instruction fetch. Return early and avoid
-	 * emulation for faults during data accesses:
-	 */
-	if (address != regs->ip) {
-		/* Failed vsyscall read */
-		if (vsyscall_mode == EMULATE)
-			return false;
-
-		/*
-		 * User code tried and failed to read the vsyscall page.
-		 */
-		warn_bad_vsyscall(KERN_INFO, regs, "vsyscall read attempt denied -- look up the vsyscall kernel parameter if you need a workaround");
-		return false;
-	}
-
-	/*
-	 * X86_PF_INSTR is only set when NX is supported.  When
-	 * available, use it to double-check that the emulation code
-	 * is only being used for instruction fetches:
-	 */
-	if (cpu_feature_enabled(X86_FEATURE_NX))
-		WARN_ON_ONCE(!(error_code & X86_PF_INSTR));
-
 	/*
 	 * No point in checking CS -- the only way to get here is a user mode
 	 * trap to a high address, which means that we're in 64-bit user code.
@@ -280,6 +250,38 @@ bool emulate_vsyscall(unsigned long error_code,
 	return true;
 }
 
+bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs,
+			 unsigned long address)
+{
+	/* Write faults or kernel-privilege faults never get fixed up. */
+	if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER)
+		return false;
+
+	/*
+	 * Assume that faults at regs->ip are because of an instruction
+	 * fetch. Return early and avoid emulation for faults during
+	 * data accesses:
+	 */
+	if (address != regs->ip) {
+		 /* User code tried and failed to read the vsyscall page. */
+		if (vsyscall_mode != EMULATE)
+			warn_bad_vsyscall(KERN_INFO, regs,
+					  "vsyscall read attempt denied -- look up the vsyscall kernel parameter if you need a workaround");
+
+		return false;
+	}
+
+	/*
+	 * X86_PF_INSTR is only set when NX is supported.  When
+	 * available, use it to double-check that the emulation code
+	 * is only being used for instruction fetches:
+	 */
+	if (cpu_feature_enabled(X86_FEATURE_NX))
+		WARN_ON_ONCE(!(error_code & X86_PF_INSTR));
+
+	return __emulate_vsyscall(regs, address);
+}
+
 /*
  * A pseudo VMA to allow ptrace access for the vsyscall page.  This only
  * covers the 64bit vsyscall page now. 32bit has a real VMA now and does
diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
index 472f0263dbc6..f34902364972 100644
--- a/arch/x86/include/asm/vsyscall.h
+++ b/arch/x86/include/asm/vsyscall.h
@@ -14,12 +14,11 @@ extern void set_vsyscall_pgtable_user_bits(pgd_t *root);
  * Called on instruction fetch fault in vsyscall page.
  * Returns true if handled.
  */
-extern bool emulate_vsyscall(unsigned long error_code,
-			     struct pt_regs *regs, unsigned long address);
+bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs, unsigned long address);
 #else
 static inline void map_vsyscall(void) {}
-static inline bool emulate_vsyscall(unsigned long error_code,
-				    struct pt_regs *regs, unsigned long address)
+static inline bool emulate_vsyscall_pf(unsigned long error_code,
+				       struct pt_regs *regs, unsigned long address)
 {
 	return false;
 }
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index b83a06739b51..f0e77e084482 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1314,7 +1314,7 @@ void do_user_addr_fault(struct pt_regs *regs,
 	 * to consider the PF_PK bit.
 	 */
 	if (is_vsyscall_vaddr(address)) {
-		if (emulate_vsyscall(error_code, regs, address))
+		if (emulate_vsyscall_pf(error_code, regs, address))
 			return;
 	}
 #endif
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 2/5] x86/traps: Consolidate user fixups in the #GP handler
  2026-03-05 21:40 [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode Sohil Mehta
  2026-03-05 21:40 ` [PATCH v2 1/5] x86/vsyscall: Reorganize the page fault emulation code Sohil Mehta
@ 2026-03-05 21:40 ` Sohil Mehta
  2026-03-05 22:22   ` H. Peter Anvin
                     ` (2 more replies)
  2026-03-05 21:40 ` [PATCH v2 3/5] x86/vsyscall: Restore vsyscall=xonly mode under LASS Sohil Mehta
                   ` (4 subsequent siblings)
  6 siblings, 3 replies; 21+ messages in thread
From: Sohil Mehta @ 2026-03-05 21:40 UTC (permalink / raw)
  To: Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	H . Peter Anvin, Peter Zijlstra, Sohil Mehta, Kiryl Shutsemau,
	Brendan Jackman, Sean Christopherson, Nam Cao, Cedric Xing,
	Rick Edgecombe, Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

Move the UMIP exception fixup under the common "if (user_mode(regs))"
condition where the rest of user mode fixups reside. Also, move the UMIP
feature check into its fixup function to keep the calling code
consistent and clean.

No functional change intended.

Suggested-by: Dave Hansen <dave.hansen@intel.com>
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
---
v2:
 - No change
---
 arch/x86/kernel/traps.c | 8 +++-----
 arch/x86/kernel/umip.c  | 3 +++
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 4dbff8ef9b1c..614a281bd419 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -921,11 +921,6 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
 
 	cond_local_irq_enable(regs);
 
-	if (static_cpu_has(X86_FEATURE_UMIP)) {
-		if (user_mode(regs) && fixup_umip_exception(regs))
-			goto exit;
-	}
-
 	if (v8086_mode(regs)) {
 		local_irq_enable();
 		handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
@@ -940,6 +935,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
 		if (fixup_vdso_exception(regs, X86_TRAP_GP, error_code, 0))
 			goto exit;
 
+		if (fixup_umip_exception(regs))
+			goto exit;
+
 		gp_user_force_sig_segv(regs, X86_TRAP_GP, error_code, desc);
 		goto exit;
 	}
diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index d432f3824f0c..3ce99cbcf187 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -354,6 +354,9 @@ bool fixup_umip_exception(struct pt_regs *regs)
 	void __user *uaddr;
 	struct insn insn;
 
+	if (!cpu_feature_enabled(X86_FEATURE_UMIP))
+		return false;
+
 	if (!regs)
 		return false;
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 3/5] x86/vsyscall: Restore vsyscall=xonly mode under LASS
  2026-03-05 21:40 [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode Sohil Mehta
  2026-03-05 21:40 ` [PATCH v2 1/5] x86/vsyscall: Reorganize the page fault emulation code Sohil Mehta
  2026-03-05 21:40 ` [PATCH v2 2/5] x86/traps: Consolidate user fixups in the #GP handler Sohil Mehta
@ 2026-03-05 21:40 ` Sohil Mehta
  2026-03-05 22:45   ` H. Peter Anvin
  2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
  2026-03-05 21:40 ` [PATCH v2 4/5] x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE Sohil Mehta
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 21+ messages in thread
From: Sohil Mehta @ 2026-03-05 21:40 UTC (permalink / raw)
  To: Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	H . Peter Anvin, Peter Zijlstra, Sohil Mehta, Kiryl Shutsemau,
	Brendan Jackman, Sean Christopherson, Nam Cao, Cedric Xing,
	Rick Edgecombe, Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

Background
==========
The vsyscall page is located in the high/kernel part of the address
space. Prior to LASS, a vsyscall page access from userspace would always
generate a #PF. The kernel emulates the accesses in the #PF handler and
returns the appropriate values to userspace.

Vsyscall emulation has two modes of operation, specified by the
vsyscall={xonly, emulate} kernel command line option. The vsyscall page
behaves as execute-only in XONLY mode or read-execute in EMULATE mode.
XONLY mode is the default and the only one expected to be commonly used.
The EMULATE mode has been deprecated since 2022 and is considered
insecure.

With LASS, a vsyscall page access triggers a #GP instead of a #PF.
Currently, LASS is only enabled when all vsyscall modes are disabled.

LASS with XONLY mode
====================
Now add support for LASS specifically with XONLY vsyscall emulation. For
XONLY mode, all that is needed is the faulting RIP, which is trivially
available regardless of the type of fault. Reuse the #PF emulation code
during the #GP when the fault address points to the vsyscall page.

As multiple fault handlers will now be using the emulation code, add a
sanity check to ensure that the fault truly happened in 64-bit user
mode.

LASS with EMULATE mode
======================
Supporting vsyscall=emulate with LASS is much harder because the #GP
doesn't provide enough error information (such as PFEC and CR2 as in
case of a #PF). So, complex instruction decoding would be required to
emulate this mode in the #GP handler.

This isn't worth the effort as remaining users of EMULATE mode can be
reasonably assumed to be niche users, who are already trading off
security for compatibility. LASS and vsyscall=emulate will be kept
mutually exclusive for simplicity.

Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
---
v2:
 - Rewrote the commit message
---
 arch/x86/entry/vsyscall/vsyscall_64.c | 22 +++++++++++++++++-----
 arch/x86/include/asm/vsyscall.h       |  6 ++++++
 arch/x86/kernel/traps.c               |  4 ++++
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
index 5c6559c37c5b..b34c8763d5e9 100644
--- a/arch/x86/entry/vsyscall/vsyscall_64.c
+++ b/arch/x86/entry/vsyscall/vsyscall_64.c
@@ -23,7 +23,7 @@
  * soon be no new userspace code that will ever use a vsyscall.
  *
  * The code in this file emulates vsyscalls when notified of a page
- * fault to a vsyscall address.
+ * fault or a general protection fault to a vsyscall address.
  */
 
 #include <linux/kernel.h>
@@ -118,10 +118,9 @@ static bool __emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 	long ret;
 	unsigned long orig_dx;
 
-	/*
-	 * No point in checking CS -- the only way to get here is a user mode
-	 * trap to a high address, which means that we're in 64-bit user code.
-	 */
+	/* Confirm that the fault happened in 64-bit user mode */
+	if (!user_64bit_mode(regs))
+		return false;
 
 	if (vsyscall_mode == NONE) {
 		warn_bad_vsyscall(KERN_INFO, regs,
@@ -282,6 +281,19 @@ bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs,
 	return __emulate_vsyscall(regs, address);
 }
 
+bool emulate_vsyscall_gp(struct pt_regs *regs)
+{
+	/* Without LASS, vsyscall accesses are expected to generate a #PF */
+	if (!cpu_feature_enabled(X86_FEATURE_LASS))
+		return false;
+
+	/* Emulate only if the RIP points to the vsyscall address */
+	if (!is_vsyscall_vaddr(regs->ip))
+		return false;
+
+	return __emulate_vsyscall(regs, regs->ip);
+}
+
 /*
  * A pseudo VMA to allow ptrace access for the vsyscall page.  This only
  * covers the 64bit vsyscall page now. 32bit has a real VMA now and does
diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
index f34902364972..538053b1656a 100644
--- a/arch/x86/include/asm/vsyscall.h
+++ b/arch/x86/include/asm/vsyscall.h
@@ -15,6 +15,7 @@ extern void set_vsyscall_pgtable_user_bits(pgd_t *root);
  * Returns true if handled.
  */
 bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs, unsigned long address);
+bool emulate_vsyscall_gp(struct pt_regs *regs);
 #else
 static inline void map_vsyscall(void) {}
 static inline bool emulate_vsyscall_pf(unsigned long error_code,
@@ -22,6 +23,11 @@ static inline bool emulate_vsyscall_pf(unsigned long error_code,
 {
 	return false;
 }
+
+static inline bool emulate_vsyscall_gp(struct pt_regs *regs)
+{
+	return false;
+}
 #endif
 
 /*
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 614a281bd419..0ca3912ecb7f 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -70,6 +70,7 @@
 #include <asm/tdx.h>
 #include <asm/cfi.h>
 #include <asm/msr.h>
+#include <asm/vsyscall.h>
 
 #ifdef CONFIG_X86_64
 #include <asm/x86_init.h>
@@ -938,6 +939,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
 		if (fixup_umip_exception(regs))
 			goto exit;
 
+		if (emulate_vsyscall_gp(regs))
+			goto exit;
+
 		gp_user_force_sig_segv(regs, X86_TRAP_GP, error_code, desc);
 		goto exit;
 	}
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 4/5] x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE
  2026-03-05 21:40 [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode Sohil Mehta
                   ` (2 preceding siblings ...)
  2026-03-05 21:40 ` [PATCH v2 3/5] x86/vsyscall: Restore vsyscall=xonly mode under LASS Sohil Mehta
@ 2026-03-05 21:40 ` Sohil Mehta
  2026-03-05 22:45   ` H. Peter Anvin
  2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
  2026-03-05 21:40 ` [PATCH v2 5/5] x86/cpu: Remove LASS restriction on vsyscall emulation Sohil Mehta
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 21+ messages in thread
From: Sohil Mehta @ 2026-03-05 21:40 UTC (permalink / raw)
  To: Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	H . Peter Anvin, Peter Zijlstra, Sohil Mehta, Kiryl Shutsemau,
	Brendan Jackman, Sean Christopherson, Nam Cao, Cedric Xing,
	Rick Edgecombe, Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

The EMULATE mode of vsyscall maps the vsyscall page with a high kernel
address directly into user address space. Reading the vsyscall page in
EMULATE mode would cause LASS to trigger a #GP.

Fixing the LASS violation in EMULATE mode would require complex
instruction decoding because the resulting #GP does include the
necessary error information, and the vsyscall address is not
readily available in the RIP.

The EMULATE mode has been deprecated since 2022 and can only be enabled
using the command line parameter vsyscall=emulate. See commit
bf00745e7791 ("x86/vsyscall: Remove CONFIG_LEGACY_VSYSCALL_EMULATE") for
details. At this point, no one is expected to be using this insecure
mode. The rare usages that need it obviously do not care about security.

Disable LASS when EMULATE mode is requested to avoid breaking legacy
user software. Also, update the vsyscall documentation to reflect this.
LASS will only be supported if vsyscall mode is set to XONLY (default)
or NONE.

Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
---
Eventually, the plan is to get rid of the EMULATE mode altogether. Linus
and AndyL seem to be okay with such a change. However, those changes are
beyond the scope of this series.

v2:
 - Picked up Dave's review tag
 - Removed unnecessary CR4 clearing during vsyscall_setup().
   CR4.LASS is enabled much later via a late_initcall().
---
 Documentation/admin-guide/kernel-parameters.txt | 4 +++-
 arch/x86/entry/vsyscall/vsyscall_64.c           | 5 +++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index cb850e5290c2..64df2c52b2e5 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -8376,7 +8376,9 @@ Kernel parameters
 
 			emulate     Vsyscalls turn into traps and are emulated
 			            reasonably safely.  The vsyscall page is
-				    readable.
+				    readable.  This disables the Linear
+				    Address Space Separation (LASS) security
+				    feature and makes the system less secure.
 
 			xonly       [default] Vsyscalls turn into traps and are
 			            emulated reasonably safely.  The vsyscall
diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
index b34c8763d5e9..215ae07dd3c7 100644
--- a/arch/x86/entry/vsyscall/vsyscall_64.c
+++ b/arch/x86/entry/vsyscall/vsyscall_64.c
@@ -62,6 +62,11 @@ static int __init vsyscall_setup(char *str)
 		else
 			return -EINVAL;
 
+		if (cpu_feature_enabled(X86_FEATURE_LASS) && vsyscall_mode == EMULATE) {
+			setup_clear_cpu_cap(X86_FEATURE_LASS);
+			pr_warn_once("x86/cpu: Disabling LASS due to vsyscall=emulate\n");
+		}
+
 		return 0;
 	}
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 5/5] x86/cpu: Remove LASS restriction on vsyscall emulation
  2026-03-05 21:40 [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode Sohil Mehta
                   ` (3 preceding siblings ...)
  2026-03-05 21:40 ` [PATCH v2 4/5] x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE Sohil Mehta
@ 2026-03-05 21:40 ` Sohil Mehta
  2026-03-05 22:46   ` H. Peter Anvin
  2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
  2026-03-05 23:21 ` [PATCH 0/1] x86/fault: cleanup: move x86-64 test into is_vsyscall_vaddr() H. Peter Anvin
  2026-03-08 10:38 ` [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode Maciej Wieczor-Retman
  6 siblings, 2 replies; 21+ messages in thread
From: Sohil Mehta @ 2026-03-05 21:40 UTC (permalink / raw)
  To: Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	H . Peter Anvin, Peter Zijlstra, Sohil Mehta, Kiryl Shutsemau,
	Brendan Jackman, Sean Christopherson, Nam Cao, Cedric Xing,
	Rick Edgecombe, Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

Vsyscall emulation has two modes of operation: XONLY and EMULATE. The
default XONLY mode is now supported with a LASS-triggered #GP. OTOH,
LASS is disabled if someone requests the deprecated EMULATE mode via the
vsyscall=emulate command line option. So, remove the restriction on LASS
when the overall vsyscall emulation support is compiled in.

As a result, there is no need for setup_lass() anymore. LASS is enabled
by default through a late_initcall().

Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
---
v2:
 - Picked up Dave's review tag
 - Improve commit message
---
 arch/x86/kernel/cpu/common.c | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 3557f0e6b3aa..02472fc763d9 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -406,20 +406,6 @@ static __always_inline void setup_umip(struct cpuinfo_x86 *c)
 	cr4_clear_bits(X86_CR4_UMIP);
 }
 
-static __always_inline void setup_lass(struct cpuinfo_x86 *c)
-{
-	if (!cpu_feature_enabled(X86_FEATURE_LASS))
-		return;
-
-	/*
-	 * Legacy vsyscall page access causes a #GP when LASS is active.
-	 * Disable LASS because the #GP handler doesn't support vsyscall
-	 * emulation.
-	 */
-	if (IS_ENABLED(CONFIG_X86_VSYSCALL_EMULATION))
-		setup_clear_cpu_cap(X86_FEATURE_LASS);
-}
-
 static int enable_lass(unsigned int cpu)
 {
 	cr4_set_bits(X86_CR4_LASS);
@@ -2061,7 +2047,6 @@ static void identify_cpu(struct cpuinfo_x86 *c)
 	setup_smep(c);
 	setup_smap(c);
 	setup_umip(c);
-	setup_lass(c);
 
 	/* Enable FSGSBASE instructions if available. */
 	if (cpu_has(c, X86_FEATURE_FSGSBASE)) {
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 2/5] x86/traps: Consolidate user fixups in the #GP handler
  2026-03-05 21:40 ` [PATCH v2 2/5] x86/traps: Consolidate user fixups in the #GP handler Sohil Mehta
@ 2026-03-05 22:22   ` H. Peter Anvin
  2026-03-05 22:41   ` H. Peter Anvin
  2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
  2 siblings, 0 replies; 21+ messages in thread
From: H. Peter Anvin @ 2026-03-05 22:22 UTC (permalink / raw)
  To: Sohil Mehta, Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	Peter Zijlstra, Kiryl Shutsemau, Brendan Jackman,
	Sean Christopherson, Nam Cao, Cedric Xing, Rick Edgecombe,
	Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

On 2026-03-05 13:40, Sohil Mehta wrote:
> Move the UMIP exception fixup under the common "if (user_mode(regs))"
> condition where the rest of user mode fixups reside. Also, move the UMIP
> feature check into its fixup function to keep the calling code
> consistent and clean.
> 
> No functional change intended.
> 
> Suggested-by: Dave Hansen <dave.hansen@intel.com>
> Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
> Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
> ---
> v2:
>  - No change
> ---
>  arch/x86/kernel/traps.c | 8 +++-----
>  arch/x86/kernel/umip.c  | 3 +++
>  2 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> index 4dbff8ef9b1c..614a281bd419 100644
> --- a/arch/x86/kernel/traps.c
> +++ b/arch/x86/kernel/traps.c
> @@ -921,11 +921,6 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
>  
>  	cond_local_irq_enable(regs);
>  
> -	if (static_cpu_has(X86_FEATURE_UMIP)) {
> -		if (user_mode(regs) && fixup_umip_exception(regs))
> -			goto exit;
> -	}
> -
>  	if (v8086_mode(regs)) {
>  		local_irq_enable();
>  		handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
> @@ -940,6 +935,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
>  		if (fixup_vdso_exception(regs, X86_TRAP_GP, error_code, 0))
>  			goto exit;
>  
> +		if (fixup_umip_exception(regs))
> +			goto exit;
> +
>  		gp_user_force_sig_segv(regs, X86_TRAP_GP, error_code, desc);
>  		goto exit;
>  	}
> diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
> index d432f3824f0c..3ce99cbcf187 100644
> --- a/arch/x86/kernel/umip.c
> +++ b/arch/x86/kernel/umip.c
> @@ -354,6 +354,9 @@ bool fixup_umip_exception(struct pt_regs *regs)
>  	void __user *uaddr;
>  	struct insn insn;
>  
> +	if (!cpu_feature_enabled(X86_FEATURE_UMIP))
> +		return false;
> +
>  	if (!regs)
>  		return false;
>  

[General comment, not really applicable to this patch]

I like this kind cleanups. However, if this had been a hot path (which it
isn't) and if UMIP wasn't very common (which it is), then it probably would be
desirable to push the cpu_feature_enabled() into the call site. This is
trivially done with an inline function in the header file where this is exported:

static inline bool fixup_umip_exception(struct pt_regs *regs)
{
	return cpu_feature_enabled(X86_FEATURE_UMIP) &&
		__fixup_umip_exception(regs);
}


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 1/5] x86/vsyscall: Reorganize the page fault emulation code
  2026-03-05 21:40 ` [PATCH v2 1/5] x86/vsyscall: Reorganize the page fault emulation code Sohil Mehta
@ 2026-03-05 22:36   ` H. Peter Anvin
  2026-03-06  0:49     ` Sohil Mehta
  2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
  1 sibling, 1 reply; 21+ messages in thread
From: H. Peter Anvin @ 2026-03-05 22:36 UTC (permalink / raw)
  To: Sohil Mehta, Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	Peter Zijlstra, Kiryl Shutsemau, Brendan Jackman,
	Sean Christopherson, Nam Cao, Cedric Xing, Rick Edgecombe,
	Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

On 2026-03-05 13:40, Sohil Mehta wrote:
> With LASS, vsyscall page accesses will cause a #GP instead of a #PF.
> Separate out the core vsyscall emulation code from the #PF specific
> handling in preparation for the upcoming #GP emulation.
> 
> No functional change intended.
> 
> Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
> Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
> ---
> v2:
>  - No change
> ---
>  arch/x86/entry/vsyscall/vsyscall_64.c | 64 ++++++++++++++-------------
>  arch/x86/include/asm/vsyscall.h       |  7 ++-
>  arch/x86/mm/fault.c                   |  2 +-
>  3 files changed, 37 insertions(+), 36 deletions(-)
> 
> diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
> index 4bd1e271bb22..5c6559c37c5b 100644
> --- a/arch/x86/entry/vsyscall/vsyscall_64.c
> +++ b/arch/x86/entry/vsyscall/vsyscall_64.c
> @@ -111,43 +111,13 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size)
>  	}
>  }
>  
> -bool emulate_vsyscall(unsigned long error_code,
> -		      struct pt_regs *regs, unsigned long address)
> +static bool __emulate_vsyscall(struct pt_regs *regs, unsigned long address)
>  {
>  	unsigned long caller;
>  	int vsyscall_nr, syscall_nr, tmp;
>  	long ret;
>  	unsigned long orig_dx;
>  
> -	/* Write faults or kernel-privilege faults never get fixed up. */
> -	if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER)
> -		return false;
> -
> -	/*
> -	 * Assume that faults at regs->ip are because of an
> -	 * instruction fetch. Return early and avoid
> -	 * emulation for faults during data accesses:
> -	 */
> -	if (address != regs->ip) {
> -		/* Failed vsyscall read */
> -		if (vsyscall_mode == EMULATE)
> -			return false;
> -
> -		/*
> -		 * User code tried and failed to read the vsyscall page.
> -		 */
> -		warn_bad_vsyscall(KERN_INFO, regs, "vsyscall read attempt denied -- look up the vsyscall kernel parameter if you need a workaround");
> -		return false;
> -	}
> -
> -	/*
> -	 * X86_PF_INSTR is only set when NX is supported.  When
> -	 * available, use it to double-check that the emulation code
> -	 * is only being used for instruction fetches:
> -	 */
> -	if (cpu_feature_enabled(X86_FEATURE_NX))
> -		WARN_ON_ONCE(!(error_code & X86_PF_INSTR));
> -
>  	/*
>  	 * No point in checking CS -- the only way to get here is a user mode
>  	 * trap to a high address, which means that we're in 64-bit user code.
> @@ -280,6 +250,38 @@ bool emulate_vsyscall(unsigned long error_code,
>  	return true;
>  }
>  
> +bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs,
> +			 unsigned long address)
> +{
> +	/* Write faults or kernel-privilege faults never get fixed up. */
> +	if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER)
> +		return false;


I think this can be tightened further.  If X86_PF_PK, X86_PF_SHSTK or
X86_PF_RSVD are set we should definitely not try to do any emulation, and I
believe the same is true for X86_PF_SGX or X86_PF_RMP; I'm not 100% as I don't
have the semantics of those bits in my head at the moment.

> +	/*
> +	 * Assume that faults at regs->ip are because of an instruction
> +	 * fetch. Return early and avoid emulation for faults during
> +	 * data accesses:
> +	 */
> +	if (address != regs->ip) {
> +		 /* User code tried and failed to read the vsyscall page. */
> +		if (vsyscall_mode != EMULATE)
> +			warn_bad_vsyscall(KERN_INFO, regs,
> +					  "vsyscall read attempt denied -- look up the vsyscall kernel parameter if you need a workaround");
> +
> +		return false;
> +	}
> +

I don't really like the reshuffling of the code here.

> +	/*
> +	 * X86_PF_INSTR is only set when NX is supported.  When
> +	 * available, use it to double-check that the emulation code
> +	 * is only being used for instruction fetches:
> +	 */
> +	if (cpu_feature_enabled(X86_FEATURE_NX))
> +		WARN_ON_ONCE(!(error_code & X86_PF_INSTR));
> +

I realize this is the same as the previous code, but I really think this
should have a "return false;" in it as well.

> +	return __emulate_vsyscall(regs, address);
> +}
> +
>  /*
>   * A pseudo VMA to allow ptrace access for the vsyscall page.  This only
>   * covers the 64bit vsyscall page now. 32bit has a real VMA now and does
> diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
> index 472f0263dbc6..f34902364972 100644
> --- a/arch/x86/include/asm/vsyscall.h
> +++ b/arch/x86/include/asm/vsyscall.h
> @@ -14,12 +14,11 @@ extern void set_vsyscall_pgtable_user_bits(pgd_t *root);
>   * Called on instruction fetch fault in vsyscall page.
>   * Returns true if handled.
>   */
> -extern bool emulate_vsyscall(unsigned long error_code,
> -			     struct pt_regs *regs, unsigned long address);
> +bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs, unsigned long address);
>  #else
>  static inline void map_vsyscall(void) {}
> -static inline bool emulate_vsyscall(unsigned long error_code,
> -				    struct pt_regs *regs, unsigned long address)
> +static inline bool emulate_vsyscall_pf(unsigned long error_code,
> +				       struct pt_regs *regs, unsigned long address)
>  {
>  	return false;
>  }
> diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
> index b83a06739b51..f0e77e084482 100644
> --- a/arch/x86/mm/fault.c
> +++ b/arch/x86/mm/fault.c
> @@ -1314,7 +1314,7 @@ void do_user_addr_fault(struct pt_regs *regs,
>  	 * to consider the PF_PK bit.
>  	 */
>  	if (is_vsyscall_vaddr(address)) {
> -		if (emulate_vsyscall(error_code, regs, address))
> +		if (emulate_vsyscall_pf(error_code, regs, address))
>  			return;
>  	}
>  #endif


Other than the above minor nitpicks, looks good to me.

Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 2/5] x86/traps: Consolidate user fixups in the #GP handler
  2026-03-05 21:40 ` [PATCH v2 2/5] x86/traps: Consolidate user fixups in the #GP handler Sohil Mehta
  2026-03-05 22:22   ` H. Peter Anvin
@ 2026-03-05 22:41   ` H. Peter Anvin
  2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
  2 siblings, 0 replies; 21+ messages in thread
From: H. Peter Anvin @ 2026-03-05 22:41 UTC (permalink / raw)
  To: Sohil Mehta, Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	Peter Zijlstra, Kiryl Shutsemau, Brendan Jackman,
	Sean Christopherson, Nam Cao, Cedric Xing, Rick Edgecombe,
	Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

On 2026-03-05 13:40, Sohil Mehta wrote:
> Move the UMIP exception fixup under the common "if (user_mode(regs))"
> condition where the rest of user mode fixups reside. Also, move the UMIP
> feature check into its fixup function to keep the calling code
> consistent and clean.
> 
> No functional change intended.
> 
> Suggested-by: Dave Hansen <dave.hansen@intel.com>
> Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
> Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
> ---
> v2:
>  - No change
> ---
>  arch/x86/kernel/traps.c | 8 +++-----
>  arch/x86/kernel/umip.c  | 3 +++
>  2 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> index 4dbff8ef9b1c..614a281bd419 100644
> --- a/arch/x86/kernel/traps.c
> +++ b/arch/x86/kernel/traps.c
> @@ -921,11 +921,6 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
>  
>  	cond_local_irq_enable(regs);
>  
> -	if (static_cpu_has(X86_FEATURE_UMIP)) {
> -		if (user_mode(regs) && fixup_umip_exception(regs))
> -			goto exit;
> -	}
> -
>  	if (v8086_mode(regs)) {
>  		local_irq_enable();
>  		handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
> @@ -940,6 +935,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
>  		if (fixup_vdso_exception(regs, X86_TRAP_GP, error_code, 0))
>  			goto exit;
>  
> +		if (fixup_umip_exception(regs))
> +			goto exit;
> +
>  		gp_user_force_sig_segv(regs, X86_TRAP_GP, error_code, desc);
>  		goto exit;
>  	}
> diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
> index d432f3824f0c..3ce99cbcf187 100644
> --- a/arch/x86/kernel/umip.c
> +++ b/arch/x86/kernel/umip.c
> @@ -354,6 +354,9 @@ bool fixup_umip_exception(struct pt_regs *regs)
>  	void __user *uaddr;
>  	struct insn insn;
>  
> +	if (!cpu_feature_enabled(X86_FEATURE_UMIP))
> +		return false;
> +
>  	if (!regs)
>  		return false;
>  

Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 3/5] x86/vsyscall: Restore vsyscall=xonly mode under LASS
  2026-03-05 21:40 ` [PATCH v2 3/5] x86/vsyscall: Restore vsyscall=xonly mode under LASS Sohil Mehta
@ 2026-03-05 22:45   ` H. Peter Anvin
  2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
  1 sibling, 0 replies; 21+ messages in thread
From: H. Peter Anvin @ 2026-03-05 22:45 UTC (permalink / raw)
  To: Sohil Mehta, Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	Peter Zijlstra, Kiryl Shutsemau, Brendan Jackman,
	Sean Christopherson, Nam Cao, Cedric Xing, Rick Edgecombe,
	Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

On 2026-03-05 13:40, Sohil Mehta wrote:
> Background
> ==========
> The vsyscall page is located in the high/kernel part of the address
> space. Prior to LASS, a vsyscall page access from userspace would always
> generate a #PF. The kernel emulates the accesses in the #PF handler and
> returns the appropriate values to userspace.
> 
> Vsyscall emulation has two modes of operation, specified by the
> vsyscall={xonly, emulate} kernel command line option. The vsyscall page
> behaves as execute-only in XONLY mode or read-execute in EMULATE mode.
> XONLY mode is the default and the only one expected to be commonly used.
> The EMULATE mode has been deprecated since 2022 and is considered
> insecure.
> 
> With LASS, a vsyscall page access triggers a #GP instead of a #PF.
> Currently, LASS is only enabled when all vsyscall modes are disabled.
> 
> LASS with XONLY mode
> ====================
> Now add support for LASS specifically with XONLY vsyscall emulation. For
> XONLY mode, all that is needed is the faulting RIP, which is trivially
> available regardless of the type of fault. Reuse the #PF emulation code
> during the #GP when the fault address points to the vsyscall page.
> 
> As multiple fault handlers will now be using the emulation code, add a
> sanity check to ensure that the fault truly happened in 64-bit user
> mode.
> 
> LASS with EMULATE mode
> ======================
> Supporting vsyscall=emulate with LASS is much harder because the #GP
> doesn't provide enough error information (such as PFEC and CR2 as in
> case of a #PF). So, complex instruction decoding would be required to
> emulate this mode in the #GP handler.
> 
> This isn't worth the effort as remaining users of EMULATE mode can be
> reasonably assumed to be niche users, who are already trading off
> security for compatibility. LASS and vsyscall=emulate will be kept
> mutually exclusive for simplicity.
> 
> Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
> ---
> v2:
>  - Rewrote the commit message
> ---
>  arch/x86/entry/vsyscall/vsyscall_64.c | 22 +++++++++++++++++-----
>  arch/x86/include/asm/vsyscall.h       |  6 ++++++
>  arch/x86/kernel/traps.c               |  4 ++++
>  3 files changed, 27 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
> index 5c6559c37c5b..b34c8763d5e9 100644
> --- a/arch/x86/entry/vsyscall/vsyscall_64.c
> +++ b/arch/x86/entry/vsyscall/vsyscall_64.c
> @@ -23,7 +23,7 @@
>   * soon be no new userspace code that will ever use a vsyscall.
>   *
>   * The code in this file emulates vsyscalls when notified of a page
> - * fault to a vsyscall address.
> + * fault or a general protection fault to a vsyscall address.
>   */
>  
>  #include <linux/kernel.h>
> @@ -118,10 +118,9 @@ static bool __emulate_vsyscall(struct pt_regs *regs, unsigned long address)
>  	long ret;
>  	unsigned long orig_dx;
>  
> -	/*
> -	 * No point in checking CS -- the only way to get here is a user mode
> -	 * trap to a high address, which means that we're in 64-bit user code.
> -	 */
> +	/* Confirm that the fault happened in 64-bit user mode */
> +	if (!user_64bit_mode(regs))
> +		return false;
>  
>  	if (vsyscall_mode == NONE) {
>  		warn_bad_vsyscall(KERN_INFO, regs,
> @@ -282,6 +281,19 @@ bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs,
>  	return __emulate_vsyscall(regs, address);
>  }
>  
> +bool emulate_vsyscall_gp(struct pt_regs *regs)
> +{
> +	/* Without LASS, vsyscall accesses are expected to generate a #PF */
> +	if (!cpu_feature_enabled(X86_FEATURE_LASS))
> +		return false;
> +
> +	/* Emulate only if the RIP points to the vsyscall address */
> +	if (!is_vsyscall_vaddr(regs->ip))
> +		return false;
> +
> +	return __emulate_vsyscall(regs, regs->ip);
> +}
> +
>  /*
>   * A pseudo VMA to allow ptrace access for the vsyscall page.  This only
>   * covers the 64bit vsyscall page now. 32bit has a real VMA now and does
> diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
> index f34902364972..538053b1656a 100644
> --- a/arch/x86/include/asm/vsyscall.h
> +++ b/arch/x86/include/asm/vsyscall.h
> @@ -15,6 +15,7 @@ extern void set_vsyscall_pgtable_user_bits(pgd_t *root);
>   * Returns true if handled.
>   */
>  bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs, unsigned long address);
> +bool emulate_vsyscall_gp(struct pt_regs *regs);
>  #else
>  static inline void map_vsyscall(void) {}
>  static inline bool emulate_vsyscall_pf(unsigned long error_code,
> @@ -22,6 +23,11 @@ static inline bool emulate_vsyscall_pf(unsigned long error_code,
>  {
>  	return false;
>  }
> +
> +static inline bool emulate_vsyscall_gp(struct pt_regs *regs)
> +{
> +	return false;
> +}
>  #endif
>  
>  /*
> diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> index 614a281bd419..0ca3912ecb7f 100644
> --- a/arch/x86/kernel/traps.c
> +++ b/arch/x86/kernel/traps.c
> @@ -70,6 +70,7 @@
>  #include <asm/tdx.h>
>  #include <asm/cfi.h>
>  #include <asm/msr.h>
> +#include <asm/vsyscall.h>
>  
>  #ifdef CONFIG_X86_64
>  #include <asm/x86_init.h>
> @@ -938,6 +939,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
>  		if (fixup_umip_exception(regs))
>  			goto exit;
>  
> +		if (emulate_vsyscall_gp(regs))
> +			goto exit;
> +
>  		gp_user_force_sig_segv(regs, X86_TRAP_GP, error_code, desc);
>  		goto exit;
>  	}

Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 4/5] x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE
  2026-03-05 21:40 ` [PATCH v2 4/5] x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE Sohil Mehta
@ 2026-03-05 22:45   ` H. Peter Anvin
  2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
  1 sibling, 0 replies; 21+ messages in thread
From: H. Peter Anvin @ 2026-03-05 22:45 UTC (permalink / raw)
  To: Sohil Mehta, Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	Peter Zijlstra, Kiryl Shutsemau, Brendan Jackman,
	Sean Christopherson, Nam Cao, Cedric Xing, Rick Edgecombe,
	Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

On 2026-03-05 13:40, Sohil Mehta wrote:
> The EMULATE mode of vsyscall maps the vsyscall page with a high kernel
> address directly into user address space. Reading the vsyscall page in
> EMULATE mode would cause LASS to trigger a #GP.
> 
> Fixing the LASS violation in EMULATE mode would require complex
> instruction decoding because the resulting #GP does include the
> necessary error information, and the vsyscall address is not
> readily available in the RIP.
> 
> The EMULATE mode has been deprecated since 2022 and can only be enabled
> using the command line parameter vsyscall=emulate. See commit
> bf00745e7791 ("x86/vsyscall: Remove CONFIG_LEGACY_VSYSCALL_EMULATE") for
> details. At this point, no one is expected to be using this insecure
> mode. The rare usages that need it obviously do not care about security.
> 
> Disable LASS when EMULATE mode is requested to avoid breaking legacy
> user software. Also, update the vsyscall documentation to reflect this.
> LASS will only be supported if vsyscall mode is set to XONLY (default)
> or NONE.
> 
> Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
> Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
> ---
> Eventually, the plan is to get rid of the EMULATE mode altogether. Linus
> and AndyL seem to be okay with such a change. However, those changes are
> beyond the scope of this series.
> 
> v2:
>  - Picked up Dave's review tag
>  - Removed unnecessary CR4 clearing during vsyscall_setup().
>    CR4.LASS is enabled much later via a late_initcall().
> ---
>  Documentation/admin-guide/kernel-parameters.txt | 4 +++-
>  arch/x86/entry/vsyscall/vsyscall_64.c           | 5 +++++
>  2 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index cb850e5290c2..64df2c52b2e5 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -8376,7 +8376,9 @@ Kernel parameters
>  
>  			emulate     Vsyscalls turn into traps and are emulated
>  			            reasonably safely.  The vsyscall page is
> -				    readable.
> +				    readable.  This disables the Linear
> +				    Address Space Separation (LASS) security
> +				    feature and makes the system less secure.
>  
>  			xonly       [default] Vsyscalls turn into traps and are
>  			            emulated reasonably safely.  The vsyscall
> diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
> index b34c8763d5e9..215ae07dd3c7 100644
> --- a/arch/x86/entry/vsyscall/vsyscall_64.c
> +++ b/arch/x86/entry/vsyscall/vsyscall_64.c
> @@ -62,6 +62,11 @@ static int __init vsyscall_setup(char *str)
>  		else
>  			return -EINVAL;
>  
> +		if (cpu_feature_enabled(X86_FEATURE_LASS) && vsyscall_mode == EMULATE) {
> +			setup_clear_cpu_cap(X86_FEATURE_LASS);
> +			pr_warn_once("x86/cpu: Disabling LASS due to vsyscall=emulate\n");
> +		}
> +
>  		return 0;
>  	}
>  

Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 5/5] x86/cpu: Remove LASS restriction on vsyscall emulation
  2026-03-05 21:40 ` [PATCH v2 5/5] x86/cpu: Remove LASS restriction on vsyscall emulation Sohil Mehta
@ 2026-03-05 22:46   ` H. Peter Anvin
  2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
  1 sibling, 0 replies; 21+ messages in thread
From: H. Peter Anvin @ 2026-03-05 22:46 UTC (permalink / raw)
  To: Sohil Mehta, Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	Peter Zijlstra, Kiryl Shutsemau, Brendan Jackman,
	Sean Christopherson, Nam Cao, Cedric Xing, Rick Edgecombe,
	Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

On 2026-03-05 13:40, Sohil Mehta wrote:
> Vsyscall emulation has two modes of operation: XONLY and EMULATE. The
> default XONLY mode is now supported with a LASS-triggered #GP. OTOH,
> LASS is disabled if someone requests the deprecated EMULATE mode via the
> vsyscall=emulate command line option. So, remove the restriction on LASS
> when the overall vsyscall emulation support is compiled in.
> 
> As a result, there is no need for setup_lass() anymore. LASS is enabled
> by default through a late_initcall().
> 
> Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
> Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
> ---
> v2:
>  - Picked up Dave's review tag
>  - Improve commit message
> ---
>  arch/x86/kernel/cpu/common.c | 15 ---------------
>  1 file changed, 15 deletions(-)
> 
> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> index 3557f0e6b3aa..02472fc763d9 100644
> --- a/arch/x86/kernel/cpu/common.c
> +++ b/arch/x86/kernel/cpu/common.c
> @@ -406,20 +406,6 @@ static __always_inline void setup_umip(struct cpuinfo_x86 *c)
>  	cr4_clear_bits(X86_CR4_UMIP);
>  }
>  
> -static __always_inline void setup_lass(struct cpuinfo_x86 *c)
> -{
> -	if (!cpu_feature_enabled(X86_FEATURE_LASS))
> -		return;
> -
> -	/*
> -	 * Legacy vsyscall page access causes a #GP when LASS is active.
> -	 * Disable LASS because the #GP handler doesn't support vsyscall
> -	 * emulation.
> -	 */
> -	if (IS_ENABLED(CONFIG_X86_VSYSCALL_EMULATION))
> -		setup_clear_cpu_cap(X86_FEATURE_LASS);
> -}
> -
>  static int enable_lass(unsigned int cpu)
>  {
>  	cr4_set_bits(X86_CR4_LASS);
> @@ -2061,7 +2047,6 @@ static void identify_cpu(struct cpuinfo_x86 *c)
>  	setup_smep(c);
>  	setup_smap(c);
>  	setup_umip(c);
> -	setup_lass(c);
>  
>  	/* Enable FSGSBASE instructions if available. */
>  	if (cpu_has(c, X86_FEATURE_FSGSBASE)) {

Love a patch that just deletes code!

Reviewed-by: H> Peter Anvin (Intel) <hpa@zytor.com>


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 0/1] x86/fault: cleanup: move x86-64 test into is_vsyscall_vaddr()
  2026-03-05 21:40 [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode Sohil Mehta
                   ` (4 preceding siblings ...)
  2026-03-05 21:40 ` [PATCH v2 5/5] x86/cpu: Remove LASS restriction on vsyscall emulation Sohil Mehta
@ 2026-03-05 23:21 ` H. Peter Anvin
  2026-03-05 23:21   ` [PATCH 1/1] " H. Peter Anvin
  2026-03-08 10:38 ` [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode Maciej Wieczor-Retman
  6 siblings, 1 reply; 21+ messages in thread
From: H. Peter Anvin @ 2026-03-05 23:21 UTC (permalink / raw)
  To: Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: H. Peter Anvin, Jonathan Corbet, Shuah Khan, Thomas Gleixner,
	Ingo Molnar, Peter Zijlstra, Sohil Mehta, linux-kernel

Reviewing Sohil's LASS patchset inspired me to cook up a very small
cleanup patch, removing some unnecessary conditional compilation. It
is on top of Sohil's patchset, but it is really orthogonal to it; the
patch applies with fuzz (line changes and the renaming of
emulate_vsyscall() to emulate_vsyscall_pf() in the context) to the
unmodified upstream kernel as well.

	 -hpa

---
 arch/x86/include/asm/vsyscall.h | 3 ++-
 arch/x86/mm/fault.c             | 4 +---
 2 files changed, 3 insertions(+), 4 deletions(-)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/1] x86/fault: cleanup: move x86-64 test into is_vsyscall_vaddr()
  2026-03-05 23:21 ` [PATCH 0/1] x86/fault: cleanup: move x86-64 test into is_vsyscall_vaddr() H. Peter Anvin
@ 2026-03-05 23:21   ` H. Peter Anvin
  0 siblings, 0 replies; 21+ messages in thread
From: H. Peter Anvin @ 2026-03-05 23:21 UTC (permalink / raw)
  To: Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: H. Peter Anvin, Jonathan Corbet, Shuah Khan, Thomas Gleixner,
	Ingo Molnar, Peter Zijlstra, Sohil Mehta, linux-kernel

In one location, there is an IS_ENABLED(CONFIG_X86_64) before calling
is_vsyscall_vaddr(), in another the whole thing is under #ifdef.

Moving IS_ENABLED(CONFIG_X86_64) into is_vsyscall_vaddr(), which is an
inline function anyway, eliminates the need for both.

This exposes a dummy call to emulate_vsyscall() to the compiler on
x86-32, but that is perfectly OK since the stub inline for
!CONFIG_X86_VSYSCALL_EMULATION is available even when compiling for
x86-32.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
---
 arch/x86/include/asm/vsyscall.h | 3 ++-
 arch/x86/mm/fault.c             | 4 +---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
index 538053b1656a..57ab3da53002 100644
--- a/arch/x86/include/asm/vsyscall.h
+++ b/arch/x86/include/asm/vsyscall.h
@@ -36,7 +36,8 @@ static inline bool emulate_vsyscall_gp(struct pt_regs *regs)
  */
 static inline bool is_vsyscall_vaddr(unsigned long vaddr)
 {
-	return unlikely((vaddr & PAGE_MASK) == VSYSCALL_ADDR);
+	return IS_ENABLED(CONFIG_X86_64) &&
+		unlikely((vaddr & PAGE_MASK) == VSYSCALL_ADDR);
 }
 
 #endif /* _ASM_X86_VSYSCALL_H */
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index f0e77e084482..fcd6b58dc0ac 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1119,7 +1119,7 @@ bool fault_in_kernel_space(unsigned long address)
 	 * TASK_SIZE_MAX, but is not considered part of the kernel
 	 * address space.
 	 */
-	if (IS_ENABLED(CONFIG_X86_64) && is_vsyscall_vaddr(address))
+	if (is_vsyscall_vaddr(address))
 		return false;
 
 	return address >= TASK_SIZE_MAX;
@@ -1301,7 +1301,6 @@ void do_user_addr_fault(struct pt_regs *regs,
 	if (user_mode(regs))
 		flags |= FAULT_FLAG_USER;
 
-#ifdef CONFIG_X86_64
 	/*
 	 * Faults in the vsyscall page might need emulation.  The
 	 * vsyscall page is at a high address (>PAGE_OFFSET), but is
@@ -1317,7 +1316,6 @@ void do_user_addr_fault(struct pt_regs *regs,
 		if (emulate_vsyscall_pf(error_code, regs, address))
 			return;
 	}
-#endif
 
 	if (!(flags & FAULT_FLAG_USER))
 		goto lock_mmap;
-- 
2.53.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 1/5] x86/vsyscall: Reorganize the page fault emulation code
  2026-03-05 22:36   ` H. Peter Anvin
@ 2026-03-06  0:49     ` Sohil Mehta
  0 siblings, 0 replies; 21+ messages in thread
From: Sohil Mehta @ 2026-03-06  0:49 UTC (permalink / raw)
  To: H. Peter Anvin, Dave Hansen, x86, Andy Lutomirski, Borislav Petkov
  Cc: Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	Peter Zijlstra, Kiryl Shutsemau, Brendan Jackman,
	Sean Christopherson, Nam Cao, Cedric Xing, Rick Edgecombe,
	Andrew Cooper, Tony Luck, Alexander Shishkin,
	Maciej Wieczor-Retman, linux-doc, linux-kernel

On 3/5/2026 2:36 PM, H. Peter Anvin wrote:
> On 2026-03-05 13:40, Sohil Mehta wrote:

>> +bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs,
>> +			 unsigned long address)
>> +{
>> +	/* Write faults or kernel-privilege faults never get fixed up. */
>> +	if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER)
>> +		return false;
> 
> 
> I think this can be tightened further.  If X86_PF_PK, X86_PF_SHSTK or
> X86_PF_RSVD are set we should definitely not try to do any emulation, and I
> believe the same is true for X86_PF_SGX or X86_PF_RMP; I'm not 100% as I don't
> have the semantics of those bits in my head at the moment.
> 

Could some of this already be (or might need to be) taken care of in the
calling function do_user_addr_fault(). For example, I see comments such as:

* PKRU never rejects instruction fetches, so we don't need
* to consider the PF_PK bit.

* Read-only permissions can not be expressed in shadow stack PTEs.
* Treat all shadow stack accesses as WRITE faults.

I would prefer to avoid changing any logic for the existing #PF
emulation handling in this patch. If it's okay, we could pursue these as
a follow-on to this series.


>> +	/*
>> +	 * Assume that faults at regs->ip are because of an instruction
>> +	 * fetch. Return early and avoid emulation for faults during
>> +	 * data accesses:
>> +	 */
>> +	if (address != regs->ip) {
>> +		 /* User code tried and failed to read the vsyscall page. */
>> +		if (vsyscall_mode != EMULATE)
>> +			warn_bad_vsyscall(KERN_INFO, regs,
>> +					  "vsyscall read attempt denied -- look up the vsyscall kernel parameter if you need a workaround");
>> +
>> +		return false;
>> +	}
>> +
> 
> I don't really like the reshuffling of the code here.
> 

Sure, I'll keep the flow same as the original code. Will change it in
the next revision.

>> +	/*
>> +	 * X86_PF_INSTR is only set when NX is supported.  When
>> +	 * available, use it to double-check that the emulation code
>> +	 * is only being used for instruction fetches:
>> +	 */
>> +	if (cpu_feature_enabled(X86_FEATURE_NX))
>> +		WARN_ON_ONCE(!(error_code & X86_PF_INSTR));
>> +
> 
> I realize this is the same as the previous code, but I really think this
> should have a "return false;" in it as well.
> 

Yes, returning early makes sense if the warning triggers. But we would
need to change the logic to:

	if (cpu_feature_enabled(X86_FEATURE_NX) &&
	    WARN_ON_ONCE(!(error_code & X86_PF_INSTR)))
		return false;

Again, I would like to avoid such a logic change in this patch as it
only focuses on code reorganization. Would it need to be backported?

Preferably I could send it out as a follow-on patch along with the other
tightening that you mentioned above. Your suggestions seem fine to me,
but I really want to understand and evaluate the changes before sending
them out.

>> +	return __emulate_vsyscall(regs, address);
>> +}
>> +
>>  /*

> 
> Other than the above minor nitpicks, looks good to me.
> 
> Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> 

Thank you!



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode
  2026-03-05 21:40 [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode Sohil Mehta
                   ` (5 preceding siblings ...)
  2026-03-05 23:21 ` [PATCH 0/1] x86/fault: cleanup: move x86-64 test into is_vsyscall_vaddr() H. Peter Anvin
@ 2026-03-08 10:38 ` Maciej Wieczor-Retman
  6 siblings, 0 replies; 21+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-08 10:38 UTC (permalink / raw)
  To: Sohil Mehta
  Cc: Dave Hansen, x86, Andy Lutomirski, Borislav Petkov,
	Jonathan Corbet, Shuah Khan, Thomas Gleixner, Ingo Molnar,
	H . Peter Anvin, Peter Zijlstra, Kiryl Shutsemau,
	Brendan Jackman, Sean Christopherson, Nam Cao, Cedric Xing,
	Rick Edgecombe, Andrew Cooper, Tony Luck, Alexander Shishkin,
	linux-doc, linux-kernel

Hi! Tested the patchset on a Sierra Forest system using mostly the selftest and
checking out the feature status. Verified all combinations of config options and
cmdline arguments behave as expected.

Tested-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

Kind regards
Maciej Wieczór-Retman

On 2026-03-05 at 13:40:21 -0800, Sohil Mehta wrote:
>Linear Address Space Separation (LASS) is currently disabled [1] when
>support for vsyscall emulation is configured. This series extends LASS
>support specifically to the default XONLY mode (vsyscall=xonly).
>
>Changes in v2
>-------------
>- Pick up review tags from Dave.
>- Improve commit messages based on feedback from Dave and Peter.
>- Minor change in patch 4 to avoid unnecessary clearing of CR4.LASS.
>
>v1: https://lore.kernel.org/lkml/20260219233600.154313-1-sohil.mehta@intel.com/
>
>Patches
>-------
>These patches were originally part of the v10 LASS series [2] before
>being split out into a smaller series to make it easier to review and
>merge. The overall approach to enable vsyscall support was okayed by
>Andy Lutomirski [3].
>
>The patches are based on the tip x86/cpu branch which has the recently
>merged LASS-EFI series [4].
>
>Issue
>-----
>Userspace attempts to access any kernel address generate a #GP when LASS
>is enabled. Legacy vsyscall functions are located in the address range
>0xffffffffff600000 - 0xffffffffff601000. Prior to LASS, default access
>(XONLY) to the vsyscall page would generate a page fault and the access
>would be emulated in the kernel. Currently, as the #GP handler lacks any
>emulation support, LASS is disabled when config X86_VSYSCALL_EMULATION
>is set.
>
>Solution
>--------
>These patches primarily update the #GP handler to reuse the existing
>vsyscall emulation code for #PF. In XONLY mode, the faulting RIP is
>readily available and can be used to determine if the #GP was triggered
>due to a vsyscall access.
>
>In contrast, the vsyscall EMULATE mode is deprecated and not expected to
>be used by anyone. Supporting EMULATE mode with LASS would require
>complex instruction decoding in the #GP fault handler, which is not
>worth the effort. So, LASS is disabled in the rare case when someone
>absolutely needs to enable vsyscall=emulate via the command line.
>
>Please find more details in the individual commit messages.
>
>Links
>-----
>[1]: https://lore.kernel.org/lkml/20251118182911.2983253-1-sohil.mehta@intel.com/
>[2]: https://lore.kernel.org/lkml/20251007065119.148605-1-sohil.mehta@intel.com/
>[3]: https://lore.kernel.org/lkml/f4ae0030-9bc2-4675-ae43-e477cd894750@app.fastmail.com/
>[4]: https://lore.kernel.org/lkml/20260120234730.2215498-1-sohil.mehta@intel.com/
>
>Sohil Mehta (5):
>  x86/vsyscall: Reorganize the page fault emulation code
>  x86/traps: Consolidate user fixups in the #GP handler
>  x86/vsyscall: Restore vsyscall=xonly mode under LASS
>  x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE
>  x86/cpu: Remove LASS restriction on vsyscall emulation
>
> .../admin-guide/kernel-parameters.txt         |  4 +-
> arch/x86/entry/vsyscall/vsyscall_64.c         | 89 +++++++++++--------
> arch/x86/include/asm/vsyscall.h               | 13 ++-
> arch/x86/kernel/cpu/common.c                  | 15 ----
> arch/x86/kernel/traps.c                       | 12 +--
> arch/x86/kernel/umip.c                        |  3 +
> arch/x86/mm/fault.c                           |  2 +-
> 7 files changed, 77 insertions(+), 61 deletions(-)
>
>
>base-commit: 68400c1aaf02636a97c45ba198110b66feb270a9
>-- 
>2.43.0
>


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [tip: x86/cpu] x86/cpu: Remove LASS restriction on vsyscall emulation
  2026-03-05 21:40 ` [PATCH v2 5/5] x86/cpu: Remove LASS restriction on vsyscall emulation Sohil Mehta
  2026-03-05 22:46   ` H. Peter Anvin
@ 2026-03-19 21:59   ` tip-bot2 for Sohil Mehta
  1 sibling, 0 replies; 21+ messages in thread
From: tip-bot2 for Sohil Mehta @ 2026-03-19 21:59 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Sohil Mehta, Dave Hansen, x86, linux-kernel

The following commit has been merged into the x86/cpu branch of tip:

Commit-ID:     0e2a0cb1bf436a3979f3bf93e3b7fede5d93f730
Gitweb:        https://git.kernel.org/tip/0e2a0cb1bf436a3979f3bf93e3b7fede5d93f730
Author:        Sohil Mehta <sohil.mehta@intel.com>
AuthorDate:    Thu, 05 Mar 2026 13:40:26 -08:00
Committer:     Dave Hansen <dave.hansen@linux.intel.com>
CommitterDate: Thu, 05 Mar 2026 13:49:26 -08:00

x86/cpu: Remove LASS restriction on vsyscall emulation

Vsyscall emulation has two modes of operation: XONLY and EMULATE. The
default XONLY mode is now supported with a LASS-triggered #GP. OTOH,
LASS is disabled if someone requests the deprecated EMULATE mode via the
vsyscall=emulate command line option. So, remove the restriction on LASS
when the overall vsyscall emulation support is compiled in.

As a result, there is no need for setup_lass() anymore. LASS is enabled
by default through a late_initcall().

Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://patch.msgid.link/20260305214026.3887452-6-sohil.mehta@intel.com
---
 arch/x86/kernel/cpu/common.c | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 3557f0e..02472fc 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -406,20 +406,6 @@ out:
 	cr4_clear_bits(X86_CR4_UMIP);
 }
 
-static __always_inline void setup_lass(struct cpuinfo_x86 *c)
-{
-	if (!cpu_feature_enabled(X86_FEATURE_LASS))
-		return;
-
-	/*
-	 * Legacy vsyscall page access causes a #GP when LASS is active.
-	 * Disable LASS because the #GP handler doesn't support vsyscall
-	 * emulation.
-	 */
-	if (IS_ENABLED(CONFIG_X86_VSYSCALL_EMULATION))
-		setup_clear_cpu_cap(X86_FEATURE_LASS);
-}
-
 static int enable_lass(unsigned int cpu)
 {
 	cr4_set_bits(X86_CR4_LASS);
@@ -2061,7 +2047,6 @@ static void identify_cpu(struct cpuinfo_x86 *c)
 	setup_smep(c);
 	setup_smap(c);
 	setup_umip(c);
-	setup_lass(c);
 
 	/* Enable FSGSBASE instructions if available. */
 	if (cpu_has(c, X86_FEATURE_FSGSBASE)) {

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [tip: x86/cpu] x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE
  2026-03-05 21:40 ` [PATCH v2 4/5] x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE Sohil Mehta
  2026-03-05 22:45   ` H. Peter Anvin
@ 2026-03-19 21:59   ` tip-bot2 for Sohil Mehta
  1 sibling, 0 replies; 21+ messages in thread
From: tip-bot2 for Sohil Mehta @ 2026-03-19 21:59 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Sohil Mehta, Dave Hansen, Rick Edgecombe, x86, linux-kernel

The following commit has been merged into the x86/cpu branch of tip:

Commit-ID:     07a11b1501042ee087a7cadd39dfea52ca12bf25
Gitweb:        https://git.kernel.org/tip/07a11b1501042ee087a7cadd39dfea52ca12bf25
Author:        Sohil Mehta <sohil.mehta@intel.com>
AuthorDate:    Thu, 05 Mar 2026 13:40:25 -08:00
Committer:     Dave Hansen <dave.hansen@linux.intel.com>
CommitterDate: Thu, 05 Mar 2026 13:49:26 -08:00

x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE

The EMULATE mode of vsyscall maps the vsyscall page with a high kernel
address directly into user address space. Reading the vsyscall page in
EMULATE mode would cause LASS to trigger a #GP.

Fixing the LASS violation in EMULATE mode would require complex
instruction decoding because the resulting #GP does include the
necessary error information, and the vsyscall address is not
readily available in the RIP.

The EMULATE mode has been deprecated since 2022 and can only be enabled
using the command line parameter vsyscall=emulate. See commit
bf00745e7791 ("x86/vsyscall: Remove CONFIG_LEGACY_VSYSCALL_EMULATE") for
details. At this point, no one is expected to be using this insecure
mode. The rare usages that need it obviously do not care about security.

Disable LASS when EMULATE mode is requested to avoid breaking legacy
user software. Also, update the vsyscall documentation to reflect this.
LASS will only be supported if vsyscall mode is set to XONLY (default)
or NONE.

Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://patch.msgid.link/20260305214026.3887452-5-sohil.mehta@intel.com
---
 Documentation/admin-guide/kernel-parameters.txt | 4 +++-
 arch/x86/entry/vsyscall/vsyscall_64.c           | 5 +++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index cb850e5..64df2c5 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -8376,7 +8376,9 @@ Kernel parameters
 
 			emulate     Vsyscalls turn into traps and are emulated
 			            reasonably safely.  The vsyscall page is
-				    readable.
+				    readable.  This disables the Linear
+				    Address Space Separation (LASS) security
+				    feature and makes the system less secure.
 
 			xonly       [default] Vsyscalls turn into traps and are
 			            emulated reasonably safely.  The vsyscall
diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
index b34c876..215ae07 100644
--- a/arch/x86/entry/vsyscall/vsyscall_64.c
+++ b/arch/x86/entry/vsyscall/vsyscall_64.c
@@ -62,6 +62,11 @@ static int __init vsyscall_setup(char *str)
 		else
 			return -EINVAL;
 
+		if (cpu_feature_enabled(X86_FEATURE_LASS) && vsyscall_mode == EMULATE) {
+			setup_clear_cpu_cap(X86_FEATURE_LASS);
+			pr_warn_once("x86/cpu: Disabling LASS due to vsyscall=emulate\n");
+		}
+
 		return 0;
 	}
 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [tip: x86/cpu] x86/vsyscall: Restore vsyscall=xonly mode under LASS
  2026-03-05 21:40 ` [PATCH v2 3/5] x86/vsyscall: Restore vsyscall=xonly mode under LASS Sohil Mehta
  2026-03-05 22:45   ` H. Peter Anvin
@ 2026-03-19 21:59   ` tip-bot2 for Sohil Mehta
  1 sibling, 0 replies; 21+ messages in thread
From: tip-bot2 for Sohil Mehta @ 2026-03-19 21:59 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Sohil Mehta, Dave Hansen, x86, linux-kernel

The following commit has been merged into the x86/cpu branch of tip:

Commit-ID:     9aabde8105ed2418c0efbc1c8b9ccb3948b48121
Gitweb:        https://git.kernel.org/tip/9aabde8105ed2418c0efbc1c8b9ccb3948b48121
Author:        Sohil Mehta <sohil.mehta@intel.com>
AuthorDate:    Thu, 05 Mar 2026 13:40:24 -08:00
Committer:     Dave Hansen <dave.hansen@linux.intel.com>
CommitterDate: Thu, 05 Mar 2026 13:49:26 -08:00

x86/vsyscall: Restore vsyscall=xonly mode under LASS

Background
==========
The vsyscall page is located in the high/kernel part of the address
space. Prior to LASS, a vsyscall page access from userspace would always
generate a #PF. The kernel emulates the accesses in the #PF handler and
returns the appropriate values to userspace.

Vsyscall emulation has two modes of operation, specified by the
vsyscall={xonly, emulate} kernel command line option. The vsyscall page
behaves as execute-only in XONLY mode or read-execute in EMULATE mode.
XONLY mode is the default and the only one expected to be commonly used.
The EMULATE mode has been deprecated since 2022 and is considered
insecure.

With LASS, a vsyscall page access triggers a #GP instead of a #PF.
Currently, LASS is only enabled when all vsyscall modes are disabled.

LASS with XONLY mode
====================
Now add support for LASS specifically with XONLY vsyscall emulation. For
XONLY mode, all that is needed is the faulting RIP, which is trivially
available regardless of the type of fault. Reuse the #PF emulation code
during the #GP when the fault address points to the vsyscall page.

As multiple fault handlers will now be using the emulation code, add a
sanity check to ensure that the fault truly happened in 64-bit user
mode.

LASS with EMULATE mode
======================
Supporting vsyscall=emulate with LASS is much harder because the #GP
doesn't provide enough error information (such as PFEC and CR2 as in
case of a #PF). So, complex instruction decoding would be required to
emulate this mode in the #GP handler.

This isn't worth the effort as remaining users of EMULATE mode can be
reasonably assumed to be niche users, who are already trading off
security for compatibility. LASS and vsyscall=emulate will be kept
mutually exclusive for simplicity.

Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://patch.msgid.link/20260305214026.3887452-4-sohil.mehta@intel.com
---
 arch/x86/entry/vsyscall/vsyscall_64.c | 22 +++++++++++++++++-----
 arch/x86/include/asm/vsyscall.h       |  6 ++++++
 arch/x86/kernel/traps.c               |  4 ++++
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
index 5c6559c..b34c876 100644
--- a/arch/x86/entry/vsyscall/vsyscall_64.c
+++ b/arch/x86/entry/vsyscall/vsyscall_64.c
@@ -23,7 +23,7 @@
  * soon be no new userspace code that will ever use a vsyscall.
  *
  * The code in this file emulates vsyscalls when notified of a page
- * fault to a vsyscall address.
+ * fault or a general protection fault to a vsyscall address.
  */
 
 #include <linux/kernel.h>
@@ -118,10 +118,9 @@ static bool __emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 	long ret;
 	unsigned long orig_dx;
 
-	/*
-	 * No point in checking CS -- the only way to get here is a user mode
-	 * trap to a high address, which means that we're in 64-bit user code.
-	 */
+	/* Confirm that the fault happened in 64-bit user mode */
+	if (!user_64bit_mode(regs))
+		return false;
 
 	if (vsyscall_mode == NONE) {
 		warn_bad_vsyscall(KERN_INFO, regs,
@@ -282,6 +281,19 @@ bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs,
 	return __emulate_vsyscall(regs, address);
 }
 
+bool emulate_vsyscall_gp(struct pt_regs *regs)
+{
+	/* Without LASS, vsyscall accesses are expected to generate a #PF */
+	if (!cpu_feature_enabled(X86_FEATURE_LASS))
+		return false;
+
+	/* Emulate only if the RIP points to the vsyscall address */
+	if (!is_vsyscall_vaddr(regs->ip))
+		return false;
+
+	return __emulate_vsyscall(regs, regs->ip);
+}
+
 /*
  * A pseudo VMA to allow ptrace access for the vsyscall page.  This only
  * covers the 64bit vsyscall page now. 32bit has a real VMA now and does
diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
index f349023..538053b 100644
--- a/arch/x86/include/asm/vsyscall.h
+++ b/arch/x86/include/asm/vsyscall.h
@@ -15,6 +15,7 @@ extern void set_vsyscall_pgtable_user_bits(pgd_t *root);
  * Returns true if handled.
  */
 bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs, unsigned long address);
+bool emulate_vsyscall_gp(struct pt_regs *regs);
 #else
 static inline void map_vsyscall(void) {}
 static inline bool emulate_vsyscall_pf(unsigned long error_code,
@@ -22,6 +23,11 @@ static inline bool emulate_vsyscall_pf(unsigned long error_code,
 {
 	return false;
 }
+
+static inline bool emulate_vsyscall_gp(struct pt_regs *regs)
+{
+	return false;
+}
 #endif
 
 /*
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 614a281..0ca3912 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -70,6 +70,7 @@
 #include <asm/tdx.h>
 #include <asm/cfi.h>
 #include <asm/msr.h>
+#include <asm/vsyscall.h>
 
 #ifdef CONFIG_X86_64
 #include <asm/x86_init.h>
@@ -938,6 +939,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
 		if (fixup_umip_exception(regs))
 			goto exit;
 
+		if (emulate_vsyscall_gp(regs))
+			goto exit;
+
 		gp_user_force_sig_segv(regs, X86_TRAP_GP, error_code, desc);
 		goto exit;
 	}

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [tip: x86/cpu] x86/traps: Consolidate user fixups in the #GP handler
  2026-03-05 21:40 ` [PATCH v2 2/5] x86/traps: Consolidate user fixups in the #GP handler Sohil Mehta
  2026-03-05 22:22   ` H. Peter Anvin
  2026-03-05 22:41   ` H. Peter Anvin
@ 2026-03-19 21:59   ` tip-bot2 for Sohil Mehta
  2 siblings, 0 replies; 21+ messages in thread
From: tip-bot2 for Sohil Mehta @ 2026-03-19 21:59 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Dave Hansen, Sohil Mehta, Dave Hansen, x86, linux-kernel

The following commit has been merged into the x86/cpu branch of tip:

Commit-ID:     97b8c8927ee107c5a1bfe990106209beb054d3bf
Gitweb:        https://git.kernel.org/tip/97b8c8927ee107c5a1bfe990106209beb054d3bf
Author:        Sohil Mehta <sohil.mehta@intel.com>
AuthorDate:    Thu, 05 Mar 2026 13:40:23 -08:00
Committer:     Dave Hansen <dave.hansen@linux.intel.com>
CommitterDate: Thu, 05 Mar 2026 13:49:26 -08:00

x86/traps: Consolidate user fixups in the #GP handler

Move the UMIP exception fixup under the common "if (user_mode(regs))"
condition where the rest of user mode fixups reside. Also, move the UMIP
feature check into its fixup function to keep the calling code
consistent and clean.

No functional change intended.

Suggested-by: Dave Hansen <dave.hansen@intel.com>
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://patch.msgid.link/20260305214026.3887452-3-sohil.mehta@intel.com
---
 arch/x86/kernel/traps.c | 8 +++-----
 arch/x86/kernel/umip.c  | 3 +++
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 4dbff8e..614a281 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -921,11 +921,6 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
 
 	cond_local_irq_enable(regs);
 
-	if (static_cpu_has(X86_FEATURE_UMIP)) {
-		if (user_mode(regs) && fixup_umip_exception(regs))
-			goto exit;
-	}
-
 	if (v8086_mode(regs)) {
 		local_irq_enable();
 		handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
@@ -940,6 +935,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
 		if (fixup_vdso_exception(regs, X86_TRAP_GP, error_code, 0))
 			goto exit;
 
+		if (fixup_umip_exception(regs))
+			goto exit;
+
 		gp_user_force_sig_segv(regs, X86_TRAP_GP, error_code, desc);
 		goto exit;
 	}
diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index d432f38..3ce99cb 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -354,6 +354,9 @@ bool fixup_umip_exception(struct pt_regs *regs)
 	void __user *uaddr;
 	struct insn insn;
 
+	if (!cpu_feature_enabled(X86_FEATURE_UMIP))
+		return false;
+
 	if (!regs)
 		return false;
 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [tip: x86/cpu] x86/vsyscall: Reorganize the page fault emulation code
  2026-03-05 21:40 ` [PATCH v2 1/5] x86/vsyscall: Reorganize the page fault emulation code Sohil Mehta
  2026-03-05 22:36   ` H. Peter Anvin
@ 2026-03-19 21:59   ` tip-bot2 for Sohil Mehta
  1 sibling, 0 replies; 21+ messages in thread
From: tip-bot2 for Sohil Mehta @ 2026-03-19 21:59 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Sohil Mehta, Dave Hansen, x86, linux-kernel

The following commit has been merged into the x86/cpu branch of tip:

Commit-ID:     5fe9c000008c56224b6f9a528f0cd8f0977ebe42
Gitweb:        https://git.kernel.org/tip/5fe9c000008c56224b6f9a528f0cd8f0977ebe42
Author:        Sohil Mehta <sohil.mehta@intel.com>
AuthorDate:    Thu, 05 Mar 2026 13:40:22 -08:00
Committer:     Dave Hansen <dave.hansen@linux.intel.com>
CommitterDate: Thu, 05 Mar 2026 13:49:25 -08:00

x86/vsyscall: Reorganize the page fault emulation code

With LASS, vsyscall page accesses will cause a #GP instead of a #PF.
Separate out the core vsyscall emulation code from the #PF specific
handling in preparation for the upcoming #GP emulation.

No functional change intended.

Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Link: https://patch.msgid.link/20260305214026.3887452-2-sohil.mehta@intel.com
---
 arch/x86/entry/vsyscall/vsyscall_64.c | 64 +++++++++++++-------------
 arch/x86/include/asm/vsyscall.h       |  7 +--
 arch/x86/mm/fault.c                   |  2 +-
 3 files changed, 37 insertions(+), 36 deletions(-)

diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
index 4bd1e27..5c6559c 100644
--- a/arch/x86/entry/vsyscall/vsyscall_64.c
+++ b/arch/x86/entry/vsyscall/vsyscall_64.c
@@ -111,43 +111,13 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size)
 	}
 }
 
-bool emulate_vsyscall(unsigned long error_code,
-		      struct pt_regs *regs, unsigned long address)
+static bool __emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 {
 	unsigned long caller;
 	int vsyscall_nr, syscall_nr, tmp;
 	long ret;
 	unsigned long orig_dx;
 
-	/* Write faults or kernel-privilege faults never get fixed up. */
-	if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER)
-		return false;
-
-	/*
-	 * Assume that faults at regs->ip are because of an
-	 * instruction fetch. Return early and avoid
-	 * emulation for faults during data accesses:
-	 */
-	if (address != regs->ip) {
-		/* Failed vsyscall read */
-		if (vsyscall_mode == EMULATE)
-			return false;
-
-		/*
-		 * User code tried and failed to read the vsyscall page.
-		 */
-		warn_bad_vsyscall(KERN_INFO, regs, "vsyscall read attempt denied -- look up the vsyscall kernel parameter if you need a workaround");
-		return false;
-	}
-
-	/*
-	 * X86_PF_INSTR is only set when NX is supported.  When
-	 * available, use it to double-check that the emulation code
-	 * is only being used for instruction fetches:
-	 */
-	if (cpu_feature_enabled(X86_FEATURE_NX))
-		WARN_ON_ONCE(!(error_code & X86_PF_INSTR));
-
 	/*
 	 * No point in checking CS -- the only way to get here is a user mode
 	 * trap to a high address, which means that we're in 64-bit user code.
@@ -280,6 +250,38 @@ sigsegv:
 	return true;
 }
 
+bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs,
+			 unsigned long address)
+{
+	/* Write faults or kernel-privilege faults never get fixed up. */
+	if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER)
+		return false;
+
+	/*
+	 * Assume that faults at regs->ip are because of an instruction
+	 * fetch. Return early and avoid emulation for faults during
+	 * data accesses:
+	 */
+	if (address != regs->ip) {
+		 /* User code tried and failed to read the vsyscall page. */
+		if (vsyscall_mode != EMULATE)
+			warn_bad_vsyscall(KERN_INFO, regs,
+					  "vsyscall read attempt denied -- look up the vsyscall kernel parameter if you need a workaround");
+
+		return false;
+	}
+
+	/*
+	 * X86_PF_INSTR is only set when NX is supported.  When
+	 * available, use it to double-check that the emulation code
+	 * is only being used for instruction fetches:
+	 */
+	if (cpu_feature_enabled(X86_FEATURE_NX))
+		WARN_ON_ONCE(!(error_code & X86_PF_INSTR));
+
+	return __emulate_vsyscall(regs, address);
+}
+
 /*
  * A pseudo VMA to allow ptrace access for the vsyscall page.  This only
  * covers the 64bit vsyscall page now. 32bit has a real VMA now and does
diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
index 472f026..f349023 100644
--- a/arch/x86/include/asm/vsyscall.h
+++ b/arch/x86/include/asm/vsyscall.h
@@ -14,12 +14,11 @@ extern void set_vsyscall_pgtable_user_bits(pgd_t *root);
  * Called on instruction fetch fault in vsyscall page.
  * Returns true if handled.
  */
-extern bool emulate_vsyscall(unsigned long error_code,
-			     struct pt_regs *regs, unsigned long address);
+bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs, unsigned long address);
 #else
 static inline void map_vsyscall(void) {}
-static inline bool emulate_vsyscall(unsigned long error_code,
-				    struct pt_regs *regs, unsigned long address)
+static inline bool emulate_vsyscall_pf(unsigned long error_code,
+				       struct pt_regs *regs, unsigned long address)
 {
 	return false;
 }
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index b83a067..f0e77e0 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1314,7 +1314,7 @@ void do_user_addr_fault(struct pt_regs *regs,
 	 * to consider the PF_PK bit.
 	 */
 	if (is_vsyscall_vaddr(address)) {
-		if (emulate_vsyscall(error_code, regs, address))
+		if (emulate_vsyscall_pf(error_code, regs, address))
 			return;
 	}
 #endif

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2026-03-19 21:59 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-03-05 21:40 [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode Sohil Mehta
2026-03-05 21:40 ` [PATCH v2 1/5] x86/vsyscall: Reorganize the page fault emulation code Sohil Mehta
2026-03-05 22:36   ` H. Peter Anvin
2026-03-06  0:49     ` Sohil Mehta
2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
2026-03-05 21:40 ` [PATCH v2 2/5] x86/traps: Consolidate user fixups in the #GP handler Sohil Mehta
2026-03-05 22:22   ` H. Peter Anvin
2026-03-05 22:41   ` H. Peter Anvin
2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
2026-03-05 21:40 ` [PATCH v2 3/5] x86/vsyscall: Restore vsyscall=xonly mode under LASS Sohil Mehta
2026-03-05 22:45   ` H. Peter Anvin
2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
2026-03-05 21:40 ` [PATCH v2 4/5] x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE Sohil Mehta
2026-03-05 22:45   ` H. Peter Anvin
2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
2026-03-05 21:40 ` [PATCH v2 5/5] x86/cpu: Remove LASS restriction on vsyscall emulation Sohil Mehta
2026-03-05 22:46   ` H. Peter Anvin
2026-03-19 21:59   ` [tip: x86/cpu] " tip-bot2 for Sohil Mehta
2026-03-05 23:21 ` [PATCH 0/1] x86/fault: cleanup: move x86-64 test into is_vsyscall_vaddr() H. Peter Anvin
2026-03-05 23:21   ` [PATCH 1/1] " H. Peter Anvin
2026-03-08 10:38 ` [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode Maciej Wieczor-Retman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox