git-getrandom-chroot
authorGNU Libc Maintainers <debian-glibc@lists.debian.org>
Mon, 25 Aug 2025 19:11:05 +0000 (21:11 +0200)
committerAurelien Jarno <aurel32@debian.org>
Mon, 25 Aug 2025 19:11:05 +0000 (21:11 +0200)
commit0be7e61fe7a7e91c0adc5da862c1280cf8a97e17
tree59e7535425695b5c05a68e2aa1c8d38a916874d0
parentdb05d6522fed0e41dc398f0c2c3b2dad1bec9525
git-getrandom-chroot

commit 8fb923ddc38dd5f4bfac4869d70fd80483fdb87a
Author: Sergey Bugaev <bugaevc@gmail.com>
Date:   Fri Dec 2 16:55:58 2022 +0300

    hurd: Make getrandom cache the server port

    Previously, getrandom would, each time it's called, traverse the file
    system to find /dev/urandom, fetch some random data from it, then throw
    away that port. This is quite slow, while calls to getrandom are
    genrally expected to be fast.

    Additionally, this means that getrandom can not work when /dev/urandom
    is unavailable, such as inside a chroot that lacks one. User programs
    expect calls to getrandom to work inside a chroot if they first call
    getrandom outside of the chroot.

    In particular, this is known to break the OpenSSH server, and in that
    case the issue is exacerbated by the API of arc4random, which prevents
    it from properly reporting errors, forcing glibc to abort on failure.
    This causes sshd to just die once it tries to generate a random number.

    Caching the random server port, in a manner similar to how socket
    server ports are cached, both improves the performance and works around
    the chroot issue.

    Tested on i686-gnu with the following program:

    pthread_barrier_t barrier;

    void *worker(void*) {
        pthread_barrier_wait(&barrier);
        uint32_t sum = 0;
        for (int i = 0; i < 10000; i++) {
            sum += arc4random();
        }
        return (void *)(uintptr_t) sum;
    }

    int main() {
        pthread_t threads[THREAD_COUNT];

        pthread_barrier_init(&barrier, NULL, THREAD_COUNT);

        for (int i = 0; i < THREAD_COUNT; i++) {
            pthread_create(&threads[i], NULL, worker, NULL);
        }
        for (int i = 0; i < THREAD_COUNT; i++) {
            void *retval;
            pthread_join(threads[i], &retval);
            printf("Thread %i: %lu\n", i, (unsigned long)(uintptr_t) retval);
        }

    In my totally unscientific benchmark, with this patch, this completes
    in about 7 seconds, whereas previously it took about 50 seconds. This
    program was also used to test that getrandom () doesn't explode if the
    random server dies, but instead reopens the /dev/urandom anew. I have
    also verified that with this patch, OpenSSH can once again accept
    connections properly.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
    Message-Id: <20221202135558.23781-1-bugaevc@gmail.com>

Gbp-Pq: Topic hurd-i386
Gbp-Pq: Name git-getrandom-chroot.diff
sysdeps/mach/hurd/getrandom.c