Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

random: introduce getrandom(2) system call

The getrandom(2) system call was requested by the LibreSSL Portable
developers. It is analoguous to the getentropy(2) system call in
OpenBSD.

The rationale of this system call is to provide resiliance against
file descriptor exhaustion attacks, where the attacker consumes all
available file descriptors, forcing the use of the fallback code where
/dev/[u]random is not available. Since the fallback code is often not
well-tested, it is better to eliminate this potential failure mode
entirely.

The other feature provided by this new system call is the ability to
request randomness from the /dev/urandom entropy pool, but to block
until at least 128 bits of entropy has been accumulated in the
/dev/urandom entropy pool. Historically, the emphasis in the
/dev/urandom development has been to ensure that urandom pool is
initialized as quickly as possible after system boot, and preferably
before the init scripts start execution.

This is because changing /dev/urandom reads to block represents an
interface change that could potentially break userspace which is not
acceptable. In practice, on most x86 desktop and server systems, in
general the entropy pool can be initialized before it is needed (and
in modern kernels, we will printk a warning message if not). However,
on an embedded system, this may not be the case. And so with this new
interface, we can provide the functionality of blocking until the
urandom pool has been initialized. Any userspace program which uses
this new functionality must take care to assure that if it is used
during the boot process, that it will not cause the init scripts or
other portions of the system startup to hang indefinitely.

SYNOPSIS
#include <linux/random.h>

int getrandom(void *buf, size_t buflen, unsigned int flags);

