[v6,01/10] stdlib: Add arc4random, arc4random_buf, and arc4random_uniform (BZ #4417)

Message ID 20220518191424.3630729-2-adhemerval.zanella@linaro.org
State Superseded
Headers
Series Add arc4random support |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent

Commit Message

Adhemerval Zanella Netto May 18, 2022, 7:14 p.m. UTC
  The implementation is based on scalar Chacha20, with global cache and
locking.  It uses getrandom or /dev/urandom as fallback to get the
initial entropy, and reseeds the internal state on every 16MB of
consumed buffer.

It maintains an internal buffer which consumes at maximum one page on
most systems (assuming minimum of 4k pages).  The internal buf optimizes
the cipher encrypt calls, by amortizing arc4random calls (where both
function call and lock cost are the dominating factor).

The ChaCha20 implementation is based on RFC8439 [1], omitting the final
XOR of the keystream with the plaintext because the plaintext is a
stream of zeros.  This strategy is similar to what OpenBSD arc4random
does.

The arc4random_uniform is based on previous work by Florian Weimer,
where the algorithm is based on Jérémie Lumbroso paper Optimal Discrete
Uniform Generation from Coin Flips, and Applications (2013) [2], who
credits Donald E. Knuth and Andrew C. Yao, The complexity of nonuniform
random number generation (1976), for solving the general case.

The main advantage of this method is the that the unit of randomness is not
the uniform random variable (uint32_t), but a random bit.  It optimizes the
internal buffer sampling by initially consuming a 32-bit random variable
and then sampling byte per byte.  Depending of the upper bound requested,
it might lead to better CPU utilization.

Checked on x86_64-linux-gnu, aarch64-linux, and powerpc64le-linux-gnu.

Co-authored-by: Florian Weimer <fweimer@redhat.com>

[1] https://datatracker.ietf.org/doc/html/rfc8439
[2] https://arxiv.org/pdf/1304.1916.pdf
---
 NEWS                                          |   4 +
 include/stdlib.h                              |  13 +
 stdlib/Makefile                               |   2 +
 stdlib/Versions                               |   5 +
 stdlib/arc4random.c                           | 244 ++++++++++++++++++
 stdlib/arc4random_uniform.c                   | 152 +++++++++++
 stdlib/chacha20.c                             | 188 ++++++++++++++
 stdlib/stdlib.h                               |  14 +
 sysdeps/generic/not-cancel.h                  |   2 +
 sysdeps/mach/hurd/_Fork.c                     |   2 +
 sysdeps/mach/hurd/i386/libc.abilist           |   5 +-
 sysdeps/mach/hurd/not-cancel.h                |   3 +
 sysdeps/nptl/_Fork.c                          |   2 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |   3 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |   3 +
 sysdeps/unix/sysv/linux/arc/libc.abilist      |   3 +
 sysdeps/unix/sysv/linux/arm/be/libc.abilist   |   3 +
 sysdeps/unix/sysv/linux/arm/le/libc.abilist   |   3 +
 sysdeps/unix/sysv/linux/csky/libc.abilist     |   3 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |   3 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |   3 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist     |   3 +
 .../sysv/linux/m68k/coldfire/libc.abilist     |   3 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |   3 +
 .../sysv/linux/microblaze/be/libc.abilist     |   3 +
 .../sysv/linux/microblaze/le/libc.abilist     |   3 +
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |   3 +
 .../sysv/linux/mips/mips32/nofpu/libc.abilist |   3 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |   3 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |   3 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |   3 +
 sysdeps/unix/sysv/linux/not-cancel.h          |   7 +
 sysdeps/unix/sysv/linux/or1k/libc.abilist     |   3 +
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |   3 +
 .../powerpc/powerpc32/nofpu/libc.abilist      |   3 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |   3 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |   3 +
 .../unix/sysv/linux/riscv/rv32/libc.abilist   |   3 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |   3 +
 .../unix/sysv/linux/s390/s390-32/libc.abilist |   3 +
 .../unix/sysv/linux/s390/s390-64/libc.abilist |   3 +
 sysdeps/unix/sysv/linux/sh/be/libc.abilist    |   3 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |   3 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |   3 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |   3 +
 .../unix/sysv/linux/x86_64/64/libc.abilist    |   3 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |   3 +
 47 files changed, 741 insertions(+), 1 deletion(-)
 create mode 100644 stdlib/arc4random.c
 create mode 100644 stdlib/arc4random_uniform.c
 create mode 100644 stdlib/chacha20.c
  

Comments

Yann Droneaud June 2, 2022, 9:44 a.m. UTC | #1
Hi,

Found some time to review arc4random_uniform() implementation this time.


Le 18/05/2022 à 21:14, Adhemerval Zanella via Libc-alpha a écrit :
> The implementation is based on scalar Chacha20, with global cache and
> locking.  It uses getrandom or /dev/urandom as fallback to get the
> initial entropy, and reseeds the internal state on every 16MB of
> consumed buffer.
>
> It maintains an internal buffer which consumes at maximum one page on
> most systems (assuming minimum of 4k pages).  The internal buf optimizes
> the cipher encrypt calls, by amortizing arc4random calls (where both
> function call and lock cost are the dominating factor).
>
> The ChaCha20 implementation is based on RFC8439 [1], omitting the final
> XOR of the keystream with the plaintext because the plaintext is a
> stream of zeros.  This strategy is similar to what OpenBSD arc4random
> does.
>
> The arc4random_uniform is based on previous work by Florian Weimer,
> where the algorithm is based on Jérémie Lumbroso paper Optimal Discrete
> Uniform Generation from Coin Flips, and Applications (2013) [2], who
> credits Donald E. Knuth and Andrew C. Yao, The complexity of nonuniform
> random number generation (1976), for solving the general case.
>
> The main advantage of this method is the that the unit of randomness is not
> the uniform random variable (uint32_t), but a random bit.  It optimizes the
> internal buffer sampling by initially consuming a 32-bit random variable
> and then sampling byte per byte.  Depending of the upper bound requested,
> it might lead to better CPU utilization.
>
> Checked on x86_64-linux-gnu, aarch64-linux, and powerpc64le-linux-gnu.
>
> Co-authored-by: Florian Weimer <fweimer@redhat.com>
>
> [1] https://datatracker.ietf.org/doc/html/rfc8439
> [2] https://arxiv.org/pdf/1304.1916.pdf
> ---
>
> diff --git a/stdlib/arc4random_uniform.c b/stdlib/arc4random_uniform.c
> new file mode 100644
> index 0000000000..722e92b3a7
> --- /dev/null
> +++ b/stdlib/arc4random_uniform.c
> @@ -0,0 +1,152 @@
> +/* Random pseudo generator numbers between 0 and 2**-31 (inclusive)
upper bound is incorrect
> +   uniformly distributed but with an upper_bound.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <endian.h>
> +#include <libc-lock.h>
> +#include <stdlib.h>
> +#include <sys/param.h>
> +
> +/* Return the number of bytes which cover values up to the limit.  */
> +__attribute__ ((const))
> +static uint32_t
> +byte_count (uint32_t n)
> +{
> +  if (n < (1U << 8))
> +    return 1;
> +  else if (n < (1U << 16))
> +    return 2;
> +  else if (n < (1U << 24))
> +    return 3;
> +  else
> +    return 4;
> +}
> +
> +/* Fill the lower bits of the result with randomness, according to the
> +   number of bytes requested.  */
> +static void
> +random_bytes (uint32_t *result, uint32_t byte_count)
> +{
> +  *result = 0;
> +  unsigned char *ptr = (unsigned char *) result;
> +  if (__BYTE_ORDER == __BIG_ENDIAN)
> +    ptr += 4 - byte_count;
> +  __arc4random_buf_internal (ptr, byte_count);
> +}
> +
> +static uint32_t
> +compute_uniform (uint32_t n)
> +{
> +  if (n <= 1)
> +    /* There is no valid return value for a zero limit, and 0 is the
> +       only possible result for limit 1.  */
> +    return 0;
> +
> +  /* The bits variable serves as a source for bits.  Prefetch the
> +     minimum number of bytes needed.  */
> +  uint32_t count = byte_count (n);
> +  uint32_t bits_length = count * CHAR_BIT;
> +  uint32_t bits;
> +  random_bytes (&bits, count);
> +
> +  /* Powers of two are easy.  */
> +  if (powerof2 (n))
> +    return bits & (n - 1);
> +
> +  /* The general case.  This algorithm follows Jérémie Lumbroso,
> +     Optimal Discrete Uniform Generation from Coin Flips, and
> +     Applications (2013), who credits Donald E. Knuth and Andrew
> +     C. Yao, The complexity of nonuniform random number generation
> +     (1976), for solving the general case.
> +
> +     The implementation below unrolls the initialization stage of the
> +     loop, where v is less than n.  */
> +
> +  /* Use 64-bit variables even though the intermediate results are
> +     never larger than 33 bits.  This ensures the code is easier to
> +     compile on 64-bit architectures.  */
> +  uint64_t v;
> +  uint64_t c;
> +
> +  /* Initialize v and c.  v is the smallest power of 2 which is larger
> +     than n.*/
> +  {
> +    uint32_t log2p1 = 32 - __builtin_clz (n);
> +    v = 1ULL << log2p1;
> +    c = bits & (v - 1);
> +    bits >>= log2p1;
> +    bits_length -= log2p1;
> +  }
> +
> +  /* At the start of the loop, c is uniformly distributed within the
> +     half-open interval [0, v), and v < 2n < 2**33.  */
> +  while (true)
> +    {
> +      if (v >= n)
> +        {
> +          /* If the candidate is less than n, accept it.  */
> +          if (c < n)
> +            /* c is uniformly distributed on [0, n).  */
> +            return c;
> +          else
> +            {
> +              /* c is uniformly distributed on [n, v).  */
> +              v -= n;
> +              c -= n;
> +              /* The distribution was shifted, so c is uniformly
> +                 distributed on [0, v) again.  */
> +            }
> +        }
> +      /* v < n here.  */
> +
> +      /* Replenish the bit source if necessary.  */
> +      if (bits_length == 0)
> +        {
> +          /* Overwrite the least significant byte.  */
> +	  random_bytes (&bits, 1);
> +	  bits_length = CHAR_BIT;
> +        }
> +
> +      /* Double the range.  No overflow because v < n < 2**32.  */
> +      v *= 2;
> +      /* v < 2n here.  */
> +
> +      /* Extract a bit and append it to c.  c remains less than v and
> +         thus 2**33.  */
> +      c = (c << 1) | (bits & 1);
> +      bits >>= 1;
> +      --bits_length;
> +
> +      /* At this point, c is uniformly distributed on [0, v) again,
> +         and v < 2n < 2**33.  */
> +    }
> +}
> +
> +__libc_lock_define (extern , __arc4random_lock attribute_hidden)
> +
> +uint32_t
> +__arc4random_uniform (uint32_t upper_bound)
> +{
> +  uint32_t r;
> +  __libc_lock_lock (__arc4random_lock);
> +  r = compute_uniform (upper_bound);
> +  __libc_lock_unlock (__arc4random_lock);
> +  return r;
> +}
> +libc_hidden_def (__arc4random_uniform)
> +weak_alias (__arc4random_uniform, arc4random_uniform)

Seems fine from a computation point of view.

So for what it worth:

LGTM

Reviewed-by: Yann Droneaud <ydroneaud@opteya.com>


Regards.
  
Adhemerval Zanella Netto June 10, 2022, 5:26 p.m. UTC | #2
On 02/06/2022 06:44, Yann Droneaud wrote:
> Hi,
> 
> Found some time to review arc4random_uniform() implementation this time.
> 
> 
> Le 18/05/2022 à 21:14, Adhemerval Zanella via Libc-alpha a écrit :
>> The implementation is based on scalar Chacha20, with global cache and
>> locking.  It uses getrandom or /dev/urandom as fallback to get the
>> initial entropy, and reseeds the internal state on every 16MB of
>> consumed buffer.
>>
>> It maintains an internal buffer which consumes at maximum one page on
>> most systems (assuming minimum of 4k pages).  The internal buf optimizes
>> the cipher encrypt calls, by amortizing arc4random calls (where both
>> function call and lock cost are the dominating factor).
>>
>> The ChaCha20 implementation is based on RFC8439 [1], omitting the final
>> XOR of the keystream with the plaintext because the plaintext is a
>> stream of zeros.  This strategy is similar to what OpenBSD arc4random
>> does.
>>
>> The arc4random_uniform is based on previous work by Florian Weimer,
>> where the algorithm is based on Jérémie Lumbroso paper Optimal Discrete
>> Uniform Generation from Coin Flips, and Applications (2013) [2], who
>> credits Donald E. Knuth and Andrew C. Yao, The complexity of nonuniform
>> random number generation (1976), for solving the general case.
>>
>> The main advantage of this method is the that the unit of randomness is not
>> the uniform random variable (uint32_t), but a random bit.  It optimizes the
>> internal buffer sampling by initially consuming a 32-bit random variable
>> and then sampling byte per byte.  Depending of the upper bound requested,
>> it might lead to better CPU utilization.
>>
>> Checked on x86_64-linux-gnu, aarch64-linux, and powerpc64le-linux-gnu.
>>
>> Co-authored-by: Florian Weimer <fweimer@redhat.com>
>>
>> [1] https://datatracker.ietf.org/doc/html/rfc8439
>> [2] https://arxiv.org/pdf/1304.1916.pdf
>> ---
>>
>> diff --git a/stdlib/arc4random_uniform.c b/stdlib/arc4random_uniform.c
>> new file mode 100644
>> index 0000000000..722e92b3a7
>> --- /dev/null
>> +++ b/stdlib/arc4random_uniform.c
>> @@ -0,0 +1,152 @@
>> +/* Random pseudo generator numbers between 0 and 2**-31 (inclusive)
> upper bound is incorrect

Right, I changed to:

/* Random pseudo generator number which returns a single 32 bit value
   uniformly distributed but with an upper_bound.


>> +   uniformly distributed but with an upper_bound.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
>> +
>> +#include <endian.h>
>> +#include <libc-lock.h>
>> +#include <stdlib.h>
>> +#include <sys/param.h>
>> +
>> +/* Return the number of bytes which cover values up to the limit.  */
>> +__attribute__ ((const))
>> +static uint32_t
>> +byte_count (uint32_t n)
>> +{
>> +  if (n < (1U << 8))
>> +    return 1;
>> +  else if (n < (1U << 16))
>> +    return 2;
>> +  else if (n < (1U << 24))
>> +    return 3;
>> +  else
>> +    return 4;
>> +}
>> +
>> +/* Fill the lower bits of the result with randomness, according to the
>> +   number of bytes requested.  */
>> +static void
>> +random_bytes (uint32_t *result, uint32_t byte_count)
>> +{
>> +  *result = 0;
>> +  unsigned char *ptr = (unsigned char *) result;
>> +  if (__BYTE_ORDER == __BIG_ENDIAN)
>> +    ptr += 4 - byte_count;
>> +  __arc4random_buf_internal (ptr, byte_count);
>> +}
>> +
>> +static uint32_t
>> +compute_uniform (uint32_t n)
>> +{
>> +  if (n <= 1)
>> +    /* There is no valid return value for a zero limit, and 0 is the
>> +       only possible result for limit 1.  */
>> +    return 0;
>> +
>> +  /* The bits variable serves as a source for bits.  Prefetch the
>> +     minimum number of bytes needed.  */
>> +  uint32_t count = byte_count (n);
>> +  uint32_t bits_length = count * CHAR_BIT;
>> +  uint32_t bits;
>> +  random_bytes (&bits, count);
>> +
>> +  /* Powers of two are easy.  */
>> +  if (powerof2 (n))
>> +    return bits & (n - 1);
>> +
>> +  /* The general case.  This algorithm follows Jérémie Lumbroso,
>> +     Optimal Discrete Uniform Generation from Coin Flips, and
>> +     Applications (2013), who credits Donald E. Knuth and Andrew
>> +     C. Yao, The complexity of nonuniform random number generation
>> +     (1976), for solving the general case.
>> +
>> +     The implementation below unrolls the initialization stage of the
>> +     loop, where v is less than n.  */
>> +
>> +  /* Use 64-bit variables even though the intermediate results are
>> +     never larger than 33 bits.  This ensures the code is easier to
>> +     compile on 64-bit architectures.  */
>> +  uint64_t v;
>> +  uint64_t c;
>> +
>> +  /* Initialize v and c.  v is the smallest power of 2 which is larger
>> +     than n.*/
>> +  {
>> +    uint32_t log2p1 = 32 - __builtin_clz (n);
>> +    v = 1ULL << log2p1;
>> +    c = bits & (v - 1);
>> +    bits >>= log2p1;
>> +    bits_length -= log2p1;
>> +  }
>> +
>> +  /* At the start of the loop, c is uniformly distributed within the
>> +     half-open interval [0, v), and v < 2n < 2**33.  */
>> +  while (true)
>> +    {
>> +      if (v >= n)
>> +        {
>> +          /* If the candidate is less than n, accept it.  */
>> +          if (c < n)
>> +            /* c is uniformly distributed on [0, n).  */
>> +            return c;
>> +          else
>> +            {
>> +              /* c is uniformly distributed on [n, v).  */
>> +              v -= n;
>> +              c -= n;
>> +              /* The distribution was shifted, so c is uniformly
>> +                 distributed on [0, v) again.  */
>> +            }
>> +        }
>> +      /* v < n here.  */
>> +
>> +      /* Replenish the bit source if necessary.  */
>> +      if (bits_length == 0)
>> +        {
>> +          /* Overwrite the least significant byte.  */
>> +      random_bytes (&bits, 1);
>> +      bits_length = CHAR_BIT;
>> +        }
>> +
>> +      /* Double the range.  No overflow because v < n < 2**32.  */
>> +      v *= 2;
>> +      /* v < 2n here.  */
>> +
>> +      /* Extract a bit and append it to c.  c remains less than v and
>> +         thus 2**33.  */
>> +      c = (c << 1) | (bits & 1);
>> +      bits >>= 1;
>> +      --bits_length;
>> +
>> +      /* At this point, c is uniformly distributed on [0, v) again,
>> +         and v < 2n < 2**33.  */
>> +    }
>> +}
>> +
>> +__libc_lock_define (extern , __arc4random_lock attribute_hidden)
>> +
>> +uint32_t
>> +__arc4random_uniform (uint32_t upper_bound)
>> +{
>> +  uint32_t r;
>> +  __libc_lock_lock (__arc4random_lock);
>> +  r = compute_uniform (upper_bound);
>> +  __libc_lock_unlock (__arc4random_lock);
>> +  return r;
>> +}
>> +libc_hidden_def (__arc4random_uniform)
>> +weak_alias (__arc4random_uniform, arc4random_uniform)
> 
> Seems fine from a computation point of view.
> 
> So for what it worth:
> 
> LGTM
> 
> Reviewed-by: Yann Droneaud <ydroneaud@opteya.com>

Thanks.

> 
> 
> Regards.
>
  

Patch

diff --git a/NEWS b/NEWS
index ad0c08d8ca..8bfc5f98c1 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,10 @@  Major new features:
   have been added.  The pidfd functionality provides access to a process
   while avoiding the issue of PID reuse on tranditional Unix systems.
 
+* The functions arc4random, arc4random_buf, and arc4random_uniform have been
+  added.  The functions use a cryptographic pseudo-random number generator
+  based on ChaCha20 initilized with entropy from the kernel.
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * Support for prelink will be removed in the next release; this includes
diff --git a/include/stdlib.h b/include/stdlib.h
index 1c6f70b082..c5f5628f22 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -144,6 +144,19 @@  libc_hidden_proto (__ptsname_r)
 libc_hidden_proto (grantpt)
 libc_hidden_proto (unlockpt)
 
+__typeof (arc4random) __arc4random;
+libc_hidden_proto (__arc4random);
+__typeof (arc4random_buf) __arc4random_buf;
+libc_hidden_proto (__arc4random_buf);
+__typeof (arc4random_uniform) __arc4random_uniform;
+libc_hidden_proto (__arc4random_uniform);
+extern void __arc4random_buf_internal (void *buffer, size_t len)
+     attribute_hidden;
+/* Called from the fork function to reinitialize the internal lock in the
+   child process.  This avoids deadlocks if fork is called in multi-threaded
+   processes.  */
+extern void __arc4random_fork_subprocess (void) attribute_hidden;
+
 extern double __strtod_internal (const char *__restrict __nptr,
 				 char **__restrict __endptr, int __group)
      __THROW __nonnull ((1)) __wur;
diff --git a/stdlib/Makefile b/stdlib/Makefile
index 60fc59c12c..9f9cc1bd7f 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -53,6 +53,8 @@  routines := \
   a64l \
   abort \
   abs \
+  arc4random \
+  arc4random_uniform \
   at_quick_exit \
   atof \
   atoi \
diff --git a/stdlib/Versions b/stdlib/Versions
index 5e9099a153..d09a308fb5 100644
--- a/stdlib/Versions
+++ b/stdlib/Versions
@@ -136,6 +136,11 @@  libc {
     strtof32; strtof64; strtof32x;
     strtof32_l; strtof64_l; strtof32x_l;
   }
+  GLIBC_2.36 {
+    arc4random;
+    arc4random_buf;
+    arc4random_uniform;
+  }
   GLIBC_PRIVATE {
     # functions which have an additional interface since they are
     # are cancelable.
diff --git a/stdlib/arc4random.c b/stdlib/arc4random.c
new file mode 100644
index 0000000000..f6553dfd7d
--- /dev/null
+++ b/stdlib/arc4random.c
@@ -0,0 +1,244 @@ 
+/* Pseudo Random Number Generator based on ChaCha20.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <libc-lock.h>
+#include <not-cancel.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/random.h>
+
+/* Besides the cipher state 'ctx', it keeps two counters: 'have' is the
+   current valid bytes not yet consumed in 'buf', while 'count' is the maximum
+   number of bytes until a reseed.
+
+   Both the initial seed and reseed try to obtain entropy from the kernel
+   and abort the process if none could be obtained.
+
+   The state 'buf' improves the usage of the cipher calls, allowing to call
+   optimized implementations (if the architecture provides it) and optimize
+   arc4random calls (since only multiple calls it will encrypt the next
+   block).  */
+
+/* Maximum number bytes until reseed (16 MB).  */
+#define CHACHA20_RESEED_SIZE	(16 * 1024 * 1024)
+/* Internal buffer size in bytes (512B).  */
+#define CHACHA20_BUFSIZE        (8 * CHACHA20_BLOCK_SIZE)
+
+#include <chacha20.c>
+
+static struct arc4random_state
+{
+  uint32_t ctx[CHACHA20_STATE_LEN];
+  size_t have;
+  size_t count;
+  uint8_t buf[CHACHA20_BUFSIZE];
+} *state;
+
+/* Indicate that MADV_WIPEONFORK is supported by the kernel and thus
+   it does not require to clear the internal state.  */
+static bool __arc4random_wipeonfork = false;
+
+__libc_lock_define_initialized (, __arc4random_lock);
+
+/* Called from the fork function to reset the state if MADV_WIPEONFORK is
+   not supported and to reinit the internal lock.  */
+void
+__arc4random_fork_subprocess (void)
+{
+  if (!__arc4random_wipeonfork && state != NULL)
+    memset (state, 0, sizeof (struct arc4random_state));
+
+  __libc_lock_init (__arc4random_lock);
+}
+
+static void
+arc4random_allocate_failure (void)
+{
+  __libc_fatal ("Fatal glibc error: Cannot allocate memory for arc4random\n");
+}
+
+static void
+arc4random_getrandom_failure (void)
+{
+  __libc_fatal ("Fatal glibc error: Cannot get entropy for arc4random\n");
+}
+
+/* Fork detection is done by checking if MADV_WIPEONFORK supported.  If not
+   the fork callback will reset the state on the fork call.  It does not
+   handle direct clone calls, nor vfork or _Fork (arc4random is not
+   async-signal-safe due the internal lock usage).  */
+static void
+arc4random_init (uint8_t *buf)
+{
+  state = __mmap (NULL, sizeof (struct arc4random_state),
+		  PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  if (state == MAP_FAILED)
+    arc4random_allocate_failure ();
+
+#ifdef MADV_WIPEONFORK
+  int r = __madvise (state, sizeof (struct arc4random_state), MADV_WIPEONFORK);
+  if (r == 0)
+    __arc4random_wipeonfork = true;
+  else if (errno != EINVAL)
+    arc4random_allocate_failure ();
+#endif
+
+  chacha20_init (state->ctx, buf, buf + CHACHA20_KEY_SIZE);
+}
+
+#define min(x,y) (((x) > (y)) ? (y) : (x))
+
+static void
+arc4random_rekey (uint8_t *rnd, size_t rndlen)
+{
+  chacha20_crypt (state->ctx, state->buf, state->buf, sizeof state->buf);
+
+  /* Mix some extra entropy if provided.  */
+  if (rnd != NULL)
+    {
+      size_t m = min (rndlen, CHACHA20_KEY_SIZE + CHACHA20_IV_SIZE);
+      for (size_t i = 0; i < m; i++)
+	state->buf[i] ^= rnd[i];
+    }
+
+  /* Immediately reinit for backtracking resistance.  */
+  chacha20_init (state->ctx, state->buf, state->buf + CHACHA20_KEY_SIZE);
+  memset (state->buf, 0, CHACHA20_KEY_SIZE + CHACHA20_IV_SIZE);
+  state->have = sizeof (state->buf) - (CHACHA20_KEY_SIZE + CHACHA20_IV_SIZE);
+}
+
+static void
+arc4random_getentropy (uint8_t *rnd, size_t len)
+{
+  if (__getrandom_nocancel (rnd, len, GRND_NONBLOCK) == len)
+    return;
+
+  int fd = __open64_nocancel ("/dev/urandom", O_RDONLY | O_CLOEXEC);
+  if (fd != -1)
+    {
+      uint8_t *p = rnd;
+      uint8_t *end = p + len;
+      do
+	{
+	  ssize_t ret = TEMP_FAILURE_RETRY (__read_nocancel (fd, p, end - p));
+	  if (ret <= 0)
+	    arc4random_getrandom_failure ();
+	  p += ret;
+	}
+      while (p < end);
+
+      if (__close_nocancel (fd) == 0)
+	return;
+    }
+  arc4random_getrandom_failure ();
+}
+
+/* Either allocates the state buffer or reinit it by reseeding the cipher
+   state with kernel entropy.  */
+static void
+arc4random_stir (void)
+{
+  uint8_t rnd[CHACHA20_KEY_SIZE + CHACHA20_IV_SIZE];
+  arc4random_getentropy (rnd, sizeof rnd);
+
+  if (state == NULL)
+    arc4random_init (rnd);
+  else
+    arc4random_rekey (rnd, sizeof rnd);
+
+  explicit_bzero (rnd, sizeof rnd);
+
+  state->have = 0;
+  memset (state->buf, 0, sizeof state->buf);
+  state->count = CHACHA20_RESEED_SIZE;
+}
+
+static void
+arc4random_check_stir (size_t len)
+{
+  if (state == NULL || state->count < len)
+    arc4random_stir ();
+  if (state->count <= len)
+    state->count = 0;
+  else
+    state->count -= len;
+}
+
+void
+__arc4random_buf_internal (void *buffer, size_t len)
+{
+  arc4random_check_stir (len);
+
+  while (len > 0)
+    {
+      if (state->have > 0)
+	{
+	  size_t m = min (len, state->have);
+	  uint8_t *ks = state->buf + sizeof (state->buf) - state->have;
+	  memcpy (buffer, ks, m);
+	  memset (ks, 0, m);
+	  buffer += m;
+	  len -= m;
+	  state->have -= m;
+	}
+      if (state->have == 0)
+	arc4random_rekey (NULL, 0);
+    }
+}
+
+void
+__arc4random_buf (void *buffer, size_t len)
+{
+  __libc_lock_lock (__arc4random_lock);
+  __arc4random_buf_internal (buffer, len);
+  __libc_lock_unlock (__arc4random_lock);
+}
+libc_hidden_def (__arc4random_buf)
+weak_alias (__arc4random_buf, arc4random_buf)
+
+
+static uint32_t
+__arc4random_internal (void)
+{
+  uint32_t r;
+
+  arc4random_check_stir (sizeof (uint32_t));
+  if (state->have < sizeof (uint32_t))
+    arc4random_rekey (NULL, 0);
+  uint8_t *ks = state->buf + sizeof (state->buf) - state->have;
+  memcpy (&r, ks, sizeof (uint32_t));
+  memset (ks, 0, sizeof (uint32_t));
+  state->have -= sizeof (uint32_t);
+
+  return r;
+}
+
+uint32_t
+__arc4random (void)
+{
+  uint32_t r;
+  __libc_lock_lock (__arc4random_lock);
+  r = __arc4random_internal ();
+  __libc_lock_unlock (__arc4random_lock);
+  return r;
+}
+libc_hidden_def (__arc4random)
+weak_alias (__arc4random, arc4random)
diff --git a/stdlib/arc4random_uniform.c b/stdlib/arc4random_uniform.c
new file mode 100644
index 0000000000..722e92b3a7
--- /dev/null
+++ b/stdlib/arc4random_uniform.c
@@ -0,0 +1,152 @@ 
+/* Random pseudo generator numbers between 0 and 2**-31 (inclusive)
+   uniformly distributed but with an upper_bound.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <endian.h>
+#include <libc-lock.h>
+#include <stdlib.h>
+#include <sys/param.h>
+
+/* Return the number of bytes which cover values up to the limit.  */
+__attribute__ ((const))
+static uint32_t
+byte_count (uint32_t n)
+{
+  if (n < (1U << 8))
+    return 1;
+  else if (n < (1U << 16))
+    return 2;
+  else if (n < (1U << 24))
+    return 3;
+  else
+    return 4;
+}
+
+/* Fill the lower bits of the result with randomness, according to the
+   number of bytes requested.  */
+static void
+random_bytes (uint32_t *result, uint32_t byte_count)
+{
+  *result = 0;
+  unsigned char *ptr = (unsigned char *) result;
+  if (__BYTE_ORDER == __BIG_ENDIAN)
+    ptr += 4 - byte_count;
+  __arc4random_buf_internal (ptr, byte_count);
+}
+
+static uint32_t
+compute_uniform (uint32_t n)
+{
+  if (n <= 1)
+    /* There is no valid return value for a zero limit, and 0 is the
+       only possible result for limit 1.  */
+    return 0;
+
+  /* The bits variable serves as a source for bits.  Prefetch the
+     minimum number of bytes needed.  */
+  uint32_t count = byte_count (n);
+  uint32_t bits_length = count * CHAR_BIT;
+  uint32_t bits;
+  random_bytes (&bits, count);
+
+  /* Powers of two are easy.  */
+  if (powerof2 (n))
+    return bits & (n - 1);
+
+  /* The general case.  This algorithm follows Jérémie Lumbroso,
+     Optimal Discrete Uniform Generation from Coin Flips, and
+     Applications (2013), who credits Donald E. Knuth and Andrew
+     C. Yao, The complexity of nonuniform random number generation
+     (1976), for solving the general case.
+
+     The implementation below unrolls the initialization stage of the
+     loop, where v is less than n.  */
+
+  /* Use 64-bit variables even though the intermediate results are
+     never larger than 33 bits.  This ensures the code is easier to
+     compile on 64-bit architectures.  */
+  uint64_t v;
+  uint64_t c;
+
+  /* Initialize v and c.  v is the smallest power of 2 which is larger
+     than n.*/
+  {
+    uint32_t log2p1 = 32 - __builtin_clz (n);
+    v = 1ULL << log2p1;
+    c = bits & (v - 1);
+    bits >>= log2p1;
+    bits_length -= log2p1;
+  }
+
+  /* At the start of the loop, c is uniformly distributed within the
+     half-open interval [0, v), and v < 2n < 2**33.  */
+  while (true)
+    {
+      if (v >= n)
+        {
+          /* If the candidate is less than n, accept it.  */
+          if (c < n)
+            /* c is uniformly distributed on [0, n).  */
+            return c;
+          else
+            {
+              /* c is uniformly distributed on [n, v).  */
+              v -= n;
+              c -= n;
+              /* The distribution was shifted, so c is uniformly
+                 distributed on [0, v) again.  */
+            }
+        }
+      /* v < n here.  */
+
+      /* Replenish the bit source if necessary.  */
+      if (bits_length == 0)
+        {
+          /* Overwrite the least significant byte.  */
+	  random_bytes (&bits, 1);
+	  bits_length = CHAR_BIT;
+        }
+
+      /* Double the range.  No overflow because v < n < 2**32.  */
+      v *= 2;
+      /* v < 2n here.  */
+
+      /* Extract a bit and append it to c.  c remains less than v and
+         thus 2**33.  */
+      c = (c << 1) | (bits & 1);
+      bits >>= 1;
+      --bits_length;
+
+      /* At this point, c is uniformly distributed on [0, v) again,
+         and v < 2n < 2**33.  */
+    }
+}
+
+__libc_lock_define (extern , __arc4random_lock attribute_hidden)
+
+uint32_t
+__arc4random_uniform (uint32_t upper_bound)
+{
+  uint32_t r;
+  __libc_lock_lock (__arc4random_lock);
+  r = compute_uniform (upper_bound);
+  __libc_lock_unlock (__arc4random_lock);
+  return r;
+}
+libc_hidden_def (__arc4random_uniform)
+weak_alias (__arc4random_uniform, arc4random_uniform)
diff --git a/stdlib/chacha20.c b/stdlib/chacha20.c
new file mode 100644
index 0000000000..28630121f9
--- /dev/null
+++ b/stdlib/chacha20.c
@@ -0,0 +1,188 @@ 
+/* Generic ChaCha20 implementation (used on arc4random).
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <array_length.h>
+#include <endian.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+/* 32-bit stream position, then 96-bit nonce.  */
+#define CHACHA20_IV_SIZE	16
+#define CHACHA20_KEY_SIZE	32
+
+#define CHACHA20_BLOCK_SIZE     64
+#define CHACHA20_STATE_LEN	16
+
+/* The ChaCha20 implementation is based on RFC8439 [1], omitting the final
+   XOR of the keystream with the plaintext because the plaintext is a
+   stream of zeros.  */
+
+enum chacha20_constants
+{
+  CHACHA20_CONSTANT_EXPA = 0x61707865U,
+  CHACHA20_CONSTANT_ND_3 = 0x3320646eU,
+  CHACHA20_CONSTANT_2_BY = 0x79622d32U,
+  CHACHA20_CONSTANT_TE_K = 0x6b206574U
+};
+
+static inline uint32_t
+read_unaligned_32 (const uint8_t *p)
+{
+  uint32_t r;
+  memcpy (&r, p, sizeof (r));
+  return r;
+}
+
+static inline void
+write_unaligned_32 (uint8_t *p, uint32_t v)
+{
+  memcpy (p, &v, sizeof (v));
+}
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define read_unaligned_le32(p) __builtin_bswap32 (read_unaligned_32 (p))
+# define set_state(v)		__builtin_bswap32 ((v))
+#else
+# define read_unaligned_le32(p) read_unaligned_32 ((p))
+# define set_state(v)		(v)
+#endif
+
+static inline void
+chacha20_init (uint32_t *state, const uint8_t *key, const uint8_t *iv)
+{
+  state[0]  = CHACHA20_CONSTANT_EXPA;
+  state[1]  = CHACHA20_CONSTANT_ND_3;
+  state[2]  = CHACHA20_CONSTANT_2_BY;
+  state[3]  = CHACHA20_CONSTANT_TE_K;
+
+  state[4]  = read_unaligned_le32 (key + 0 * sizeof (uint32_t));
+  state[5]  = read_unaligned_le32 (key + 1 * sizeof (uint32_t));
+  state[6]  = read_unaligned_le32 (key + 2 * sizeof (uint32_t));
+  state[7]  = read_unaligned_le32 (key + 3 * sizeof (uint32_t));
+  state[8]  = read_unaligned_le32 (key + 4 * sizeof (uint32_t));
+  state[9]  = read_unaligned_le32 (key + 5 * sizeof (uint32_t));
+  state[10] = read_unaligned_le32 (key + 6 * sizeof (uint32_t));
+  state[11] = read_unaligned_le32 (key + 7 * sizeof (uint32_t));
+
+  state[12] = read_unaligned_le32 (iv + 0 * sizeof (uint32_t));
+  state[13] = read_unaligned_le32 (iv + 1 * sizeof (uint32_t));
+  state[14] = read_unaligned_le32 (iv + 2 * sizeof (uint32_t));
+  state[15] = read_unaligned_le32 (iv + 3 * sizeof (uint32_t));
+}
+
+static inline uint32_t
+rotl32 (unsigned int shift, uint32_t word)
+{
+  return (word << (shift & 31)) | (word >> ((-shift) & 31));
+}
+
+static void
+state_final (const uint8_t *src, uint8_t *dst, uint32_t v)
+{
+#ifdef CHACHA20_XOR_FINAL
+  v ^= read_unaligned_32 (src);
+#endif
+  write_unaligned_32 (dst, v);
+}
+
+static inline void
+chacha20_block (uint32_t *state, uint8_t *dst, const uint8_t *src)
+{
+  uint32_t x0, x1, x2, x3, x4, x5, x6, x7;
+  uint32_t x8, x9, x10, x11, x12, x13, x14, x15;
+
+  x0 = state[0];
+  x1 = state[1];
+  x2 = state[2];
+  x3 = state[3];
+  x4 = state[4];
+  x5 = state[5];
+  x6 = state[6];
+  x7 = state[7];
+  x8 = state[8];
+  x9 = state[9];
+  x10 = state[10];
+  x11 = state[11];
+  x12 = state[12];
+  x13 = state[13];
+  x14 = state[14];
+  x15 = state[15];
+
+  for (int i = 0; i < 20; i += 2)
+    {
+#define QROUND(_x0, _x1, _x2, _x3) 			\
+  do {							\
+   _x0 = _x0 + _x1; _x3 = rotl32 (16, (_x0 ^ _x3)); 	\
+   _x2 = _x2 + _x3; _x1 = rotl32 (12, (_x1 ^ _x2)); 	\
+   _x0 = _x0 + _x1; _x3 = rotl32 (8,  (_x0 ^ _x3));	\
+   _x2 = _x2 + _x3; _x1 = rotl32 (7,  (_x1 ^ _x2));	\
+  } while(0)
+
+      QROUND (x0, x4, x8,  x12);
+      QROUND (x1, x5, x9,  x13);
+      QROUND (x2, x6, x10, x14);
+      QROUND (x3, x7, x11, x15);
+
+      QROUND (x0, x5, x10, x15);
+      QROUND (x1, x6, x11, x12);
+      QROUND (x2, x7, x8,  x13);
+      QROUND (x3, x4, x9,  x14);
+    }
+
+  state_final (&src[0], &dst[0], set_state (x0 + state[0]));
+  state_final (&src[4], &dst[4], set_state (x1 + state[1]));
+  state_final (&src[8], &dst[8], set_state (x2 + state[2]));
+  state_final (&src[12], &dst[12], set_state (x3 + state[3]));
+  state_final (&src[16], &dst[16], set_state (x4 + state[4]));
+  state_final (&src[20], &dst[20], set_state (x5 + state[5]));
+  state_final (&src[24], &dst[24], set_state (x6 + state[6]));
+  state_final (&src[28], &dst[28], set_state (x7 + state[7]));
+  state_final (&src[32], &dst[32], set_state (x8 + state[8]));
+  state_final (&src[36], &dst[36], set_state (x9 + state[9]));
+  state_final (&src[40], &dst[40], set_state (x10 + state[10]));
+  state_final (&src[44], &dst[44], set_state (x11 + state[11]));
+  state_final (&src[48], &dst[48], set_state (x12 + state[12]));
+  state_final (&src[52], &dst[52], set_state (x13 + state[13]));
+  state_final (&src[56], &dst[56], set_state (x14 + state[14]));
+  state_final (&src[60], &dst[60], set_state (x15 + state[15]));
+
+  state[12]++;
+}
+
+static void
+chacha20_crypt (uint32_t *state, uint8_t *dst, const uint8_t *src,
+		size_t bytes)
+{
+  while (bytes >= CHACHA20_BLOCK_SIZE)
+    {
+      chacha20_block (state, dst, src);
+
+      bytes -= CHACHA20_BLOCK_SIZE;
+      dst += CHACHA20_BLOCK_SIZE;
+      src += CHACHA20_BLOCK_SIZE;
+    }
+
+  if (__glibc_unlikely (bytes != 0))
+    {
+      uint8_t stream[CHACHA20_BLOCK_SIZE];
+      chacha20_block (state, stream, src);
+      memcpy (dst, stream, bytes);
+      explicit_bzero (stream, sizeof stream);
+    }
+}
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index bf7cd438e1..f02a713a7b 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -485,6 +485,7 @@  extern unsigned short int *seed48 (unsigned short int __seed16v[3])
 extern void lcong48 (unsigned short int __param[7]) __THROW __nonnull ((1));
 
 # ifdef __USE_MISC
+#  include <bits/stdint-uintn.h>
 /* Data structure for communication with thread safe versions.  This
    type is to be regarded as opaque.  It's only exported because users
    have to allocate objects of this type.  */
@@ -533,6 +534,19 @@  extern int seed48_r (unsigned short int __seed16v[3],
 extern int lcong48_r (unsigned short int __param[7],
 		      struct drand48_data *__buffer)
      __THROW __nonnull ((1, 2));
+
+/* Return a random integer between zero and 2**32-1 (inclusive).  */
+extern uint32_t arc4random (void)
+     __THROW __wur;
+
+/* Fill the buffer with random data.  */
+extern void arc4random_buf (void *__buf, size_t __size)
+     __THROW __nonnull ((1));
+
+/* Return a random number between zero (inclusive) and the specified
+   limit (exclusive).  */
+extern uint32_t arc4random_uniform (uint32_t __upper_bound)
+     __THROW __wur;
 # endif	/* Use misc.  */
 #endif	/* Use misc or X/Open.  */
 
diff --git a/sysdeps/generic/not-cancel.h b/sysdeps/generic/not-cancel.h
index 2104efeb54..acceb9b67f 100644
--- a/sysdeps/generic/not-cancel.h
+++ b/sysdeps/generic/not-cancel.h
@@ -48,5 +48,7 @@ 
   (void) __writev (fd, iov, n)
 #define __fcntl64_nocancel(fd, cmd, ...) \
   __fcntl64 (fd, cmd, __VA_ARGS__)
+#define __getrandom_nocancel(buf, size, flags) \
+  __getrandom (buf, size, flags)
 
 #endif /* NOT_CANCEL_H  */
diff --git a/sysdeps/mach/hurd/_Fork.c b/sysdeps/mach/hurd/_Fork.c
index e60b86fab1..1c44b39c5b 100644
--- a/sysdeps/mach/hurd/_Fork.c
+++ b/sysdeps/mach/hurd/_Fork.c
@@ -665,6 +665,8 @@  retry:
       /* Run things that want to run in the child task to set up.  */
       RUN_HOOK (_hurd_fork_child_hook, ());
 
+      call_function_static_weak (__arc4random_fork_subprocess);
+
       /* Set up proc server-assisted fault recovery for the signal thread.  */
       _hurdsig_fault_init ();
 
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index 4dc87e9061..87322091d5 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -609,7 +609,7 @@  GLIBC_2.2.6 _libc_intl_domainname D 0x5
 GLIBC_2.2.6 _longjmp F
 GLIBC_2.2.6 _mcleanup F
 GLIBC_2.2.6 _mcount F
-GLIBC_2.2.6 _nl_default_dirname D 0xe
+GLIBC_2.2.6 _nl_default_dirname D 0x12
 GLIBC_2.2.6 _nl_domain_bindings D 0x4
 GLIBC_2.2.6 _nl_msg_cat_cntr D 0x4
 GLIBC_2.2.6 _null_auth D 0xc
@@ -2289,6 +2289,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 close_range F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/mach/hurd/not-cancel.h b/sysdeps/mach/hurd/not-cancel.h
index 6ec92ced84..9a3a7ed59a 100644
--- a/sysdeps/mach/hurd/not-cancel.h
+++ b/sysdeps/mach/hurd/not-cancel.h
@@ -74,6 +74,9 @@  __typeof (__fcntl) __fcntl_nocancel;
 #define __fcntl64_nocancel(...) \
   __fcntl_nocancel (__VA_ARGS__)
 
+#define __getrandom_nocancel(buf, size, flags) \
+  __getrandom (buf, size, flags)
+
 #if IS_IN (libc)
 hidden_proto (__close_nocancel)
 hidden_proto (__close_nocancel_nostatus)
diff --git a/sysdeps/nptl/_Fork.c b/sysdeps/nptl/_Fork.c
index dd568992e2..7dc02569f6 100644
--- a/sysdeps/nptl/_Fork.c
+++ b/sysdeps/nptl/_Fork.c
@@ -43,6 +43,8 @@  _Fork (void)
       self->robust_head.list = &self->robust_head;
       INTERNAL_SYSCALL_CALL (set_robust_list, &self->robust_head,
 			     sizeof (struct robust_list_head));
+
+      call_function_static_weak (__arc4random_fork_subprocess);
     }
   return pid;
 }
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 7602129631..51b70a677e 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2616,6 +2616,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 5b39d6023c..48e6eae64e 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2713,6 +2713,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
index e413302f2e..4ae092fcc3 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -2377,6 +2377,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index ade1b93d13..5aec8ab0c0 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -496,6 +496,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index 10e91537fa..131b7a4858 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -493,6 +493,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index 22618c7aaa..be50ff1063 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2652,6 +2652,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index e2aea90c74..92a283fb6e 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2601,6 +2601,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 29ecca26bb..90b9085d26 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2785,6 +2785,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 69a2ca2391..deec02a605 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2551,6 +2551,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 23cc4ddd8a..8ac2b8c477 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -497,6 +497,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 2d1d8a3d0c..c06b7f9d92 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2728,6 +2728,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index 7b6e88bdb9..41d2ccf3c3 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2701,6 +2701,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index 155c974790..84d041363b 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -2698,6 +2698,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 7a811120ea..374e356b5a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2693,6 +2693,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 7d28dca5c1..ae3a41f90e 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2691,6 +2691,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 41790f0d63..ef99267544 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2699,6 +2699,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 9c15006c12..6d02c6f889 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2602,6 +2602,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 27c0498b60..b2a35ab5aa 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2740,6 +2740,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/linux/not-cancel.h
index 75b9e0ee1e..2c58d5ae2f 100644
--- a/sysdeps/unix/sysv/linux/not-cancel.h
+++ b/sysdeps/unix/sysv/linux/not-cancel.h
@@ -67,6 +67,13 @@  __writev_nocancel_nostatus (int fd, const struct iovec *iov, int iovcnt)
   INTERNAL_SYSCALL_CALL (writev, fd, iov, iovcnt);
 }
 
+static inline int
+__getrandom_nocancel (void *buf, size_t buflen, unsigned int flags)
+{
+  return INTERNAL_SYSCALL_CALL (getrandom, buf, buflen, flags);
+}
+
+
 /* Uncancelable fcntl.  */
 __typeof (__fcntl) __fcntl64_nocancel;
 
diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
index e500d4756f..204176b2f2 100644
--- a/sysdeps/unix/sysv/linux/or1k/libc.abilist
+++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist
@@ -2123,6 +2123,9 @@  GLIBC_2.35 wprintf F
 GLIBC_2.35 write F
 GLIBC_2.35 writev F
 GLIBC_2.35 wscanf F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index adb21db204..ee0080b12c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2755,6 +2755,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 28a08c4afb..8201b58146 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2788,6 +2788,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index 98c5f3e61c..c5ad19d8ad 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2510,6 +2510,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index 31e5aa90cd..301fca4e00 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2812,6 +2812,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
index 87d90bf668..c8ee335503 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
@@ -2379,6 +2379,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index b4a8f56aa2..32094c9162 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2579,6 +2579,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index e4a58cc145..b07cb128e6 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2753,6 +2753,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index ef0f0c3fa1..5c10d3d588 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2547,6 +2547,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
index 603d50668f..36f683de0b 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -2608,6 +2608,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index 078cdf05a7..3a730e5b96 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2605,6 +2605,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 735505ac51..1595282003 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2748,6 +2748,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 48df7952cd..86ef3e3aee 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2574,6 +2574,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 1629fb7762..f604657c34 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2525,6 +2525,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index ee9674ff75..51715e9c16 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2631,6 +2631,9 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 arc4random F
+GLIBC_2.36 arc4random_buf F
+GLIBC_2.36 arc4random_uniform F
 GLIBC_2.36 pidfd_getfd F
 GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F