Skip to content

Commit 3f2dc27

Browse files
committed
Merge branch 'entropy'
Merge active entropy generation updates. This is admittedly partly "for discussion". We need to have a way forward for the boot time deadlocks where user space ends up waiting for more entropy, but no entropy is forthcoming because the system is entirely idle just waiting for something to happen. While this was triggered by what is arguably a user space bug with GDM/gnome-session asking for secure randomness during early boot, when they didn't even need any such truly secure thing, the issue ends up being that our "getrandom()" interface is prone to that kind of confusion, because people don't think very hard about whether they want to block for sufficient amounts of entropy. The approach here-in is to decide to not just passively wait for entropy to happen, but to start actively collecting it if it is missing. This is not necessarily always possible, but if the architecture has a CPU cycle counter, there is a fair amount of noise in the exact timings of reasonably complex loads. We may end up tweaking the load and the entropy estimates, but this should be at least a reasonable starting point. As part of this, we also revert the revert of the ext4 IO pattern improvement that ended up triggering the reported lack of external entropy. * getrandom() active entropy waiting: Revert "Revert "ext4: make __ext4_get_inode_loc plug"" random: try to actively add entropy rather than passively wait for it
2 parents a3c0e7b + 02f03c4 commit 3f2dc27

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

drivers/char/random.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,56 @@ void get_random_bytes(void *buf, int nbytes)
17321732
}
17331733
EXPORT_SYMBOL(get_random_bytes);
17341734

1735+
1736+
/*
1737+
* Each time the timer fires, we expect that we got an unpredictable
1738+
* jump in the cycle counter. Even if the timer is running on another
1739+
* CPU, the timer activity will be touching the stack of the CPU that is
1740+
* generating entropy..
1741+
*
1742+
* Note that we don't re-arm the timer in the timer itself - we are
1743+
* happy to be scheduled away, since that just makes the load more
1744+
* complex, but we do not want the timer to keep ticking unless the
1745+
* entropy loop is running.
1746+
*
1747+
* So the re-arming always happens in the entropy loop itself.
1748+
*/
1749+
static void entropy_timer(struct timer_list *t)
1750+
{
1751+
credit_entropy_bits(&input_pool, 1);
1752+
}
1753+
1754+
/*
1755+
* If we have an actual cycle counter, see if we can
1756+
* generate enough entropy with timing noise
1757+
*/
1758+
static void try_to_generate_entropy(void)
1759+
{
1760+
struct {
1761+
unsigned long now;
1762+
struct timer_list timer;
1763+
} stack;
1764+
1765+
stack.now = random_get_entropy();
1766+
1767+
/* Slow counter - or none. Don't even bother */
1768+
if (stack.now == random_get_entropy())
1769+
return;
1770+
1771+
timer_setup_on_stack(&stack.timer, entropy_timer, 0);
1772+
while (!crng_ready()) {
1773+
if (!timer_pending(&stack.timer))
1774+
mod_timer(&stack.timer, jiffies+1);
1775+
mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
1776+
schedule();
1777+
stack.now = random_get_entropy();
1778+
}
1779+
1780+
del_timer_sync(&stack.timer);
1781+
destroy_timer_on_stack(&stack.timer);
1782+
mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
1783+
}
1784+
17351785
/*
17361786
* Wait for the urandom pool to be seeded and thus guaranteed to supply
17371787
* cryptographically secure random numbers. This applies to: the /dev/urandom
@@ -1746,7 +1796,17 @@ int wait_for_random_bytes(void)
17461796
{
17471797
if (likely(crng_ready()))
17481798
return 0;
1749-
return wait_event_interruptible(crng_init_wait, crng_ready());
1799+
1800+
do {
1801+
int ret;
1802+
ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
1803+
if (ret)
1804+
return ret > 0 ? 0 : ret;
1805+
1806+
try_to_generate_entropy();
1807+
} while (!crng_ready());
1808+
1809+
return 0;
17501810
}
17511811
EXPORT_SYMBOL(wait_for_random_bytes);
17521812

fs/ext4/inode.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4551,6 +4551,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
45514551
struct buffer_head *bh;
45524552
struct super_block *sb = inode->i_sb;
45534553
ext4_fsblk_t block;
4554+
struct blk_plug plug;
45544555
int inodes_per_block, inode_offset;
45554556

45564557
iloc->bh = NULL;
@@ -4639,6 +4640,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
46394640
* If we need to do any I/O, try to pre-readahead extra
46404641
* blocks from the inode table.
46414642
*/
4643+
blk_start_plug(&plug);
46424644
if (EXT4_SB(sb)->s_inode_readahead_blks) {
46434645
ext4_fsblk_t b, end, table;
46444646
unsigned num;
@@ -4669,6 +4671,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
46694671
get_bh(bh);
46704672
bh->b_end_io = end_buffer_read_sync;
46714673
submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, bh);
4674+
blk_finish_plug(&plug);
46724675
wait_on_buffer(bh);
46734676
if (!buffer_uptodate(bh)) {
46744677
EXT4_ERROR_INODE_BLOCK(inode, block,

0 commit comments

Comments
 (0)