From: "Jason A. Donenfeld" <Jason@zx2c4.com>
To: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <ndesaulniers@google.com>,
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
Subject: Re: [PATCH] random: vDSO: Avoid call to memset() when zeroing reserved in __cvdso_getrandom_data()
Date: Sat, 19 Sep 2026 12:57:10 +0200 [thread overview]
Message-ID: <aq5qhgPT63dY2xg4@zx2c4.com> (raw)
In-Reply-To: <20260918210744.GA235304@ax162>
On Fri, Sep 18, 2026 at 02:07:44PM -0700, Nathan Chancellor wrote:
> On Fri, Sep 18, 2026 at 09:19:00PM +0200, Jason A. Donenfeld wrote:
> > Untested, but putting this all together I suppose looks like this, if
> > you want to play around and see:
>
> Thanks!
>
> > 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;
> > }
>
> This will regress GCC < 14 because '-finline-stringops=memset' does not
> exist yet, meaning __builtin_memset() may still generated a call to
> memset(). Testing GCC 13 with ARCH=riscv defconfig, I get the same error
> as originally reported up thread. I am not sure we can get rid of the
> loop for that reason. I tested the following diff that keeps
>
> clang (__builtin_memset_inline)
> GCC 14+ (-finline-stringops=memset + __builtin_memset)
> GCC <14 (simple loop)
>
> happy (and moves the checks into Kconfig, which is being discussed at a
> wider level [1]) but it is admittedly slightly uglier... That said, it
> certainly seems more robust.
>
> [1]: https://lore.kernel.org/linux-kbuild/20260917-build-speedup-v3-11-9ecf4163ff36@kernel.org
>
> diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
> index 7dec05dd33b7..f6619e1cb2ce 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 $(CONFIG_CC_OPT_INLINE_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..0b84892d084b 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)) \
> + $(CONFIG_CC_OPT_INLINE_MEMSET) \
> $(CLANG_FLAGS) \
> -D__VDSO__
>
> diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
> index 8dbf2532a573..c023046a3fd7 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 += $(CONFIG_CC_OPT_INLINE_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..54bcf2984ca1 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 += $(CONFIG_CC_OPT_INLINE_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..c2353a065279 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 $(CONFIG_CC_OPT_INLINE_MEMSET)
>
> # The location of this include matters!
> include $(src)/../common/Makefile.include
> diff --git a/init/Kconfig b/init/Kconfig
> index 6e82b4957a5d..09251b5f79d4 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -173,6 +173,13 @@ config CC_HAS_ALLOC_TOKEN
> config CC_HAS_MULTIDIMENSIONAL_NONSTRING
> def_bool $(success,echo 'char tag[][4] __attribute__((__nonstring__)) = { };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror)
>
> +config CC_HAS_OPT_INLINE_MEMSET
> + def_bool $(cc-option,-finline-stringops=memset)
> +
> +config CC_OPT_INLINE_MEMSET
> + string
> + default "-finline-stringops=memset" if CC_HAS_OPT_INLINE_MEMSET
> +
> config LD_CAN_USE_KEEP_IN_OVERLAY
> # ld.lld prior to 21.0.0 did not support KEEP within an overlay description
> # https://github.com/llvm/llvm-project/pull/130661
> diff --git a/lib/vdso/getrandom.c b/lib/vdso/getrandom.c
> index 2851afa9154f..83831dab08b2 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_inline(dst, value, size) __builtin_memset_inline(dst, value, size)
> +#elif IS_ENABLED(CONFIG_CC_HAS_OPT_INLINE_MEMSET)
> +#define memset_inline(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,12 @@ __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;
> +#ifdef memset_inline
> + memset_inline(params->reserved, 0, sizeof(params->reserved));
> +#else
> for (size_t i = 0; i < ARRAY_SIZE(params->reserved); ++i)
> params->reserved[i] = 0;
> +#endif
> return 0;
> }
I wonder if it makes more sense to have an "#else static inline void memset(...) { for (...) .. = 0; }"
in the ifdef defines for memset, rather than cluttering the function
with an ifdef like that.
Also, I might have left ppc out of my initial commit.
Nick, do you have feelings about this approach?
prev parent reply other threads:[~2026-09-19 10:57 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
2026-09-18 21:07 ` Nathan Chancellor
2026-09-19 10:57 ` Jason A. Donenfeld [this message]
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=aq5qhgPT63dY2xg4@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.