Re: [RFC PATCH 1/2] random: emit reseed notifications for PRNGs

Alexander Graf
2023-08-23T10:20:45Z

Hey Greg,

On 23.08.23 12:08, Babis Chalios wrote:
>
>
> On 23/8/23 12:06, Greg KH wrote:
>>
>> On Wed, Aug 23, 2023 at 11:27:11AM +0200, Babis Chalios wrote:
>>> Hi Greg,
>>>
>>> On 23/8/23 11:08, Greg KH wrote:
>>>>
>>>> On Wed, Aug 23, 2023 at 11:01:05AM +0200, Babis Chalios wrote:
>>>>> Sometimes, PRNGs need to reseed. For example, on a regular timer
>>>>> interval, to ensure nothing consumes a random value for longer than e.g.
>>>>> 5 minutes, or when VMs get cloned, to ensure seeds don't leak in to
>>>>> clones.
>>>>>
>>>>> The notification happens through a 32bit epoch value that changes every
>>>>> time cached entropy is no longer valid, hence PRNGs need to reseed. User
>>>>> space applications can get hold of a pointer to this value through
>>>>> /dev/(u)random. We introduce a new ioctl() that returns an anonymous
>>>>> file descriptor. From this file descriptor we can mmap() a single page
>>>>> which includes the epoch at offset 0.
>>>>>
>>>>> random.c maintains the epoch value in a global shared page. It exposes
>>>>> a registration API for kernel subsystems that are able to notify when
>>>>> reseeding is needed. Notifiers register with random.c and receive a
>>>>> unique 8bit ID and a pointer to the epoch. When they need to report a
>>>>> reseeding event they write a new epoch value which includes the
>>>>> notifier ID in the first 8 bits and an increasing counter value in the
>>>>> remaining 24 bits:
>>>>>
>>>>> RNG epoch
>>>>> *-------------*---------------------*
>>>>> | notifier id | epoch counter value |
>>>>> *-------------*---------------------*
>>>>> 8 bits 24 bits
>>>> Why not just use 32/32 for a full 64bit value, or better yet, 2
>>>> different variables? Why is 32bits and packing things together here
>>>> somehow simpler?
>>> We made it 32 bits so that we can read/write it atomically in all 32bit
>>> architectures.
>>> Do you think that's not a problem?
>> What 32bit platforms care about this type of interface at all?
>
> I think, any 32bit platform that gets random bytes from the kernel.

We're building an ABI here that generically propagates an atomic way for
user space to learn about an "rng epoch". Since there are 32bit user
space applications out there whose executing VMs can be cloned or that
want to learn about regular epoch changes (i386, arm32, 32bit riscv,
etc), we need to make sure we have a viable way for them to consume the
ABI as well. This applies to 32bit user space - the kernel may as well
run 64bit like a typical aarch64 setup today.

We could of course build this ABI with a "long" notion in mind. But then
you would get an ioctl to a kernel data structure that is 64bit, even
with CONFIG_COMPAT. So now we'd have to build wrappers and maintain 2
structures for 32bit and 64bit user space and everything would become
super complicated.

These events won't happen very often. 24bits is very likely easily
sufficient to not ever race between someone setting a new epoch and
someone reading the epoch value. So by keeping it 32bit, we make it
guaranteed atomic on all targets and completely remove any CONFIG_COMPAT
woes.

Alex

Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879