aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/syscalls/syscall_32.tbl1
-rw-r--r--arch/x86/syscalls/syscall_64.tbl1
-rw-r--r--drivers/char/random.c40
-rw-r--r--include/linux/syscalls.h3
-rw-r--r--include/uapi/asm-generic/unistd.h4
-rw-r--r--include/uapi/linux/random.h9
6 files changed, 54 insertions, 4 deletions
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index d6b867921612..5b46a618aeb1 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -360,3 +360,4 @@
360351 i386 sched_setattr sys_sched_setattr 360351 i386 sched_setattr sys_sched_setattr
361352 i386 sched_getattr sys_sched_getattr 361352 i386 sched_getattr sys_sched_getattr
362353 i386 renameat2 sys_renameat2 362353 i386 renameat2 sys_renameat2
363355 i386 getrandom sys_getrandom
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
index ec255a1646d2..0dc4bf891460 100644
--- a/arch/x86/syscalls/syscall_64.tbl
+++ b/arch/x86/syscalls/syscall_64.tbl
@@ -323,6 +323,7 @@
323314 common sched_setattr sys_sched_setattr 323314 common sched_setattr sys_sched_setattr
324315 common sched_getattr sys_sched_getattr 324315 common sched_getattr sys_sched_getattr
325316 common renameat2 sys_renameat2 325316 common renameat2 sys_renameat2
326318 common getrandom sys_getrandom
326 327
327# 328#
328# x32-specific system call numbers start at 512 to avoid cache impact 329# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/drivers/char/random.c b/drivers/char/random.c
index aa22fe551c2a..7d1682ea1e86 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -258,6 +258,8 @@
258#include <linux/kmemcheck.h> 258#include <linux/kmemcheck.h>
259#include <linux/workqueue.h> 259#include <linux/workqueue.h>
260#include <linux/irq.h> 260#include <linux/irq.h>
261#include <linux/syscalls.h>
262#include <linux/completion.h>
261 263
262#include <asm/processor.h> 264#include <asm/processor.h>
263#include <asm/uaccess.h> 265#include <asm/uaccess.h>
@@ -404,6 +406,7 @@ static struct poolinfo {
404 */ 406 */
405static DECLARE_WAIT_QUEUE_HEAD(random_read_wait); 407static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
406static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); 408static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
409static DECLARE_WAIT_QUEUE_HEAD(urandom_init_wait);
407static struct fasync_struct *fasync; 410static struct fasync_struct *fasync;
408 411
409/********************************************************************** 412/**********************************************************************
@@ -657,6 +660,7 @@ retry:
657 r->entropy_total = 0; 660 r->entropy_total = 0;
658 if (r == &nonblocking_pool) { 661 if (r == &nonblocking_pool) {
659 prandom_reseed_late(); 662 prandom_reseed_late();
663 wake_up_interruptible(&urandom_init_wait);
660 pr_notice("random: %s pool is initialized\n", r->name); 664 pr_notice("random: %s pool is initialized\n", r->name);
661 } 665 }
662 } 666 }
@@ -1174,13 +1178,14 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
1174{ 1178{
1175 ssize_t ret = 0, i; 1179 ssize_t ret = 0, i;
1176 __u8 tmp[EXTRACT_SIZE]; 1180 __u8 tmp[EXTRACT_SIZE];
1181 int large_request = (nbytes > 256);
1177 1182
1178 trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_); 1183 trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
1179 xfer_secondary_pool(r, nbytes); 1184 xfer_secondary_pool(r, nbytes);
1180 nbytes = account(r, nbytes, 0, 0); 1185 nbytes = account(r, nbytes, 0, 0);
1181 1186
1182 while (nbytes) { 1187 while (nbytes) {
1183 if (need_resched()) { 1188 if (large_request && need_resched()) {
1184 if (signal_pending(current)) { 1189 if (signal_pending(current)) {
1185 if (ret == 0) 1190 if (ret == 0)
1186 ret = -ERESTARTSYS; 1191 ret = -ERESTARTSYS;
@@ -1355,7 +1360,7 @@ static int arch_random_refill(void)
1355} 1360}
1356 1361
1357static ssize_t 1362static ssize_t
1358random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) 1363_random_read(int nonblock, char __user *buf, size_t nbytes)
1359{ 1364{
1360 ssize_t n; 1365 ssize_t n;
1361 1366
@@ -1379,7 +1384,7 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
1379 if (arch_random_refill()) 1384 if (arch_random_refill())
1380 continue; 1385 continue;
1381 1386
1382 if (file->f_flags & O_NONBLOCK) 1387 if (nonblock)
1383 return -EAGAIN; 1388 return -EAGAIN;
1384 1389
1385 wait_event_interruptible(random_read_wait, 1390 wait_event_interruptible(random_read_wait,
@@ -1391,6 +1396,12 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
1391} 1396}
1392 1397
1393static ssize_t 1398static ssize_t
1399random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
1400{
1401 return _random_read(file->f_flags & O_NONBLOCK, buf, nbytes);
1402}
1403
1404static ssize_t
1394urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) 1405urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
1395{ 1406{
1396 int ret; 1407 int ret;
@@ -1533,6 +1544,29 @@ const struct file_operations urandom_fops = {
1533 .llseek = noop_llseek, 1544 .llseek = noop_llseek,
1534}; 1545};
1535 1546
1547SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
1548 unsigned int, flags)
1549{
1550 if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
1551 return -EINVAL;
1552
1553 if (count > INT_MAX)
1554 count = INT_MAX;
1555
1556 if (flags & GRND_RANDOM)
1557 return _random_read(flags & GRND_NONBLOCK, buf, count);
1558
1559 if (unlikely(nonblocking_pool.initialized == 0)) {
1560 if (flags & GRND_NONBLOCK)
1561 return -EAGAIN;
1562 wait_event_interruptible(urandom_init_wait,
1563 nonblocking_pool.initialized);
1564 if (signal_pending(current))
1565 return -ERESTARTSYS;
1566 }
1567 return urandom_read(NULL, buf, count, NULL);
1568}
1569
1536/*************************************************************** 1570/***************************************************************
1537 * Random UUID interface 1571 * Random UUID interface
1538 * 1572 *
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index b0881a0ed322..43324a897cf2 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -866,4 +866,7 @@ asmlinkage long sys_process_vm_writev(pid_t pid,
866asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, 866asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
867 unsigned long idx1, unsigned long idx2); 867 unsigned long idx1, unsigned long idx2);
868asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags); 868asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
869asmlinkage long sys_getrandom(char __user *buf, size_t count,
870 unsigned int flags);
871
869#endif 872#endif
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 333640608087..1d104a2ca643 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -699,9 +699,11 @@ __SYSCALL(__NR_sched_setattr, sys_sched_setattr)
699__SYSCALL(__NR_sched_getattr, sys_sched_getattr) 699__SYSCALL(__NR_sched_getattr, sys_sched_getattr)
700#define __NR_renameat2 276 700#define __NR_renameat2 276
701__SYSCALL(__NR_renameat2, sys_renameat2) 701__SYSCALL(__NR_renameat2, sys_renameat2)
702#define __NR_getrandom 278
703__SYSCALL(__NR_getrandom, sys_getrandom)
702 704
703#undef __NR_syscalls 705#undef __NR_syscalls
704#define __NR_syscalls 277 706#define __NR_syscalls 279
705 707
706/* 708/*
707 * All syscalls below here should go away really, 709 * All syscalls below here should go away really,
diff --git a/include/uapi/linux/random.h b/include/uapi/linux/random.h
index fff3528a078f..3f93d1695e7f 100644
--- a/include/uapi/linux/random.h
+++ b/include/uapi/linux/random.h
@@ -40,4 +40,13 @@ struct rand_pool_info {
40 __u32 buf[0]; 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#endif /* _UAPI_LINUX_RANDOM_H */ 52#endif /* _UAPI_LINUX_RANDOM_H */