[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] x86/emulator: Add Linear Address Space Separation (LASS) support
- To: Abdelkareem Abdelsaamad <abdelkareem.abdelsaamad@xxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
- From: Teddy Astie <teddy.astie@xxxxxxxxxx>
- Date: Wed, 14 Oct 2026 14:07:41 +0200
- Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=vates.tech header.i="@vates.tech" header.h="From:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:In-Reply-To:References:Feedback-ID"
- Autocrypt: addr=teddy.astie@xxxxxxxxxx; keydata= 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 x9fhaZEsniw8/bYgC3igkk5YJiOa
- Cc: jbeulich@xxxxxxxx, andrew.cooper3@xxxxxxxxxx, roger@xxxxxxxxxxxxxx
- Delivery-date: Wed, 14 Oct 2026 12:07:51 +0000
- Feedback-id: default:8631fc262581453bbf619ec5b2062170:Sweego
- List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
Le 14/10/2026 à 13:09, Abdelkareem Abdelsaamad a écrit :
Linear Address Space Separation (LASS) is an architectural security feature
that is intended to prevent cross userspace/kernelspace memory boundary access
with the CPU hardware support. Unlike the related mode-based paging protections
such as the Supervisor Mode Access Prevention (SMAP) and the Supervisor Mode
Execution Prevention (SMEP), LASS provides the efficient mechanism to guard
against the cross memory boundary accesses without traversing the paging
structures. This provides a more efficient guarding mechanism against the class
of malicious software attacks that relies on paging-based timing information,
see (1) for more information. Enlighten the x86 instruction emulator to comply
with the hardware Intel's CPU support for the LASS.
The LASS violation check logic is adapted from the reviewed logic in the Linux
KVM mailing list (2) for the LASS violation checks.
[1]
https://cdrdv2-public.intel.com/774990/architecture-instruction-set-extensions-programming-reference.pdf
[2]
https://lwn.net/ml/linux-kernel/20230913124227.12574-16-binbin.wu@xxxxxxxxxxxxxxx/
---
Testing:
- With A virtual machine setup with installing the fedora rawhide/f45
development
branch which is based on the Linux kernel 7.1, I verified the following
test cases
1- Using the Xen Server, I enabled the lass cpu fetaure. Running the command
grep 'lass' /proc/cpuinfo
is successfully reporting and verifying lass is supported by the guest
kernel.
2- On the setup guest, I wrote the following code to verify the kernelspace
linear
address access from userspace is prevented with #GP. Disabling lass from
the guest
and commenting the FEP is rather reporting #PF.
int main(void){
char usrspace_buf[16] = {0};
char* usrspace = usrspace_buf;
char* kernspace = (char*) 0xffff800000000000;
asm volatile (
".byte 0x0f, 0x0b, 0x78, 0x65, 0x6e\n\t"
"rep movsb"
: "+S" (usrspace), "+D" (kernspace)
: "c" (16)
: "memory"
);
return 0;
}
3- On the setup guest, I wrote the following kernel module to verify the
userspace linear
address access from the kernelspace is prevented with #GP. Disabling
lass from the guest
is rather reprting #PF. Executing the code with commentted Forced
Emulation Prefix
(FEP) and the lass feature enabled is reporting #GP.
#include <linux/module.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Testing Module for Intel's LASS Xen Trap");
static int __init my_module_init(void){
char* usrspace = (char*) 0x00007ffffffffd00;
char* kernspace = kzalloc(16, GFP_KERNEL);
if (!kernspace) {
pr_err("Memory allocation failed\n");
return -ENOMEM;
}
asm volatile (
".byte 0x0f, 0x0b, 0x78, 0x65, 0x6e\n\t"
"rep movsb"
: "+S" (usrspace), "+D" (kernspace)
: "c" (16)
: "memory"
);
return 0;
}
static void __exit my_module_exit(void){
pr_info("my module ");
}
module_init(my_module_init);
module_exit(my_module_exit);
4- On the setup guest, I wrote the following code to verify the implicit
system (spervisor)
address access from userspace is not prevented with #GP.
#include <stdio.h>
#define XEN_FEP ".byte 0x0f, 0x0b, 0x78, 0x65, 0x6e\n\t"
int main() {
asm volatile (XEN_FEP "mov %[sel], %%fs" :: [sel] "r" (15*8+3));
return 0;
}
5- CI tests:
https://gitlab.com/xen-project/people/aabdelsa/xen/-/pipelines/2946430503
---
xen/arch/x86/hvm/hvm.c | 73 ++++++++++++++++++++++++++++++++----------
1 file changed, 56 insertions(+), 17 deletions(-)
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ef9c7cd057..3477d62d43 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -2557,6 +2557,40 @@ int hvm_set_cr4(unsigned long value, bool may_defer)
return X86EMUL_OKAY;
}
+static bool is_lass_violation(struct vcpu *v, unsigned long addr,
+ unsigned long size,
+ enum hvm_access_type access_type,
+ bool is_implicit_supervisor_access)
+{
+ const bool is_supervisor_address = !!(addr & (1ULL << 63));
+
What happens if addr is not in LASS range, but addr..addr+size crosses
it (for instance, if addr is 0x7FFFFFFFFFFFFFFF and size is 16) ?
We would have is_supervisor_address == false, as we only checked the
starting address, but there is a part of the access within the LASS
range (with bit 63).
+ if ( !(v->arch.hvm.guest_cr[4] & X86_CR4_LASS) || !hvm_long_mode_active(v)
)
+ return false;
+
+ if ( !is_implicit_supervisor_access && hvm_get_cpl(v) == 3 )
+ return is_supervisor_address;
+
+ /*
+ * In the subsequent logic, we are emulating a verified supervisor
+ * access LASS check.
+ */
+
+ if ( access_type != hvm_access_insn_fetch )
+ {
+ if ( !(v->arch.hvm.guest_cr[4] & X86_CR4_SMAP) )
+ return false;
+
+ if ( !is_implicit_supervisor_access &&
+ guest_cpu_user_regs()->eflags & X86_EFLAGS_AC )
+ return false;
+ }
+
+ if ( size && !((addr + size - 1) & (1ULL << 63)) )
+ return true;
+
+ return !is_supervisor_address;
+}
I'm not sure to follow the entire logic
AIUI, LASS violations happens when :
- user-mode : Any access to LASS range (bit 63 = 1)
- supervisor-mode access :
- Any access to non-LASS range (bit 63 = 0) if SMAP && (AC=0 ||
"implicit supervisor-mode access")
- Any instruction fetch to non-LASS range (bit 63 = 0)
+
bool hvm_vcpu_virtual_to_linear(
struct vcpu *v,
enum x86_segment seg,
@@ -2602,26 +2636,31 @@ bool hvm_vcpu_virtual_to_linear(
if ( max(offset, last_byte) >> 16 )
goto out;
}
- else if ( hvm_long_mode_active(v) &&
- (is_x86_system_segment(seg) || active_cs->l) )
+ else if ( hvm_long_mode_active(v) )
{
- /*
- * User segments are always treated as present. System segment may
- * not be, and also incur limit checks.
- */
- if ( is_x86_system_segment(seg) &&
- (!reg->p || (offset + bytes - !!bytes) > reg->limit) )
- goto out;
+ if ( (is_x86_system_segment(seg) || active_cs->l) )
+ {
+ /*
+ * User segments are always treated as present. System segment may
+ * not be, and also incur limit checks.
+ */
+ if ( is_x86_system_segment(seg) &&
+ (!reg->p || (offset + bytes - !!bytes) > reg->limit) )
+ goto out;
- /*
- * LONG MODE: FS, GS and system segments: add segment base. All
- * addresses must be canonical.
- */
- if ( seg >= x86_seg_fs )
- addr += reg->base;
+ /*
+ * LONG MODE: FS, GS and system segments: add segment base. All
+ * addresses must be canonical.
+ */
+ if ( seg >= x86_seg_fs )
+ addr += reg->base;
+
+ last_byte = addr + bytes - !!bytes;
+ if ( !is_canonical_address((long)addr < 0 ? addr : last_byte) )
+ goto out;
+ }
- last_byte = addr + bytes - !!bytes;
- if ( !is_canonical_address((long)addr < 0 ? addr : last_byte) )
+ if ( is_lass_violation(v, addr, bytes, access_type,
is_x86_system_segment(seg)) )
goto out;
}
else
Teddy
Attachment:
OpenPGP_signature.asc
Description: OpenPGP digital signature
|