From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-oo1-xc29.google.com (mail-oo1-xc29.google.com [IPv6:2607:f8b0:4864:20::c29]) by sourceware.org (Postfix) with ESMTPS id 1A2853858D33 for ; Mon, 25 Apr 2022 02:22:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1A2853858D33 Received: by mail-oo1-xc29.google.com with SMTP id y3-20020a4ab403000000b0035e74942d42so14127oon.13 for ; Sun, 24 Apr 2022 19:22:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=60x/ffWYKcXVLDK4XCmzJWX6Ha4AT+wS/YrH/ypIvQY=; b=AnNnRxd0Vh5WJRrePO9C/z+0xvK5UDl4+leEvuepXRqAA/WME6iWrJo3HWztQfIbRi DSzqiCN8LfQPfgz+CvwEZZOoKBSxXR/SAvQZ+zvKp1LBBzyiucfPbNPo9T0WEVSE5Df5 ZoNelWqVrSx9tEPcWrJS47eNnBGqiIR22XbtYCrDjJZIAmkRkJA1JSpTMQ69Npdc1bwp rWQv13bySrdAw1jXhjWneFxmKmuY5xkqm2oD1nmpIyv1p9thefUh+NTpssD2O5JeOcLu FcyGirioQS7jP+lQ2EkW/CAVCp8AuzxRb6WzlBMSu/m4Yr5cxKePOLn6+Rk7q6azDQ5f q4eg== X-Gm-Message-State: AOAM532nnwkJ3tgIZaU8tRjurGwyc526Zjft6yc28S4mNrgrowJWSz+H rNSDJ8yOlYWEqNYL86HP6scBT8zj6VVDp0ySFnc= X-Google-Smtp-Source: ABdhPJzGTlVbJ0wq3BoirzSbbL1DOicRpmwtnPkWnEdeAYzlByzwzyMlUP3pOCwtRWEReZu4O/n4HDhn4B3TIKe/+C0= X-Received: by 2002:a4a:e4c7:0:b0:329:afad:cb2d with SMTP id w7-20020a4ae4c7000000b00329afadcb2dmr5544379oov.77.1650853339870; Sun, 24 Apr 2022 19:22:19 -0700 (PDT) MIME-Version: 1.0 References: <20220419212812.2688764-1-adhemerval.zanella@linaro.org> <20220419212812.2688764-2-adhemerval.zanella@linaro.org> In-Reply-To: <20220419212812.2688764-2-adhemerval.zanella@linaro.org> From: Mark Harris Date: Sun, 24 Apr 2022 19:22:09 -0700 Message-ID: Subject: Re: [PATCH v3 1/9] stdlib: Add arc4random, arc4random_buf, and arc4random_uniform (BZ #4417) To: Adhemerval Zanella Cc: libc-alpha@sourceware.org, Florian Weimer Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-8.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 25 Apr 2022 02:22:26 -0000 On Tue, Apr 19, 2022 at 2:29 PM Adhemerval Zanella via Libc-alpha wrote: > > 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 amortize arc4random calls (where both s/amortize/amortizing/ > function call and locks cost are the dominating factor). s/locks/lock/ > > The ChaCha20 implementation is based on the RFC8439 [1], with last > step that XOR with the input omited. Since the input stream will either > zero bytes (initial state) or the PRNG output itself this step does not > add any extra entropy. The src argument to chacha20_crypt is always zeros, never PRNG output. Perhaps it would be clearer to say something like this: 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. > > The arc4random_uniform is based on previous work by Florian Weimer. > > Checked on x86_64-linux-gnu, aarch64-linux, and powerpc64le-linux-gnu. > > Co-authored-by: Florian Weimer > > [1] https://datatracker.ietf.org/doc/html/rfc8439 > --- > NEWS | 4 +- > include/stdlib.h | 13 + > posix/fork.c | 2 + > stdlib/Makefile | 2 + > stdlib/Versions | 5 + > stdlib/arc4random.c | 245 ++++++++++++++++++ > stdlib/arc4random_uniform.c | 152 +++++++++++ > stdlib/chacha20.c | 163 ++++++++++++ > stdlib/stdlib.h | 14 + > sysdeps/generic/not-cancel.h | 2 + > sysdeps/mach/hurd/i386/libc.abilist | 3 + > sysdeps/mach/hurd/not-cancel.h | 3 + > 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 + > 46 files changed, 713 insertions(+), 1 deletion(-) > create mode 100644 stdlib/arc4random.c > create mode 100644 stdlib/arc4random_uniform.c > create mode 100644 stdlib/chacha20.c > > diff --git a/NEWS b/NEWS > index 4b6d9de2b5..4d9d95b35b 100644 > --- a/NEWS > +++ b/NEWS > @@ -9,7 +9,9 @@ Version 2.36 > > Major new features: > > - [Add new features here] > +* The functions arc4random, arc4random_buf, arc4random_uniform have been > + added. The functions use a cryptographic pseudo-random number generat= or > + based on ChaCha20 initilized with entropy from kernel. > > Deprecated and removed features, and other changes affecting compatibili= ty: > > diff --git a/include/stdlib.h b/include/stdlib.h > index 1c6f70b082..055f9d2965 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 th= te s/thte/the/ > + child process. This avoids deadlocks if fork is called in multi-thre= aded > + 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/posix/fork.c b/posix/fork.c > index 6b50c091f9..87d8329b46 100644 > --- a/posix/fork.c > +++ b/posix/fork.c > @@ -96,6 +96,8 @@ __libc_fork (void) > &nss_database_data); > } > > + call_function_static_weak (__arc4random_fork_subprocess); > + > /* Reset the lock the dynamic loader uses to protect its data. */ > __rtld_lock_initialize (GL(dl_load_lock)); > > diff --git a/stdlib/Makefile b/stdlib/Makefile > index 60fc59c12c..9f9cc1bd7f 100644 > --- a/stdlib/Makefile > +++ b/stdlib/Makefile > @@ -53,6 +53,8 @@ routines :=3D \ > 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..cddb0e405a > --- /dev/null > +++ b/stdlib/arc4random.c > @@ -0,0 +1,245 @@ > +/* 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 > + . */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* Besides the cipher state 'ctx', it keeps two counters: 'have' is the > + current valid bytes not yet consumed in 'buf', while 'count' is the m= aximum > + number of bytes until a reseed. > + > + Both the initial seed an reseed tries to obtain entropy from the kern= el > + and abort the process if none could be obtained. > + > + The state 'buf' improves the usage of the cipher call, allowing to ca= ll > + optimized implementations (if the archictecture provides it) and opti= mize > + arc4random calls (since only multiple call it will encrypt the next b= lock). > + */ > + > +/* Maximum number bytes until reseed (16 MB). */ > +#define CHACHE_RESEED_SIZE (16 * 1024 * 1024) Should this be CHACHA20_RESEED_SIZE? > +/* Internal buffer size in bytes (1KB). */ > +#define CHACHA20_BUFSIZE (8 * CHACHA20_BLOCK_SIZE) 8 * 64 =3D 512; should this be (16 * CHACHA20_BLOCK_SIZE)? > + > +#include > + > +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 =3D false; > + > +__libc_lock_define_initialized (, __arc4random_lock); > + > +/* Called from the fork function to reset the state if MADV_WIPEONFORK i= s > + not supported and to reinit the internal lock. */ > +void > +__arc4random_fork_subprocess (void) > +{ > + if (__arc4random_wipeonfork && state !=3D 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 arc4rando= m\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, size_t len) len is not used in this function. > +{ > + state =3D __mmap (NULL, sizeof (struct arc4random_state), > + PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1= , 0); > + if (state =3D=3D MAP_FAILED) > + arc4random_allocate_failure (); > + > +#ifdef MADV_WIPEONFORK > + int r =3D __madvise (state, sizeof (struct arc4random_state), MADV_WIP= EONFORK); > + if (r =3D=3D 0) > + __arc4random_wipeonfork =3D true; > + else if (errno !=3D 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) > +{ > + memset (state->buf, 0, sizeof state->buf); > + chacha20_crypt (state->ctx, state->buf, state->buf, sizeof state->buf)= ; > + > + /* Mix some extra entropy if provided. */ > + if (rnd !=3D NULL) > + { > + size_t m =3D min (rndlen, CHACHA20_KEY_SIZE + CHACHA20_IV_SIZE); > + for (size_t i =3D 0; i < m; i++) > + state->buf[i] ^=3D 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 =3D sizeof (state->buf) - (CHACHA20_KEY_SIZE + CHACHA20_IV= _SIZE); > +} > + > +static void > +arc4random_getentropy (uint8_t *rnd, size_t len) > +{ > + if (__getrandomn_nocancel (rnd, len, GRND_NONBLOCK) =3D=3D len) > + return; > + > + int fd =3D __open64_nocancel ("/dev/urandom", O_RDONLY); Should this be O_RDONLY | O_CLOEXEC? > + if (fd !=3D -1) > + { > + unsigned char *p =3D rnd; > + unsigned char *end =3D p + len; uint8_t * would be consistent with the declaration of md. > + do > + { > + ssize_t ret =3D TEMP_FAILURE_RETRY (__read_nocancel (fd, p, end= - p)); > + if (ret <=3D 0) > + arc4random_getrandom_failure (); > + p +=3D ret; > + } > + while (p < end); > + > + if (__close_nocancel (fd) !=3D 0) Should this be =3D=3D 0? > + return; > + } > + arc4random_getrandom_failure (); > +} > + > +/* Either allocates the state buffer or reinit it by reseeding the ciphe= r > + 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 =3D=3D NULL) > + arc4random_init (rnd, sizeof rnd); > + else > + arc4random_rekey (rnd, sizeof rnd); > + > + explicit_bzero (rnd, sizeof rnd); > + > + state->have =3D 0; > + memset (state->buf, 0, sizeof state->buf); > + state->count =3D CHACHE_RESEED_SIZE; > +} > + > +static void > +arc4random_check_stir (size_t len) > +{ > + if (state =3D=3D NULL || state->count < len) > + arc4random_stir (); > + if (state->count <=3D len) > + state->count =3D 0; > + else > + state->count -=3D len; > +} > + > +void > +__arc4random_buf_internal (void *buffer, size_t len) > +{ > + arc4random_check_stir (len); > + > + while (len > 0) > + { > + if (state->have > 0) > + { > + size_t m =3D min (len, state->have); > + uint8_t *ks =3D state->buf + sizeof (state->buf) - state->have; > + memcpy (buffer, ks, m); > + memset (ks, 0, m); > + buffer +=3D m; > + len -=3D m; > + state->have -=3D m; > + } > + if (state->have =3D=3D 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 =3D state->buf + sizeof (state->buf) - state->have; > + memcpy (&r, ks, sizeof (uint32_t)); > + memset (ks, 0, sizeof (uint32_t)); > + state->have -=3D sizeof (uint32_t); > + > + return r; > +} > + > +uint32_t > +__arc4random (void) > +{ > + uint32_t r; > + __libc_lock_lock (__arc4random_lock); > + r =3D __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..96ffe62df1 > --- /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 > + . */ > + > +#include > +#include > +#include > +#include > + > +/* Return the number of bytes which cover values up to the limit. */ > +__attribute__ ((const)) > +static uint32_t > +byte_count (uint32_t n) > +{ > + if (n <=3D (1U << 8)) > + return 1; > + else if (n <=3D (1U << 16)) > + return 2; > + else if (n <=3D (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 =3D 0; > + unsigned char *ptr =3D (unsigned char *) result; > + if (__BYTE_ORDER =3D=3D __BIG_ENDIAN) > + ptr +=3D 4 - byte_count; > + __arc4random_buf_internal (ptr, byte_count); > +} > + > +static uint32_t > +compute_uniform (uint32_t n) > +{ > + if (n <=3D 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. */ > + unsigned count =3D byte_count (n); uint32_t would be consistent with the declaration of byte_count. > + uint32_t bits_length =3D 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=C3=A9r=C3=A9mie Lumbros= o, > + 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 that 33 bits. This ensures the code easier to s/that/than/ s/the code/that the code is/ > + 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 =3D 32 - __builtin_clz (n); > + v =3D 1ULL << log2p1; > + c =3D bits & (v - 1); > + bits >>=3D log2p1; > + bits_length -=3D 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 >=3D 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 -=3D n; > + c -=3D 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 =3D=3D 0) > + { > + /* Overwrite the least significant byte. */ > + random_bytes (&bits, 1); > + bits_length =3D CHAR_BIT; > + } > + > + /* Double the range. No overflow because v < n < 2**32. */ > + v *=3D 2; > + /* v < 2n here. */ > + > + /* Extract a bit and append it to c. c remains less than v and > + thus 2**33. */ > + c =3D (c << 1) | (bits & 1); > + bits >>=3D 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 =3D 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..af4ffa9860 > --- /dev/null > +++ b/stdlib/chacha20.c > @@ -0,0 +1,163 @@ > +/* 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 > + . */ > + > +#include > +#include > +#include > +#include > +#include > + > +/* 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_BLOCK_WORDS (CHACHA20_BLOCK_SIZE / sizeof (uint32_t)= ) > + > +#define CHACHA20_STATE_LEN 16 > + > +/* Defining CHACHA20_XOR_FINAL issues the final XOR using the input as d= efined > + Sby RFC8439. Since the input stream will either zero bytes (initial = state) s/Sby/by/ > + or the PRNG output itself this step does not add any extra entropy. = */ The plaintext input stream (src argument to chacha20_crypt) is always zeros, never PRNG output. > + > +enum chacha20_constants > +{ > + CHACHA20_CONSTANT_EXPA =3D 0x61707865U, > + CHACHA20_CONSTANT_ND_3 =3D 0x3320646eU, > + CHACHA20_CONSTANT_2_BY =3D 0x79622d32U, > + CHACHA20_CONSTANT_TE_K =3D 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 =3D=3D __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] =3D CHACHA20_CONSTANT_EXPA; > + state[1] =3D CHACHA20_CONSTANT_ND_3; > + state[2] =3D CHACHA20_CONSTANT_2_BY; > + state[3] =3D CHACHA20_CONSTANT_TE_K; > + > + state[4] =3D read_unaligned_le32 (key + 0 * sizeof (uint32_t)); > + state[5] =3D read_unaligned_le32 (key + 1 * sizeof (uint32_t)); > + state[6] =3D read_unaligned_le32 (key + 2 * sizeof (uint32_t)); > + state[7] =3D read_unaligned_le32 (key + 3 * sizeof (uint32_t)); > + state[8] =3D read_unaligned_le32 (key + 4 * sizeof (uint32_t)); > + state[9] =3D read_unaligned_le32 (key + 5 * sizeof (uint32_t)); > + state[10] =3D read_unaligned_le32 (key + 6 * sizeof (uint32_t)); > + state[11] =3D read_unaligned_le32 (key + 7 * sizeof (uint32_t)); > + > + state[12] =3D read_unaligned_le32 (iv + 0 * sizeof (uint32_t)); > + state[13] =3D read_unaligned_le32 (iv + 1 * sizeof (uint32_t)); > + state[14] =3D read_unaligned_le32 (iv + 2 * sizeof (uint32_t)); > + state[15] =3D 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)); > +} > + > +#define QROUND(x0, x1, x2, x3) \ > + do { \ > + x0 =3D x0 + x1; x3 =3D rotl32 (16, (x0 ^ x3)); \ > + x2 =3D x2 + x3; x1 =3D rotl32 (12, (x1 ^ x2)); \ > + x0 =3D x0 + x1; x3 =3D rotl32 (8, (x0 ^ x3)); \ > + x2 =3D x2 + x3; x1 =3D rotl32 (7, (x1 ^ x2)); \ > + } while(0) > + > +static inline void > +chacha20_block (uint32_t *state, uint32_t *stream) > +{ > + uint32_t x[CHACHA20_STATE_LEN]; > + memcpy (x, state, sizeof x); > + > + for (int i =3D 0; i < 20; i +=3D 2) > + { > + QROUND (x[0], x[4], x[8], x[12]); > + QROUND (x[1], x[5], x[9], x[13]); > + QROUND (x[2], x[6], x[10], x[14]); > + QROUND (x[3], x[7], x[11], x[15]); > + > + QROUND (x[0], x[5], x[10], x[15]); > + QROUND (x[1], x[6], x[11], x[12]); > + QROUND (x[2], x[7], x[8], x[13]); > + QROUND (x[3], x[4], x[9], x[14]); > + } > + > + /* Unroll the loop a bit. */ > + for (int i =3D 0; i < CHACHA20_BLOCK_WORDS / 4; i++) > + { > + stream[i*4+0] =3D set_state (x[i*4+0] + state[i*4+0]); > + stream[i*4+1] =3D set_state (x[i*4+1] + state[i*4+1]); > + stream[i*4+2] =3D set_state (x[i*4+2] + state[i*4+2]); > + stream[i*4+3] =3D set_state (x[i*4+3] + state[i*4+3]); > + } > + > + state[12]++; > +} > + > +static void > +chacha20_crypt (uint32_t *state, uint8_t *dst, const uint8_t *src, > + size_t bytes) > +{ > + uint32_t stream[CHACHA20_BLOCK_WORDS]; > + > + while (bytes >=3D CHACHA20_BLOCK_SIZE) > + { > + chacha20_block (state, stream); > +#ifdef CHACHA20_XOR_FINAL > + for (int i =3D 0; i < CHACHA20_BLOCK_WORDS; i++) > + stream[i] ^=3D read_unaligned_32 (&src[i * sizeof (uint32_t)]); > +#endif > + memcpy (dst, stream, CHACHA20_BLOCK_SIZE); > + bytes -=3D CHACHA20_BLOCK_SIZE; > + dst +=3D CHACHA20_BLOCK_SIZE; > + src +=3D CHACHA20_BLOCK_SIZE; > + } > + if (bytes !=3D 0) > + { > + chacha20_block (state, stream); > +#ifdef CHACHA20_XOR_FINAL > + for (int i =3D 0; i < CHACHA20_BLOCK_WORDS; i++) > + stream[i] ^=3D read_unaligned_32 (&src[i * sizeof (uint32_t)]); > +#endif > + memcpy (dst, stream, bytes); > + } > +} > diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h > index bf7cd438e1..f2b0c83c12 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 > /* 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**31-1 (inclusive). */ 2**32-1 > +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..f4882a9ffd 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 __getrandomn_nocancel(buf, size, flags) \ > + __getrandom (buf, size, flags) > > #endif /* NOT_CANCEL_H */ > diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386= /libc.abilist > index 4dc87e9061..7bd565103b 100644 > --- a/sysdeps/mach/hurd/i386/libc.abilist > +++ b/sysdeps/mach/hurd/i386/libc.abilist > @@ -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-cance= l.h > index 6ec92ced84..39edfe76b6 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 __getrandomn_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/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/= sysv/linux/aarch64/libc.abilist > index 1b63d9e447..f8f38bb205 100644 > --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist > @@ -2616,3 +2616,6 @@ 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 > diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sy= sv/linux/alpha/libc.abilist > index e7e4cf7d2a..9de1726de0 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.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv= /linux/arc/libc.abilist > index bc3d228e31..16e2532838 100644 > --- a/sysdeps/unix/sysv/linux/arc/libc.abilist > +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist > @@ -2377,3 +2377,6 @@ 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 > diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/s= ysv/linux/arm/be/libc.abilist > index db7039c4ab..ae9e465088 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.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0xa0 > GLIBC_2.4 _IO_2_1_stdin_ D 0xa0 > diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/s= ysv/linux/arm/le/libc.abilist > index d2add4fb49..b669f43194 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.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0xa0 > GLIBC_2.4 _IO_2_1_stdin_ D 0xa0 > diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sys= v/linux/csky/libc.abilist > index 355d72a30c..42daa90248 100644 > --- a/sysdeps/unix/sysv/linux/csky/libc.abilist > +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist > @@ -2652,3 +2652,6 @@ 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 > diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sys= v/linux/hppa/libc.abilist > index 3df39bb28c..090be20f53 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sys= v/linux/i386/libc.abilist > index c4da358f80..6b7cf064bb 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sys= v/linux/ia64/libc.abilist > index 241bac70ea..3e766f64dd 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps= /unix/sysv/linux/m68k/coldfire/libc.abilist > index 78bf372b72..c0b99199a8 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.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0x98 > GLIBC_2.4 _IO_2_1_stdin_ D 0x98 > diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/u= nix/sysv/linux/m68k/m680x0/libc.abilist > index 00df5c901f..4d0be7c86d 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps= /unix/sysv/linux/microblaze/be/libc.abilist > index e8118569c3..b944680ede 100644 > --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist > +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist > @@ -2701,3 +2701,6 @@ 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 > diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps= /unix/sysv/linux/microblaze/le/libc.abilist > index c0d2373e64..28f7d19983 100644 > --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist > +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist > @@ -2698,3 +2698,6 @@ 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 > diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysde= ps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > index 2d0fd04f54..3da7cdaca5 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sys= deps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > index e39ccfb312..9fe87f15be 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysde= ps/unix/sysv/linux/mips/mips64/n32/libc.abilist > index 1e900f86e4..c14fca2111 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysde= ps/unix/sysv/linux/mips/mips64/n64/libc.abilist > index 9145ba7931..a363830226 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sy= sv/linux/nios2/libc.abilist > index e95d60d926..89b6f98667 100644 > --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist > +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist > @@ -2740,3 +2740,6 @@ 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 > diff --git a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/lin= ux/not-cancel.h > index 75b9e0ee1e..be5df35927 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 > +__getrandomn_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/sys= v/linux/or1k/libc.abilist > index ca934e374b..94c0ff9526 100644 > --- a/sysdeps/unix/sysv/linux/or1k/libc.abilist > +++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist > @@ -2123,3 +2123,6 @@ 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 > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b= /sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > index 3820b9f235..d6188de00b 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.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist= b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > index 464dc27fcd..8201230059 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.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/= sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > index 2f7e58747f..623505d783 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.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/= sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > index 4f3043d913..23b0d83408 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > @@ -2812,3 +2812,6 @@ 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 > diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/un= ix/sysv/linux/riscv/rv32/libc.abilist > index 84b6ac815a..a72e8ed9cc 100644 > --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist > @@ -2379,3 +2379,6 @@ 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 > diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/un= ix/sysv/linux/riscv/rv64/libc.abilist > index 4d5c19c56a..f3faecc2ae 100644 > --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > @@ -2579,3 +2579,6 @@ 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 > diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/= unix/sysv/linux/s390/s390-32/libc.abilist > index 7c5ee8d569..105e5a9231 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.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/= unix/sysv/linux/s390/s390-64/libc.abilist > index 50de0b46cf..c08c6c8301 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.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sy= sv/linux/sh/be/libc.abilist > index 66fba013ca..8ec1005644 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sy= sv/linux/sh/le/libc.abilist > index 38703f8aa0..5d776576f9 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps= /unix/sysv/linux/sparc/sparc32/libc.abilist > index 6df55eb765..f5f07f612e 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.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps= /unix/sysv/linux/sparc/sparc64/libc.abilist > index b90569d881..be687ebe02 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/uni= x/sysv/linux/x86_64/64/libc.abilist > index e88b0f101f..7f456fbb55 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.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/un= ix/sysv/linux/x86_64/x32/libc.abilist > index e0755272eb..c737201248 100644 > --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > @@ -2631,3 +2631,6 @@ 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 > -- > 2.32.0 - Mark