DESCRIPTION
The system call getrandom() fills the buffer pointed to by buf
with up to buflen random bytes which can be used to seed user
space random number generators (i.e., DRBG's) or for other
cryptographic uses. It should not be used for Monte Carlo
simulations or other programs/algorithms which are doing
probabilistic sampling.

If the GRND_RANDOM flags bit is set, then draw from the
/dev/random pool instead of the /dev/urandom pool. The
/dev/random pool is limited based on the entropy that can be
obtained from environmental noise, so if there is insufficient
entropy, the requested number of bytes may not be returned.
If there is no entropy available at all, getrandom(2) will
either block, or return an error with errno set to EAGAIN if
the GRND_NONBLOCK bit is set in flags.

If the GRND_RANDOM bit is not set, then the /dev/urandom pool
will be used. Unlike using read(2) to fetch data from
/dev/urandom, if the urandom pool has not been sufficiently
initialized, getrandom(2) will block (or return -1 with the
errno set to EAGAIN if the GRND_NONBLOCK bit is set in flags).

The getentropy(2) system call in OpenBSD can be emulated using
the following function:

int getentropy(void *buf, size_t buflen)
{
int ret;

if (buflen > 256)
goto failure;
ret = getrandom(buf, buflen, 0);
if (ret < 0)
return ret;
if (ret == buflen)
return 0;
failure:
errno = EIO;
return -1;
}

RETURN VALUE
On success, the number of bytes that was filled in the buf is
returned. This may not be all the bytes requested by the
caller via buflen if insufficient entropy was present in the
/dev/random pool, or if the system call was interrupted by a
signal.

On error, -1 is returned, and errno is set appropriately.

ERRORS
EINVAL An invalid flag was passed to getrandom(2)

EFAULT buf is outside the accessible address space.

EAGAIN The requested entropy was not available, and
getentropy(2) would have blocked if the
GRND_NONBLOCK flag was not set.

EINTR While blocked waiting for entropy, the call was
interrupted by a signal handler; see the description
of how interrupted read(2) calls on "slow" devices
are handled with and without the SA_RESTART flag
in the signal(7) man page.

NOTES
For small requests (buflen <= 256) getrandom(2) will not
return EINTR when reading from the urandom pool once the
entropy pool has been initialized, and it will return all of
the bytes that have been requested. This is the recommended
way to use getrandom(2), and is designed for compatibility
with OpenBSD's getentropy() system call.

However, if you are using GRND_RANDOM, then getrandom(2) may
block until the entropy accounting determines that sufficient
environmental noise has been gathered such that getrandom(2)
will be operating as a NRBG instead of a DRBG for those people
who are working in the NIST SP 800-90 regime. Since it may
block for a long time, these guarantees do *not* apply. The
user may want to interrupt a hanging process using a signal,
so blocking until all of the requested bytes are returned
would be unfriendly.

For this reason, the user of getrandom(2) MUST always check
the return value, in case it returns some error, or if fewer
bytes than requested was returned. In the case of
!GRND_RANDOM and small request, the latter should never
happen, but the careful userspace code (and all crypto code
should be careful) should check for this anyway!

Finally, unless you are doing long-term key generation (and
perhaps not even then), you probably shouldn't be using
GRND_RANDOM. The cryptographic algorithms used for
/dev/urandom are quite conservative, and so should be
sufficient for all purposes. The disadvantage of GRND_RANDOM
is that it can block, and the increased complexity required to
deal with partially fulfilled getrandom(2) requests.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Zach Brown <zab@zabbo.net>

+54 -4
+1
arch/x86/syscalls/syscall_32.tbl
··· 360 360 351 i386 sched_setattr sys_sched_setattr 361 361 352 i386 sched_getattr sys_sched_getattr 362 362 353 i386 renameat2 sys_renameat2 363 + 355 i386 getrandom sys_getrandom
+1
arch/x86/syscalls/syscall_64.tbl
··· 323 323 314 common sched_setattr sys_sched_setattr 324 324 315 common sched_getattr sys_sched_getattr 325 325 316 common renameat2 sys_renameat2 326 + 318 common getrandom sys_getrandom 326 327 327 328 # 328 329 # x32-specific system call numbers start at 512 to avoid cache impact
+37 -3
drivers/char/random.c
··· 258 258 #include <linux/kmemcheck.h> 259 259 #include <linux/workqueue.h> 260 260 #include <linux/irq.h> 261 + #include <linux/syscalls.h> 262 + #include <linux/completion.h> 261 263 262 264 #include <asm/processor.h> 263 265 #include <asm/uaccess.h> ··· 406 404 */ 407 405 static DECLARE_WAIT_QUEUE_HEAD(random_read_wait); 408 406 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); 407 + static DECLARE_WAIT_QUEUE_HEAD(urandom_init_wait); 409 408 static struct fasync_struct *fasync; 410 409 411 410 /********************************************************************** ··· 660 657 r->entropy_total = 0; 661 658 if (r == &nonblocking_pool) { 662 659 prandom_reseed_late(); 660 + wake_up_interruptible(&urandom_init_wait); 663 661 pr_notice("random: %s pool is initialized\n", r->name); 664 662 } 665 663 } ··· 1178 1174 { 1179 1175 ssize_t ret = 0, i; 1180 1176 __u8 tmp[EXTRACT_SIZE]; 1177 + int large_request = (nbytes > 256); 1181 1178 1182 1179 trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_); 1183 1180 xfer_secondary_pool(r, nbytes); 1184 1181 nbytes = account(r, nbytes, 0, 0); 1185 1182 1186 1183 while (nbytes) { 1187 - if (need_resched()) { 1184 + if (large_request && need_resched()) { 1188 1185 if (signal_pending(current)) { 1189 1186 if (ret == 0) 1190 1187 ret = -ERESTARTSYS; ··· 1360 1355 } 1361 1356 1362 1357 static ssize_t 1363 - random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) 1358 + _random_read(int nonblock, char __user *buf, size_t nbytes) 1364 1359 { 1365 1360 ssize_t n; 1366 1361 ··· 1384 1379 if (arch_random_refill()) 1385 1380 continue; 1386 1381 1387 - if (file->f_flags & O_NONBLOCK) 1382 + if (nonblock) 1388 1383 return -EAGAIN; 1389 1384 1390 1385 wait_event_interruptible(random_read_wait, ··· 1393 1388 if (signal_pending(current)) 1394 1389 return -ERESTARTSYS; 1395 1390 } 1391 + } 1392 + 1393 + static ssize_t 1394 + random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) 1395 + { 1396 + return _random_read(file->f_flags & O_NONBLOCK, buf, nbytes); 1396 1397 } 1397 1398 1398 1399 static ssize_t ··· 1543 1532 .fasync = random_fasync, 1544 1533 .llseek = noop_llseek, 1545 1534 }; 1535 + 1536 + SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, 1537 + unsigned int, flags) 1538 + { 1539 + if (flags & ~(GRND_NONBLOCK|GRND_RANDOM)) 1540 + return -EINVAL; 1541 + 1542 + if (count > INT_MAX) 1543 + count = INT_MAX; 1544 + 1545 + if (flags & GRND_RANDOM) 1546 + return _random_read(flags & GRND_NONBLOCK, buf, count); 1547 + 1548 + if (unlikely(nonblocking_pool.initialized == 0)) { 1549 + if (flags & GRND_NONBLOCK) 1550 + return -EAGAIN; 1551 + wait_event_interruptible(urandom_init_wait, 1552 + nonblocking_pool.initialized); 1553 + if (signal_pending(current)) 1554 + return -ERESTARTSYS; 1555 + } 1556 + return urandom_read(NULL, buf, count, NULL); 1557 + } 1546 1558 1547 1559 /*************************************************************** 1548 1560 * Random UUID interface
+3
include/linux/syscalls.h
··· 866 866 asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, 867 867 unsigned long idx1, unsigned long idx2); 868 868 asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags); 869 + asmlinkage long sys_getrandom(char __user *buf, size_t count, 870 + unsigned int flags); 871 + 869 872 #endif
+3 -1
include/uapi/asm-generic/unistd.h
··· 699 699 __SYSCALL(__NR_sched_getattr, sys_sched_getattr) 700 700 #define __NR_renameat2 276 701 701 __SYSCALL(__NR_renameat2, sys_renameat2) 702 + #define __NR_getrandom 278 703 + __SYSCALL(__NR_getrandom, sys_getrandom) 702 704 703 705 #undef __NR_syscalls 704 - #define __NR_syscalls 277 706 + #define __NR_syscalls 279 705 707 706 708 /* 707 709 * All syscalls below here should go away really,
+9
include/uapi/linux/random.h
··· 40 40 __u32 buf[0]; 41 41 }; 42 42 43 + /* 44 + * Flags for getrandom(2) 45 + * 46 + * GRND_NONBLOCK Don't block and return EAGAIN instead 47 + * GRND_RANDOM Use the /dev/random pool instead of /dev/urandom 48 + */ 49 + #define GRND_NONBLOCK 0x0001 50 + #define GRND_RANDOM 0x0002 51 + 43 52 #endif /* _UAPI_LINUX_RANDOM_H */