Re: [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data()

From: Jason A. Donenfeld

Date: Thu Sep 17 2026 - 05:33:26 EST


On Wed, Sep 16, 2026 at 02:58:44PM -0700, Nathan Chancellor wrote:
> After a recent change in LLVM [1], RISC-V builds fail when checking the
> vDSO:
>
> arch/riscv/kernel/vdso/vdso.so.dbg: dynamic relocations are not supported
> make[4]: *** [arch/riscv/kernel/vdso/Makefile:78: arch/riscv/kernel/vdso/vdso.so.dbg] Error 1
>
> memset() is now generated when zeroing params->reserved because LLVM has
> an optimization (now run in more instances) that can recognize at
> compile time when it is assigning a static value to a contiguous area of
> memory and turn that into a call to memset(). Both clang and GCC assume
> memset() is always available [2].
>
> Hide the value of the iterator variable from the optimizer using
> OPTIMIZER_HIDE_VAR to inhibit this optimization since it can no longer
> assume that the zeroing is contiguous.
>
> Link: https://github.com/llvm/llvm-project/commit/90cebef1411617fc3eedd359bdf00cb44b1c2439 [1]
> Link: https://gcc.gnu.org/onlinedocs/gcc-16.2.0/gcc/Standards.html#index-ffreestanding [2]
> Signed-off-by: Nathan Chancellor <nathan@xxxxxxxxxx>
> ---
> lib/vdso/getrandom.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/lib/vdso/getrandom.c b/lib/vdso/getrandom.c
> index 2851afa9154f..d48d1fdb3351 100644
> --- a/lib/vdso/getrandom.c
> +++ b/lib/vdso/getrandom.c
> @@ -4,6 +4,7 @@
> */
>
> #include <linux/array_size.h>
> +#include <linux/compiler.h>
> #include <linux/minmax.h>
> #include <vdso/datapage.h>
> #include <vdso/getrandom.h>
> @@ -83,8 +84,11 @@ __cvdso_getrandom_data(const struct vdso_rng_data *rng_info, void *buffer, size_
> params->size_of_opaque_state = sizeof(*state);
> params->mmap_prot = PROT_READ | PROT_WRITE;
> params->mmap_flags = MAP_DROPPABLE | MAP_ANONYMOUS;
> - for (size_t i = 0; i < ARRAY_SIZE(params->reserved); ++i)
> + for (size_t i = 0; i < ARRAY_SIZE(params->reserved); ++i) {
> + /* prevent compiler from turning loop into memset() */
> + OPTIMIZER_HIDE_VAR(i);
> params->reserved[i] = 0;
> + }
> return 0;
> }

I don't suspect this is the right change. On x86_64, this changes to
code from:

rep stosq

into:

loc_2D9:
mov dword ptr [rbx+rax*4+0Ch], 0
add rax, 1
cmp rax, 0Ch
jbe short loc_2D9

Which is a lot less compact. It seems like the actual solution is for
gcc&clang to emit this inline memset mnemonic when the platform has a
good one, and otherwise not. But disabling optimizations for all
platforms, because it's broken on one, seems bad.

In this case, the compiler is being smart: it identifies a loop and
rightly turns it into memset. But if this isn't a compilation
environment that has an outline function, it should do something else.

Jason