From: "Jason A. Donenfeld" <Jason@zx2c4.com>
To: Nick Desaulniers <ndesaulniers@google.com>
Cc: Andy Lutomirski <luto@kernel.org>,
Thomas Gleixner <tglx@kernel.org>, Theodore Ts'o <tytso@mit.edu>,
Vincenzo Frascino <vincenzo.frascino@arm.com>,
Bill Wendling <morbo@google.com>,
Justin Stitt <justinstitt@google.com>,
linux-kernel@vger.kernel.org, llvm@lists.linux.dev,
Nathan Chancellor <nathan@kernel.org>
Subject: Re: [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data()
Date: Fri, 18 Sep 2026 21:19:00 +0200 [thread overview]
Message-ID: <aq2OpBZIMVhMZhWW@zx2c4.com> (raw)
In-Reply-To: <aq01ud_zTYN-3Zby@zx2c4.com>
On Fri, Sep 18, 2026 at 02:59:37PM +0200, Jason A. Donenfeld wrote:
> On Fri, Sep 18, 2026 at 10:20:45AM +0200, Jason A. Donenfeld wrote:
> > On Thu, Sep 17, 2026 at 6:49 PM Nick Desaulniers
> > <ndesaulniers@google.com> wrote:
> > >
> > > On Thu, Sep 17, 2026 at 10:39 AM Nathan Chancellor <nathan@kernel.org> wrote:
> > > >
> > > > On Thu, Sep 17, 2026 at 11:26:46AM +0200, Jason A. Donenfeld wrote:
> > > > > 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
> > >
> > > /me nods
> > >
> > > > >
> > > > > 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.
> > >
> > > Ideally, yeah.
> > > Pragmatically:
> > > the compiler doesn't know what you will link against or not; so it
> > > just emits relocations that the linker will (hopefully) resolve. I've
> > > definitely looked at how llvm decides when to emit libcalls to
> > > compiler-rt/libgcc ("the compiler runtime") and thought "I wonder how
> > > this works with compiler runtime version N-1?"
> > >
> > > There's also the requirement gcc and clang have about memcpy, memmove,
> > > memset, memcmp always being available (-ffreestanding or not) noted
> > > below.
> > >
> > > > > 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.
> > > >
> > > > As I mentioned in the commit message, compilers require all environments
> > > > (hosted or not) to provide memset(), so the "doing something else" is
> > > > nothing :)
> > > >
> > > > GCC requires the freestanding environment provide memcpy, memmove,
> > > > memset and memcmp.
> > >
> > > +1
> > >
> > > >
> > > > I guess another option is to just include a basic memset() like the one
> > > > in lib/string.c so that it is only used if the compiler makes this sort
> > > > of transformation, while leaving all other architectures alone.
> > >
> > > It's also possible to get GCC to emit the libcall, even in the
> > > presence of -ffreestanding: https://godbolt.org/z/6hTrYq9z8
> > >
> > > And it's not the first time this code in particular has had this issue;
> > >
> > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b7bad082e113640fc81200ff869e5c2d7a9c29a2
> > >
> > > (is this patch a Fixes: for that?)
> > >
> > > Clang has __builtin_memset_inline to avoid explicit libcalls; AFAICT
> > > GCC does not. So we could use that here to provide such a guarantee
> > > with clang; the code would remain brittle and likely break again with
> > > GCC.
> >
> > It sounds like this is broken currently only on clang on riscv, right?
> > So maybe we can use __builtin_memset_inline, and get something similar
> > into gcc, before a future gcc version also breaks? That way it doesn't
> > break in the future.
>
> There's -finline-stringops=memset for gcc (>=14), which should keep
> things sane there. So, we can use that on gcc, and alias memset to
> __builtin_memset_inline on clang. And then we should be good?
Untested, but putting this all together I suppose looks like this, if
you want to play around and see:
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index 7dec05dd33b7..3b98058f95ea 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -41,7 +41,7 @@ CC_FLAGS_REMOVE_VDSO := $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) \
$(CC_FLAGS_LTO) $(CC_FLAGS_CFI) \
-Wmissing-prototypes -Wmissing-declarations
-CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables
+CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables $(call cc-option,-finline-stringops=memset)
CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_REMOVE_VDSO)
CFLAGS_REMOVE_vgetrandom.o = $(CC_FLAGS_REMOVE_VDSO)
diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile
index 9c9181bb4071..4c6b597a7665 100644
--- a/arch/loongarch/vdso/Makefile
+++ b/arch/loongarch/vdso/Makefile
@@ -16,6 +16,7 @@ ccflags-vdso := \
$(filter -m64,$(KBUILD_CFLAGS)) \
$(filter -march=%,$(KBUILD_CFLAGS)) \
$(filter -m%-float,$(KBUILD_CFLAGS)) \
+ $(call cc-option,-finline-stringops=memset) \
$(CLANG_FLAGS) \
-D__VDSO__
diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
index 8dbf2532a573..720f95cd24f8 100644
--- a/arch/riscv/kernel/vdso/Makefile
+++ b/arch/riscv/kernel/vdso/Makefile
@@ -36,6 +36,7 @@ endif
ccflags-y := -fno-stack-protector
ccflags-y += -DDISABLE_BRANCH_PROFILING
ccflags-y += -fno-builtin
+ccflags-y += $(call cc-option,-finline-stringops=memset)
ccflags-y += $(KBUILD_BASE_ISA)$(CFI_MARCH)
ccflags-y += $(CFI_FULL)
asflags-y += $(KBUILD_BASE_ISA)$(CFI_MARCH)
diff --git a/arch/s390/kernel/vdso/Makefile b/arch/s390/kernel/vdso/Makefile
index 35c834b895ec..9d0ae1f38388 100644
--- a/arch/s390/kernel/vdso/Makefile
+++ b/arch/s390/kernel/vdso/Makefile
@@ -29,6 +29,7 @@ KBUILD_CFLAGS_VDSO := $(filter-out -munaligned-symbols,$(KBUILD_CFLAGS_VDSO))
KBUILD_CFLAGS_VDSO := $(filter-out -fno-asynchronous-unwind-tables,$(KBUILD_CFLAGS_VDSO))
KBUILD_CFLAGS_VDSO += -fPIC -fno-common -fno-builtin -fasynchronous-unwind-tables
KBUILD_CFLAGS_VDSO += -fno-stack-protector $(DISABLE_KSTACK_ERASE)
+KBUILD_CFLAGS_VDSO += $(call cc-option,-finline-stringops=memset)
ldflags-y := -shared -soname=linux-vdso.so.1 \
--hash-style=both --build-id=sha1 \
$(call ld-option, --eh-frame-hdr) -T
diff --git a/arch/x86/entry/vdso/vdso64/Makefile b/arch/x86/entry/vdso/vdso64/Makefile
index 7c0790065b5e..751cb6f99b65 100644
--- a/arch/x86/entry/vdso/vdso64/Makefile
+++ b/arch/x86/entry/vdso/vdso64/Makefile
@@ -14,7 +14,7 @@ vobjs-$(CONFIG_X86_SGX) += vsgx.o
vobjs-$(CONFIG_FUTEX_ROBUST_UNLOCK) += vfutex.o
# Compilation flags
-flags-y := -DBUILD_VDSO64 -m64 -mcmodel=small
+flags-y := -DBUILD_VDSO64 -m64 -mcmodel=small $(call cc-option,-finline-stringops=memset)
# The location of this include matters!
include $(src)/../common/Makefile.include
diff --git a/lib/vdso/getrandom.c b/lib/vdso/getrandom.c
index 2851afa9154f..713e95dfdedc 100644
--- a/lib/vdso/getrandom.c
+++ b/lib/vdso/getrandom.c
@@ -29,6 +29,12 @@
} \
} while (0)
+#if __has_builtin(__builtin_memset_inline)
+#define memset(dst, value, size) __builtin_memset_inline(dst, value, size)
+#else
+#define memset(dst, value, size) __builtin_memset(dst, value, size)
+#endif
+
static void memcpy_and_zero_src(void *dst, void *src, size_t len)
{
if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) {
@@ -83,8 +89,7 @@ __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)
- params->reserved[i] = 0;
+ memset(params->reserved, 0, sizeof(params->reserved));
return 0;
}
next prev parent reply other threads:[~2026-09-18 19:19 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-16 21:58 [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data() Nathan Chancellor
2026-09-16 22:08 ` Nick Desaulniers
2026-09-16 22:57 ` Nathan Chancellor
2026-09-16 23:40 ` Nick Desaulniers
2026-09-17 9:26 ` Jason A. Donenfeld
2026-09-17 17:39 ` Nathan Chancellor
2026-09-17 22:49 ` Nick Desaulniers
2026-09-18 8:20 ` Jason A. Donenfeld
2026-09-18 12:59 ` Jason A. Donenfeld
2026-09-18 19:19 ` Jason A. Donenfeld [this message]
2026-09-18 21:07 ` Nathan Chancellor
2026-09-19 10:57 ` Jason A. Donenfeld
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aq2OpBZIMVhMZhWW@zx2c4.com \
--to=jason@zx2c4.com \
--cc=justinstitt@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=luto@kernel.org \
--cc=morbo@google.com \
--cc=nathan@kernel.org \
--cc=ndesaulniers@google.com \
--cc=tglx@kernel.org \
--cc=tytso@mit.edu \
--cc=vincenzo.frascino@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.