Skip to content

Commit eb9d1bf

Browse files
committed
random: only read from /dev/random after its pool has received 128 bits
Immediately after boot, we allow reads from /dev/random before its entropy pool has been fully initialized. Fix this so that we don't allow this until the blocking pool has received 128 bits. We do this by repurposing the initialized flag in the entropy pool struct, and use the initialized flag in the blocking pool to indicate whether it is safe to pull from the blocking pool. To do this, we needed to rework when we decide to push entropy from the input pool to the blocking pool, since the initialized flag for the input pool was used for this purpose. To simplify things, we no longer use the initialized flag for that purpose, nor do we use the entropy_total field any more. Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 764ed18 commit eb9d1bf

File tree

2 files changed

+27
-30
lines changed

2 files changed

+27
-30
lines changed

drivers/char/random.c

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,6 @@ struct entropy_store {
470470
unsigned short add_ptr;
471471
unsigned short input_rotate;
472472
int entropy_count;
473-
int entropy_total;
474473
unsigned int initialized:1;
475474
unsigned int last_data_init:1;
476475
__u8 last_data[EXTRACT_SIZE];
@@ -643,7 +642,7 @@ static void process_random_ready_list(void)
643642
*/
644643
static void credit_entropy_bits(struct entropy_store *r, int nbits)
645644
{
646-
int entropy_count, orig;
645+
int entropy_count, orig, has_initialized = 0;
647646
const int pool_size = r->poolinfo->poolfracbits;
648647
int nfrac = nbits << ENTROPY_SHIFT;
649648

@@ -698,23 +697,25 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
698697
entropy_count = 0;
699698
} else if (entropy_count > pool_size)
700699
entropy_count = pool_size;
700+
if ((r == &blocking_pool) && !r->initialized &&
701+
(entropy_count >> ENTROPY_SHIFT) > 128)
702+
has_initialized = 1;
701703
if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
702704
goto retry;
703705

704-
r->entropy_total += nbits;
705-
if (!r->initialized && r->entropy_total > 128) {
706+
if (has_initialized)
706707
r->initialized = 1;
707-
r->entropy_total = 0;
708-
}
709708

710709
trace_credit_entropy_bits(r->name, nbits,
711-
entropy_count >> ENTROPY_SHIFT,
712-
r->entropy_total, _RET_IP_);
710+
entropy_count >> ENTROPY_SHIFT, _RET_IP_);
713711

714712
if (r == &input_pool) {
715713
int entropy_bits = entropy_count >> ENTROPY_SHIFT;
714+
struct entropy_store *other = &blocking_pool;
716715

717-
if (crng_init < 2 && entropy_bits >= 128) {
716+
if (crng_init < 2) {
717+
if (entropy_bits < 128)
718+
return;
718719
crng_reseed(&primary_crng, r);
719720
entropy_bits = r->entropy_count >> ENTROPY_SHIFT;
720721
}
@@ -725,20 +726,14 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
725726
wake_up_interruptible(&random_read_wait);
726727
kill_fasync(&fasync, SIGIO, POLL_IN);
727728
}
728-
/* If the input pool is getting full, send some
729-
* entropy to the blocking pool until it is 75% full.
729+
/* If the input pool is getting full, and the blocking
730+
* pool has room, send some entropy to the blocking
731+
* pool.
730732
*/
731-
if (entropy_bits > random_write_wakeup_bits &&
732-
r->initialized &&
733-
r->entropy_total >= 2*random_read_wakeup_bits) {
734-
struct entropy_store *other = &blocking_pool;
735-
736-
if (other->entropy_count <=
737-
3 * other->poolinfo->poolfracbits / 4) {
738-
schedule_work(&other->push_work);
739-
r->entropy_total = 0;
740-
}
741-
}
733+
if (!work_pending(&other->push_work) &&
734+
(ENTROPY_BITS(r) > 6 * r->poolinfo->poolbytes) &&
735+
(ENTROPY_BITS(other) <= 6 * other->poolinfo->poolbytes))
736+
schedule_work(&other->push_work);
742737
}
743738
}
744739

@@ -1553,6 +1548,11 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
15531548
int large_request = (nbytes > 256);
15541549

15551550
trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
1551+
if (!r->initialized && r->pull) {
1552+
xfer_secondary_pool(r, ENTROPY_BITS(r->pull)/8);
1553+
if (!r->initialized)
1554+
return 0;
1555+
}
15561556
xfer_secondary_pool(r, nbytes);
15571557
nbytes = account(r, nbytes, 0, 0);
15581558

include/trace/events/random.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,30 +62,27 @@ DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
6262

6363
TRACE_EVENT(credit_entropy_bits,
6464
TP_PROTO(const char *pool_name, int bits, int entropy_count,
65-
int entropy_total, unsigned long IP),
65+
unsigned long IP),
6666

67-
TP_ARGS(pool_name, bits, entropy_count, entropy_total, IP),
67+
TP_ARGS(pool_name, bits, entropy_count, IP),
6868

6969
TP_STRUCT__entry(
7070
__field( const char *, pool_name )
7171
__field( int, bits )
7272
__field( int, entropy_count )
73-
__field( int, entropy_total )
7473
__field(unsigned long, IP )
7574
),
7675

7776
TP_fast_assign(
7877
__entry->pool_name = pool_name;
7978
__entry->bits = bits;
8079
__entry->entropy_count = entropy_count;
81-
__entry->entropy_total = entropy_total;
8280
__entry->IP = IP;
8381
),
8482

85-
TP_printk("%s pool: bits %d entropy_count %d entropy_total %d "
86-
"caller %pS", __entry->pool_name, __entry->bits,
87-
__entry->entropy_count, __entry->entropy_total,
88-
(void *)__entry->IP)
83+
TP_printk("%s pool: bits %d entropy_count %d caller %pS",
84+
__entry->pool_name, __entry->bits,
85+
__entry->entropy_count, (void *)__entry->IP)
8986
);
9087

9188
TRACE_EVENT(push_to_pool,

0 commit comments

Comments
 (0)