Skip to content

Commit

Permalink
x86: vdso: Wire up getrandom() vDSO implementation
Browse files Browse the repository at this point in the history
Hook up the generic vDSO implementation to the x86 vDSO data page. Since
the existing vDSO infrastructure is heavily based on the timekeeping
functionality, which works over arrays of bases, a new macro is
introduced for vvars that are not arrays.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
  • Loading branch information
zx2c4 committed Nov 19, 2022
1 parent a8f845b commit 6211dcd
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 1 deletion.
1 change: 1 addition & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ config X86
select HAVE_UNSTABLE_SCHED_CLOCK
select HAVE_USER_RETURN_NOTIFIER
select HAVE_GENERIC_VDSO
select HAVE_VDSO_GETRANDOM
select HOTPLUG_SMT if SMP
select IRQ_FORCED_THREADING
select NEED_PER_CPU_EMBED_FIRST_CHUNK
Expand Down
3 changes: 2 additions & 1 deletion arch/x86/entry/vdso/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ VDSO32-$(CONFIG_X86_32) := y
VDSO32-$(CONFIG_IA32_EMULATION) := y

# files to link into the vdso
vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o
vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o vgetrandom.o
vobjs32-y := vdso32/note.o vdso32/system_call.o vdso32/sigreturn.o
vobjs32-y += vdso32/vclock_gettime.o
vobjs-$(CONFIG_X86_SGX) += vsgx.o
Expand Down Expand Up @@ -104,6 +104,7 @@ CFLAGS_REMOVE_vclock_gettime.o = -pg
CFLAGS_REMOVE_vdso32/vclock_gettime.o = -pg
CFLAGS_REMOVE_vgetcpu.o = -pg
CFLAGS_REMOVE_vsgx.o = -pg
CFLAGS_REMOVE_vgetrandom.o = -pg

#
# X32 processes use x32 vDSO to access 64bit kernel data.
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/entry/vdso/vdso.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ VERSION {
clock_getres;
__vdso_clock_getres;
__vdso_sgx_enter_enclave;
getrandom;
__vdso_getrandom;
local: *;
};
}
16 changes: 16 additions & 0 deletions arch/x86/entry/vdso/vgetrandom.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*/
#include <linux/kernel.h>
#include <linux/types.h>

#include "../../../../lib/vdso/getrandom.c"

ssize_t __vdso_getrandom(void *buffer, size_t len, unsigned int flags, void *state)
{
return __cvdso_getrandom(buffer, len, flags, state);
}

ssize_t getrandom(void *, size_t, unsigned int, void *)
__attribute__((weak, alias("__vdso_getrandom")));
37 changes: 37 additions & 0 deletions arch/x86/include/asm/vdso/getrandom.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*/
#ifndef __ASM_VDSO_GETRANDOM_H
#define __ASM_VDSO_GETRANDOM_H

#ifndef __ASSEMBLY__

#include <asm/unistd.h>
#include <asm/vvar.h>

static __always_inline ssize_t
getrandom_syscall(void *buffer, size_t len, unsigned int flags)
{
long ret;

asm ("syscall" : "=a" (ret) :
"0" (__NR_getrandom), "D" (buffer), "S" (len), "d" (flags) :
"rcx", "r11", "memory");

return ret;
}

#define __vdso_rng_data (VVAR(_vdso_rng_data))

static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void)
{
if (__vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS)
return (void *)&__vdso_rng_data +
((void *)&__timens_vdso_data - (void *)&__vdso_data);
return &__vdso_rng_data;
}

#endif /* !__ASSEMBLY__ */

#endif /* __ASM_VDSO_GETRANDOM_H */
2 changes: 2 additions & 0 deletions arch/x86/include/asm/vdso/vsyscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <asm/vvar.h>

DEFINE_VVAR(struct vdso_data, _vdso_data);
DEFINE_VVAR_SINGLE(struct vdso_rng_data, _vdso_rng_data);

/*
* Update the vDSO data page to keep in sync with kernel timekeeping.
*/
Expand Down
16 changes: 16 additions & 0 deletions arch/x86/include/asm/vvar.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
*/
#define DECLARE_VVAR(offset, type, name) \
EMIT_VVAR(name, offset)
#define DECLARE_VVAR_SINGLE(offset, type, name) \
EMIT_VVAR(name, offset)

#else

Expand All @@ -37,19 +39,33 @@ extern char __vvar_page;
extern type timens_ ## name[CS_BASES] \
__attribute__((visibility("hidden"))); \

#define DECLARE_VVAR_SINGLE(offset, type, name) \
extern type vvar_ ## name \
__attribute__((visibility("hidden"))); \

#define VVAR(name) (vvar_ ## name)
#define TIMENS(name) (timens_ ## name)

#define DEFINE_VVAR(type, name) \
type name[CS_BASES] \
__attribute__((section(".vvar_" #name), aligned(16))) __visible

#define DEFINE_VVAR_SINGLE(type, name) \
type name \
__attribute__((section(".vvar_" #name), aligned(16))) __visible

#endif

/* DECLARE_VVAR(offset, type, name) */

DECLARE_VVAR(128, struct vdso_data, _vdso_data)

#if !defined(_SINGLE_DATA)
#define _SINGLE_DATA
DECLARE_VVAR_SINGLE(640, struct vdso_rng_data, _vdso_rng_data)
#endif

#undef DECLARE_VVAR
#undef DECLARE_VVAR_SINGLE

#endif

0 comments on commit 6211dcd

Please sign in to comment.