lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAFULd4bQ-0ZD8PeAYiK1WK6yhKctxTSPksJLGg4gmE1eqzKDNg@mail.gmail.com>
Date: Tue, 6 Jan 2026 19:09:48 +0100
From: Uros Bizjak <ubizjak@...il.com>
To: "H. Peter Anvin" <hpa@...or.com>
Cc: "Jason A. Donenfeld" <Jason@...c4.com>, "Peter Zijlstra (Intel)" <peterz@...radead.org>, "Theodore Ts'o" <tytso@....edu>, 
	Thomas Weißschuh <thomas.weissschuh@...utronix.de>, 
	Xin Li <xin@...or.com>, Andrew Cooper <andrew.cooper3@...rix.com>, 
	Andy Lutomirski <luto@...nel.org>, Ard Biesheuvel <ardb@...nel.org>, Borislav Petkov <bp@...en8.de>, 
	Brian Gerst <brgerst@...il.com>, Dave Hansen <dave.hansen@...ux.intel.com>, 
	Ingo Molnar <mingo@...hat.com>, James Morse <james.morse@....com>, 
	Jarkko Sakkinen <jarkko@...nel.org>, Josh Poimboeuf <jpoimboe@...nel.org>, Kees Cook <kees@...nel.org>, 
	Nam Cao <namcao@...utronix.de>, Oleg Nesterov <oleg@...hat.com>, Perry Yuan <perry.yuan@....com>, 
	Thomas Gleixner <tglx@...utronix.de>, Thomas Huth <thuth@...hat.com>, linux-kernel@...r.kernel.org, 
	linux-mm@...ck.org, linux-sgx@...r.kernel.org, x86@...nel.org
Subject: Re: [PATCH v4 08/10] x86/vdso: abstract out vdso system call internals

On Tue, Dec 16, 2025 at 10:26 PM H. Peter Anvin <hpa@...or.com> wrote:
>
> Abstract out the calling of true system calls from the vdso into
> macros.
>
> It has been a very long time since gcc did not allow %ebx or %ebp in
> inline asm in 32-bit PIC mode; remove the corresponding hacks.
>
> Remove the use of memory output constraints in gettimeofday.h in favor
> of "memory" clobbers. The resulting code is identical for the current
> use cases, as the system call is usually a terminal fallback anyway,
> and it merely complicates the macroization.
>
> This patch adds only a handful of more lines of code than it removes,
> and in fact could be made substantially smaller by removing the macros
> for the argument counts that aren't currently used, however, it seems
> better to be general from the start.
>
> [ v3: remove stray comment from prototyping; remove VDSO_SYSCALL6()
>       since it would require special handling on 32 bits and is
>       currently unused. (Uros Biszjak)
>
>       Indent nested preprocessor directives. ]
>
> Signed-off-by: H. Peter Anvin (Intel) <hpa@...or.com>

Acked-by: Uros Bizjak <ubizjak@...il.com>

