random: add fork_events sysctl for polling VM forks

In order to inform userspace of virtual machine forks, this commit adds
a "fork_events" sysctl, which returns the number of times a VM has
forked (from the view of the current system) and allows userspace
processes to poll() on it for notification of VM forks.

It avoids exposing the actual vmgenid from the hypervisor to userspace,
in case there is any randomness value in keeping it secret. Rather,
userspace is expected to simply use getrandom() if it wants a fresh
value. The counter read from this file itself may not be fresh, since
another VM fork may be incremented to the same value.

For example, the following snippet can be used to print a message every
time a VM forks, after the RNG has been reseeded:

  struct pollfd fd = { .fd = open("/proc/sys/kernel/random/fork_events", O_RDONLY)  };
  assert(fd.fd >= 0);
  for (;;) {
    assert(poll(&fd, 1, -1) > 0);
    puts("vm fork detected");
  }

Various programs and libraries that utilize cryptographic operations
depending on fresh randomness can invalidate old keys or take other
appropriate actions when receiving that event. While this is racier than
allowing userspace to mmap/vDSO the vmgenid itself, it's an incremental
step forward that's not as heavyweight.

Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Theodore Ts'o <tytso@mit.edu>
Cc: Alexander Graf <graf@amazon.com>
Cc: Colm MacCarthaigh <colmmacc@amazon.com>
Cc: Torben Hansen <htorben@amazon.co.uk>
Cc: Jann Horn <jannh@google.com>
Cc: Lennart Poettering <mzxreary@0pointer.de>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2 files changed