Hi, Le 23/08/2023 à 11:01, Babis Chalios a écrit :
User space often implements PRNGs that use /dev/random as entropy source. We can not expect that this randomness sources stay completely unknown forever. For various reasons, the originating PRNG seed may become known at which point the PRNG becomes insecure for further random number generation. Events that can lead to that are for example fast computers reversing the PRNG function using a number of inputs or Virtual Machine clones which carry seed values into their clones. During LPC 2022 Jason, Alex, Michael and me brainstormed on how to atomically expose a notification to user space that it should reseed. Atomicity is key for the VM clone case. This patchset implements a potential path to do so. This patchset introduces an epoch value as the means of communicating to the guest the need to reseed. The epoch is a 32bit value with the following form: RNG epoch *-------------*---------------------* | notifier id | epoch counter value | *-------------*---------------------* 8 bits 24 bits Changes in this value signal moments in time that PRNGs need to be re-seeded. As a result, the intended use of the epoch from user space PRNGs is to cache the epoch value every time they reseed using kernel entropy, then control that its value hasn't changed before giving out random numbers. If the value has changed the PRNG needs to reseed before producing any more random bits. The API for getting hold of this value is offered through /dev/(u)random. We introduce a new ioctl for these devices, which creates an anonymous file descriptor. User processes can call the ioctl() to get the anon fd and then mmap it to a single page. That page contains the value of the epoch at offset 0. Naturally, random.c is the component that maintains the RNG epoch. During initialization it allocates a single global page which holds the epoch value. Moreover, it exposes an API to kernel subsystems (notifiers) which can report events that require PRNG reseeding. Notifiers register with random.c and receive an 8-bit notifier id (up to 256 subscribers should be enough) and a pointer to the epoch. Notifying, then, is equivalent to writing in the epoch address a new epoch value. Notifiers write epoch values that include the notifier ID on the higher 8 bits and increasing counter values on the 24 remaining bits. This guarantees that two notifiers cannot ever write the same epoch value, since notificator IDs are unique. The first patch of this series implements the epoch mechanism. It adds the logic in the random.c to maintain the epoch page and expose the user space facing API. It also adds the internal API that allows kernel systems to register as notifiers.
From userspace point of view, having to open /dev/random, ioctl, and mmap() is a no-go for a (CS)PRNG embedded in libc for arc4random(). I'm biased, as I proposed to expose such seed epoch value to userspace through getrandom() directly, relying on vDSO for reasonable performances, because current's glibc arc4random() is somewhat to slow to be a general replacement rand(). See https://lore.kernel.org/all/cover.1673539719.git.ydroneaud@xxxxxxxxxx/ https://lore.kernel.org/all/ae35afa5b824dc76c5ded98efcabc117e6dd3d70@xxxxxxxxxx/ Reards. -- Yann Droneaud