[PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode

Sohil Mehta posted 5 patches 1 month ago
There is a newer version of this series
.../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(-)
[PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode
Posted by Sohil Mehta 1 month ago
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
Re: [PATCH v2 0/5] x86: Enable LASS support with vsyscall=xonly mode
Posted by Maciej Wieczor-Retman 1 month ago
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
>
[PATCH 0/1] x86/fault: cleanup: move x86-64 test into is_vsyscall_vaddr()
Posted by H. Peter Anvin 1 month ago
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(-)
[PATCH 1/1] x86/fault: cleanup: move x86-64 test into is_vsyscall_vaddr()
Posted by H. Peter Anvin 1 month ago
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