255
255
#include <linux/fips.h>
256
256
#include <linux/ptrace.h>
257
257
#include <linux/kmemcheck.h>
258
+ #include <linux/syscalls.h>
259
+ #include <linux/completion.h>
258
260
259
261
#ifdef CONFIG_GENERIC_HARDIRQS
260
262
# include <linux/irq.h>
@@ -397,6 +399,7 @@ static struct poolinfo {
397
399
*/
398
400
static DECLARE_WAIT_QUEUE_HEAD (random_read_wait );
399
401
static DECLARE_WAIT_QUEUE_HEAD (random_write_wait );
402
+ static DECLARE_WAIT_QUEUE_HEAD (urandom_init_wait );
400
403
static struct fasync_struct * fasync ;
401
404
402
405
#if 0
@@ -607,10 +610,15 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
607
610
if (cmpxchg (& r -> entropy_count , orig , entropy_count ) != orig )
608
611
goto retry ;
609
612
610
- if (!r -> initialized && nbits > 0 ) {
611
- r -> entropy_total += nbits ;
612
- if (r -> entropy_total > 128 )
613
- r -> initialized = 1 ;
613
+ r -> entropy_total += nbits ;
614
+ if (!r -> initialized && r -> entropy_total > 128 ) {
615
+ r -> initialized = 1 ;
616
+ r -> entropy_total = 0 ;
617
+ if (r == & nonblocking_pool ) {
618
+ prandom_reseed_late ();
619
+ wake_up_all (& urandom_init_wait );
620
+ pr_notice ("random: %s pool is initialized\n" , r -> name );
621
+ }
614
622
}
615
623
616
624
trace_credit_entropy_bits (r -> name , nbits , entropy_count ,
@@ -999,13 +1007,14 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
999
1007
{
1000
1008
ssize_t ret = 0 , i ;
1001
1009
__u8 tmp [EXTRACT_SIZE ];
1010
+ int large_request = (nbytes > 256 );
1002
1011
1003
1012
trace_extract_entropy_user (r -> name , nbytes , r -> entropy_count , _RET_IP_ );
1004
1013
xfer_secondary_pool (r , nbytes );
1005
1014
nbytes = account (r , nbytes , 0 , 0 );
1006
1015
1007
1016
while (nbytes ) {
1008
- if (need_resched ()) {
1017
+ if (large_request && need_resched ()) {
1009
1018
if (signal_pending (current )) {
1010
1019
if (ret == 0 )
1011
1020
ret = - ERESTARTSYS ;
@@ -1138,7 +1147,7 @@ void rand_initialize_disk(struct gendisk *disk)
1138
1147
#endif
1139
1148
1140
1149
static ssize_t
1141
- random_read ( struct file * file , char __user * buf , size_t nbytes , loff_t * ppos )
1150
+ _random_read ( int nonblock , char __user * buf , size_t nbytes )
1142
1151
{
1143
1152
ssize_t n , retval = 0 , count = 0 ;
1144
1153
@@ -1158,7 +1167,7 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
1158
1167
n * 8 , (nbytes - n )* 8 );
1159
1168
1160
1169
if (n == 0 ) {
1161
- if (file -> f_flags & O_NONBLOCK ) {
1170
+ if (nonblock ) {
1162
1171
retval = - EAGAIN ;
1163
1172
break ;
1164
1173
}
@@ -1193,6 +1202,12 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
1193
1202
return (count ? count : retval );
1194
1203
}
1195
1204
1205
+ static ssize_t
1206
+ random_read (struct file * file , char __user * buf , size_t nbytes , loff_t * ppos )
1207
+ {
1208
+ return _random_read (file -> f_flags & O_NONBLOCK , buf , nbytes );
1209
+ }
1210
+
1196
1211
static ssize_t
1197
1212
urandom_read (struct file * file , char __user * buf , size_t nbytes , loff_t * ppos )
1198
1213
{
@@ -1319,6 +1334,29 @@ const struct file_operations urandom_fops = {
1319
1334
.llseek = noop_llseek ,
1320
1335
};
1321
1336
1337
+ SYSCALL_DEFINE3 (getrandom , char __user * , buf , size_t , count ,
1338
+ unsigned int , flags )
1339
+ {
1340
+ if (flags & ~(GRND_NONBLOCK |GRND_RANDOM ))
1341
+ return - EINVAL ;
1342
+
1343
+ if (count > INT_MAX )
1344
+ count = INT_MAX ;
1345
+
1346
+ if (flags & GRND_RANDOM )
1347
+ return _random_read (flags & GRND_NONBLOCK , buf , count );
1348
+
1349
+ if (unlikely (nonblocking_pool .initialized == 0 )) {
1350
+ if (flags & GRND_NONBLOCK )
1351
+ return - EAGAIN ;
1352
+ wait_event_interruptible (urandom_init_wait ,
1353
+ nonblocking_pool .initialized );
1354
+ if (signal_pending (current ))
1355
+ return - ERESTARTSYS ;
1356
+ }
1357
+ return urandom_read (NULL , buf , count , NULL );
1358
+ }
1359
+
1322
1360
/***************************************************************
1323
1361
* Random UUID interface
1324
1362
*
0 commit comments