[glibc] elf: Do not scrub AT_RANDOM to a constant when reseeding fails (BZ 34197)

Adhemerval Zanella via Glibc-cvs <[email protected]> Wed, 17 Jun 2026 13:02:51 +0000 (GMT)
Newsgroups gmane.comp.lib.glibc.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=242a1f4b0f8d72948ee14a33c2dd5d0c361b6d73

commit 242a1f4b0f8d72948ee14a33c2dd5d0c361b6d73
Author: Adhemerval Zanella <[email protected]>
Date:   Tue Jun 16 16:10:01 2026 -0300

    elf: Do not scrub AT_RANDOM to a constant when reseeding fails (BZ 34197)
    
    _dl_reseed_random zeroed the AT_RANDOM bytes before refilling them with
    getrandom (GRND_NONBLOCK).  That call is best-effort and can write nothing
    (e.g. before the kernel entropy pool is initialized early at boot), leaving
    the 16 bytes as a constant zero.
    
    Since the value is exposed through getauxval (AT_RANDOM), this traded a
    potential guard leak for a guaranteed predictable value.
    
    Drop the memset and overwrite the bytes in place instead.  The generic
    version now just drops the pointer (it is not used anywhere).
    
    Checked on x86_64-linux-gnu and i686-linux-gnu.
    
    Reviewed-by: Florian Weimer <[email protected]>

Diff:
---
 sysdeps/generic/dl-reseed-random.h         |  8 +++-----
 sysdeps/unix/sysv/linux/dl-reseed-random.h | 17 +++++++++--------
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/sysdeps/generic/dl-reseed-random.h b/sysdeps/generic/dl-reseed-random.h
index 7e1a3c3be2..b55bdb909c 100644
--- a/sysdeps/generic/dl-reseed-random.h
+++ b/sysdeps/generic/dl-reseed-random.h
@@ -19,15 +19,13 @@
 #ifndef _DL_RESEED_RANDOM_H
 #define _DL_RESEED_RANDOM_H
 
-#include <string.h>
+#include <stddef.h>
 
+/* Leave the kernel-provided bytes untouched rather than scrubbing them to a
+   predictable constant, the value is exposed through getauxval (AT_RANDOM). */
 static inline void __attribute__ ((always_inline))
 _dl_reseed_random (void **dl_random)
 {
-  if (*dl_random == NULL)
-    return;
-  memset (*dl_random, '\0', 16);
-  __asm__ __volatile__ ("" : : "r" (*dl_random) : "memory");
   *dl_random = NULL;
 }
 
diff --git a/sysdeps/unix/sysv/linux/dl-reseed-random.h b/sysdeps/unix/sysv/linux/dl-reseed-random.h
index b0ceb5cc65..cf0a898b99 100644
--- a/sysdeps/unix/sysv/linux/dl-reseed-random.h
+++ b/sysdeps/unix/sysv/linux/dl-reseed-random.h
@@ -19,23 +19,24 @@
 #ifndef _DL_RESEED_RANDOM_H
 #define _DL_RESEED_RANDOM_H
 
-#include <string.h>
 #include <not-cancel.h>
 #include <sys/random.h>
 
 /* The stack and pointer guards have been derived from the 16 AT_RANDOM
-   bytes pointed to by DL_RANDOM.  Scrub them first, so the guards cannot be
-   recovered even if the refill below fails, then refill them with fresh
-   entropy unrelated to the guards so that getauxval (AT_RANDOM) keeps
-   returning random bytes.  */
+   bytes pointed to by DL_RANDOM.  Overwrite them in place with fresh entropy
+   unrelated to the guards, so the value returned by getauxval (AT_RANDOM) no
+   longer reveals them while still being random.
+
+   This is best-effort and must not perturb process startup.  The getrandom
+   might not provide all the requested entropy, and leaving the original bytes
+   is deliberate: AT_RANDOM is exposed through getauxval, and a potential
+   leak of the guards is preferable to scrubbing the value to a predictable
+   constant.  */
 static inline void __attribute__ ((always_inline))
 _dl_reseed_random (void **dl_random)
 {
   if (*dl_random == NULL)
     return;
-  memset (*dl_random, '\0', 16);
-  __asm__ __volatile__ ("" : : "r" (*dl_random) : "memory");
-
   __getrandom_nocancel_nostatus_direct (*dl_random, 16, GRND_NONBLOCK);
   *dl_random = NULL;
 }