> ---
>  arch/x86/include/asm/vdso/gettimeofday.h | 108 ++---------------------
>  arch/x86/include/asm/vdso/sys_call.h     | 103 +++++++++++++++++++++
>  2 files changed, 111 insertions(+), 100 deletions(-)
>  create mode 100644 arch/x86/include/asm/vdso/sys_call.h
>
> diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h
> index 73b2e7ee8f0f..3cf214cc4a75 100644
> --- a/arch/x86/include/asm/vdso/gettimeofday.h
> +++ b/arch/x86/include/asm/vdso/gettimeofday.h
> @@ -18,6 +18,7 @@
>  #include <asm/msr.h>
>  #include <asm/pvclock.h>
>  #include <clocksource/hyperv_timer.h>
> +#include <asm/vdso/sys_call.h>
>
>  #define VDSO_HAS_TIME 1
>
> @@ -53,130 +54,37 @@ extern struct ms_hyperv_tsc_page hvclock_page
>         __attribute__((visibility("hidden")));
>  #endif
>
> -#ifndef BUILD_VDSO32
> -
>  static __always_inline
>  long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
>  {
> -       long ret;
> -
> -       asm ("syscall" : "=a" (ret), "=m" (*_ts) :
> -            "0" (__NR_clock_gettime), "D" (_clkid), "S" (_ts) :
> -            "rcx", "r11");
> -
> -       return ret;
> +       return VDSO_SYSCALL2(clock_gettime,64,_clkid,_ts);
>  }
>
>  static __always_inline
>  long gettimeofday_fallback(struct __kernel_old_timeval *_tv,
>                            struct timezone *_tz)
>  {
> -       long ret;
> -
> -       asm("syscall" : "=a" (ret) :
> -           "0" (__NR_gettimeofday), "D" (_tv), "S" (_tz) : "memory");
> -
> -       return ret;
> +       return VDSO_SYSCALL2(gettimeofday,,_tv,_tz);
>  }
>
>  static __always_inline
>  long clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
>  {
> -       long ret;
> -
> -       asm ("syscall" : "=a" (ret), "=m" (*_ts) :
> -            "0" (__NR_clock_getres), "D" (_clkid), "S" (_ts) :
> -            "rcx", "r11");
> -
> -       return ret;
> +       return VDSO_SYSCALL2(clock_getres,_time64,_clkid,_ts);
>  }
>
> -#else
> -
> -static __always_inline
> -long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
> -{
> -       long ret;
> -
> -       asm (
> -               "mov %%ebx, %%edx \n"
> -               "mov %[clock], %%ebx \n"
> -               "call __kernel_vsyscall \n"
> -               "mov %%edx, %%ebx \n"
> -               : "=a" (ret), "=m" (*_ts)
> -               : "0" (__NR_clock_gettime64), [clock] "g" (_clkid), "c" (_ts)
> -               : "edx");
> -
> -       return ret;
> -}
> +#ifndef CONFIG_X86_64
>
>  static __always_inline
>  long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
>  {
> -       long ret;
> -
> -       asm (
> -               "mov %%ebx, %%edx \n"
> -               "mov %[clock], %%ebx \n"
> -               "call __kernel_vsyscall \n"
> -               "mov %%edx, %%ebx \n"
> -               : "=a" (ret), "=m" (*_ts)
> -               : "0" (__NR_clock_gettime), [clock] "g" (_clkid), "c" (_ts)
> -               : "edx");
> -
> -       return ret;
> -}
> -
> -static __always_inline
> -long gettimeofday_fallback(struct __kernel_old_timeval *_tv,
> -                          struct timezone *_tz)
> -{
> -       long ret;
> -
> -       asm(
> -               "mov %%ebx, %%edx \n"
> -               "mov %2, %%ebx \n"
> -               "call __kernel_vsyscall \n"
> -               "mov %%edx, %%ebx \n"
> -               : "=a" (ret)
> -               : "0" (__NR_gettimeofday), "g" (_tv), "c" (_tz)
> -               : "memory", "edx");
> -
> -       return ret;
> +       return VDSO_SYSCALL2(clock_gettime,,_clkid,_ts);
>  }
>
>  static __always_inline long
> -clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
> -{
> -       long ret;
> -
> -       asm (
> -               "mov %%ebx, %%edx \n"
> -               "mov %[clock], %%ebx \n"
> -               "call __kernel_vsyscall \n"
> -               "mov %%edx, %%ebx \n"
> -               : "=a" (ret), "=m" (*_ts)
> -               : "0" (__NR_clock_getres_time64), [clock] "g" (_clkid), "c" (_ts)
> -               : "edx");
> -
> -       return ret;
> -}
> -
> -static __always_inline
> -long clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
> +clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
>  {
> -       long ret;
> -
> -       asm (
> -               "mov %%ebx, %%edx \n"
> -               "mov %[clock], %%ebx \n"
> -               "call __kernel_vsyscall \n"
> -               "mov %%edx, %%ebx \n"
> -               : "=a" (ret), "=m" (*_ts)
> -               : "0" (__NR_clock_getres), [clock] "g" (_clkid), "c" (_ts)
> -               : "edx");
> -
> -       return ret;
> +       return VDSO_SYSCALL2(clock_getres,,_clkid,_ts);
>  }
>
>  #endif
> diff --git a/arch/x86/include/asm/vdso/sys_call.h b/arch/x86/include/asm/vdso/sys_call.h
> new file mode 100644
> index 000000000000..dcfd17c6dd57
> --- /dev/null
> +++ b/arch/x86/include/asm/vdso/sys_call.h
> @@ -0,0 +1,103 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Macros for issuing an inline system call from the vDSO.
> + */
> +
> +#ifndef X86_ASM_VDSO_SYS_CALL_H
> +#define X86_ASM_VDSO_SYS_CALL_H
> +
> +#include <linux/compiler.h>
> +#include <asm/cpufeatures.h>
> +#include <asm/alternative.h>
> +
> +#ifdef CONFIG_X86_64
> +# define __sys_instr   "syscall"
> +# define __sys_clobber "rcx", "r11", "memory"
> +# define __sys_nr(x,y) __NR_ ## x
> +# define __sys_reg1    "rdi"
> +# define __sys_reg2    "rsi"
> +# define __sys_reg3    "rdx"
> +# define __sys_reg4    "r10"
> +# define __sys_reg5    "r8"
> +#else
> +# define __sys_instr   "call __kernel_vsyscall"
> +# define __sys_clobber "memory"
> +# define __sys_nr(x,y) __NR_ ## x ## y
> +# define __sys_reg1    "ebx"
> +# define __sys_reg2    "ecx"
> +# define __sys_reg3    "edx"
> +# define __sys_reg4    "esi"
> +# define __sys_reg5    "edi"
> +#endif
> +
> +/*
> + * Example usage:
> + *
> + * result = VDSO_SYSCALL3(foo,64,x,y,z);
> + *
> + * ... calls foo(x,y,z) on 64 bits, and foo64(x,y,z) on 32 bits.
> + *
> + * VDSO_SYSCALL6() is currently missing, because it would require
> + * special handling for %ebp on 32 bits when the vdso is compiled with
> + * frame pointers enabled (the default on 32 bits.) Add it as a special
> + * case when and if it becomes necessary.
> + */
> +#define _VDSO_SYSCALL(name,suf32,...)                                  \
> +       ({                                                              \
> +               long _sys_num_ret = __sys_nr(name,suf32);               \
> +               asm_inline volatile(                                    \
> +                       __sys_instr                                     \
> +                       : "+a" (_sys_num_ret)                           \
> +                       : __VA_ARGS__                                   \
> +                       : __sys_clobber);                               \
> +               _sys_num_ret;                                           \
> +       })
> +
> +#define VDSO_SYSCALL0(name,suf32)                                      \
> +       _VDSO_SYSCALL(name,suf32)
> +#define VDSO_SYSCALL1(name,suf32,a1)                                   \
> +       ({                                                              \
> +               register long _sys_arg1 asm(__sys_reg1) = (long)(a1);   \
> +               _VDSO_SYSCALL(name,suf32,                               \
> +                             "r" (_sys_arg1));                         \
> +       })
> +#define VDSO_SYSCALL2(name,suf32,a1,a2)                                \
> +       ({                                                              \
> +               register long _sys_arg1 asm(__sys_reg1) = (long)(a1);   \
> +               register long _sys_arg2 asm(__sys_reg2) = (long)(a2);   \
> +               _VDSO_SYSCALL(name,suf32,                               \
> +                             "r" (_sys_arg1), "r" (_sys_arg2));        \
> +       })
> +#define VDSO_SYSCALL3(name,suf32,a1,a2,a3)                             \
> +       ({                                                              \
> +               register long _sys_arg1 asm(__sys_reg1) = (long)(a1);   \
> +               register long _sys_arg2 asm(__sys_reg2) = (long)(a2);   \
> +               register long _sys_arg3 asm(__sys_reg3) = (long)(a3);   \
> +               _VDSO_SYSCALL(name,suf32,                               \
> +                             "r" (_sys_arg1), "r" (_sys_arg2),         \
> +                             "r" (_sys_arg3));                         \
> +       })
> +#define VDSO_SYSCALL4(name,suf32,a1,a2,a3,a4)                          \
> +       ({                                                              \
> +               register long _sys_arg1 asm(__sys_reg1) = (long)(a1);   \
> +               register long _sys_arg2 asm(__sys_reg2) = (long)(a2);   \
> +               register long _sys_arg3 asm(__sys_reg3) = (long)(a3);   \
> +               register long _sys_arg4 asm(__sys_reg4) = (long)(a4);   \
> +               _VDSO_SYSCALL(name,suf32,                               \
> +                             "r" (_sys_arg1), "r" (_sys_arg2),         \
> +                             "r" (_sys_arg3), "r" (_sys_arg4));        \
> +       })
> +#define VDSO_SYSCALL5(name,suf32,a1,a2,a3,a4,a5)                       \
> +       ({                                                              \
> +               register long _sys_arg1 asm(__sys_reg1) = (long)(a1);   \
> +               register long _sys_arg2 asm(__sys_reg2) = (long)(a2);   \
> +               register long _sys_arg3 asm(__sys_reg3) = (long)(a3);   \
> +               register long _sys_arg4 asm(__sys_reg4) = (long)(a4);   \
> +               register long _sys_arg5 asm(__sys_reg5) = (long)(a5);   \
> +               _VDSO_SYSCALL(name,suf32,                               \
> +                             "r" (_sys_arg1), "r" (_sys_arg2),         \
> +                             "r" (_sys_arg3), "r" (_sys_arg4),         \
> +                             "r" (_sys_arg5));                         \
> +       })
> +
> +#endif /* X86_VDSO_SYS_CALL_H */
> --
> 2.52.0
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