Re: [PATCH 4/7] x86/vsyscall: Setup vsyscall to compromise LASS protection

From: Andy Lutomirski
Date: Fri Jan 20 2023 - 23:09:46 EST




On Mon, Jan 9, 2023, at 9:52 PM, Yian Chen wrote:
> Kernel enables LASS automatically at starting time in LASS
> capable platforms. Any access to kernel addresses
> or upper half addresses from user space triggers a #GP
> fault.
>
> Legacy vsyscall does not comply with LASS, because
> the vsyscall functions are mapped in the range
> 0xffffffffff600000-0xffffffffff601000.
>
> In theory, it would be possible to write a #GP fault handler
> to emulate the old vsyscall behavior, but vsyscall has been
> deprecated for some time, so this has not been done.

The ISE docs are really quite explicit that #GP will have RIP pointing at the vDSO if LASS is on. Unless I’ve missed something, this should be quite straightforward to handle without breaking userspace compatibility. Let’s please do this.

>
> Therefore, when kernel enforces LASS, vsyscall does not work
> and should be disabled. On the other hand, the user can relax
> the enforcement by clearing lass cpu id (clearcpuid=lass/390)
> or enabling vsyscall (vsyscall=xxx) from kernel command line.
> The user can also opt-out LASS in config file to build kernel
> binary.
>
> Signed-off-by: Yian Chen <yian.chen@xxxxxxxxx>
> Reviewed-by: Tony Luck <tony.luck@xxxxxxxxx>
> ---
> Documentation/admin-guide/kernel-parameters.txt | 12 ++++++++----
> arch/x86/entry/vsyscall/vsyscall_64.c | 14 ++++++++++++++
> 2 files changed, 22 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt
> b/Documentation/admin-guide/kernel-parameters.txt
> index 6cfa6e3996cf..3988e0c8c175 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -6755,10 +6755,14 @@
> versions of glibc use these calls. Because these
> functions are at fixed addresses, they make nice
> targets for exploits that can control RIP.
> -
> - emulate [default] Vsyscalls turn into traps and are
> - emulated reasonably safely. The vsyscall
> - page is readable.
> + In newer versions of Intel platforms that come with
> + LASS(Linear Address Space separation) protection,
> + vsyscall is disabled by default. Enabling vsyscall
> + via the parameter overrides LASS protection.
> +
> + emulate [default if not LASS capable] Vsyscalls
> + turn into traps and are emulated reasonably
> + safely. The vsyscall page is readable.
>
> xonly 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 4af81df133ee..2691f26835d1 100644
> --- a/arch/x86/entry/vsyscall/vsyscall_64.c
> +++ b/arch/x86/entry/vsyscall/vsyscall_64.c
> @@ -63,6 +63,12 @@ static int __init vsyscall_setup(char *str)
> else
> return -EINVAL;
>
> + if (cpu_feature_enabled(X86_FEATURE_LASS) &&
> + vsyscall_mode != NONE) {
> + setup_clear_cpu_cap(X86_FEATURE_LASS);
> + pr_warn("LASS disabled by command line enabling vsyscall\n");
> + }
> +
> return 0;
> }
>
> @@ -379,6 +385,14 @@ void __init map_vsyscall(void)
> extern char __vsyscall_page;
> unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page);
>
> + /*
> + * When LASS is on, vsyscall triggers a #GP fault,
> + * so that force vsyscall_mode to NONE.
> + */
> + if (cpu_feature_enabled(X86_FEATURE_LASS)) {
> + vsyscall_mode = NONE;
> + return;
> + }
> /*
> * For full emulation, the page needs to exist for real. In
> * execute-only mode, there is no PTE at all backing the vsyscall
> --
> 2.34.1