lkml.org 
[lkml]   [2022]   [Jan]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.4 72/73] random: do not throw away excess input to crng_fast_load
    Date
    From: "Jason A. Donenfeld" <Jason@zx2c4.com>

    [ Upstream commit 73c7733f122e8d0107f88655a12011f68f69e74b ]

    When crng_fast_load() is called by add_hwgenerator_randomness(), we
    currently will advance to crng_init==1 once we've acquired 64 bytes, and
    then throw away the rest of the buffer. Usually, that is not a problem:
    When add_hwgenerator_randomness() gets called via EFI or DT during
    setup_arch(), there won't be any IRQ randomness. Therefore, the 64 bytes
    passed by EFI exactly matches what is needed to advance to crng_init==1.
    Usually, DT seems to pass 64 bytes as well -- with one notable exception
    being kexec, which hands over 128 bytes of entropy to the kexec'd kernel.
    In that case, we'll advance to crng_init==1 once 64 of those bytes are
    consumed by crng_fast_load(), but won't continue onward feeding in bytes
    to progress to crng_init==2. This commit fixes the issue by feeding
    any leftover bytes into the next phase in add_hwgenerator_randomness().

    [linux@dominikbrodowski.net: rewrite commit message]
    Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
    Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/char/random.c | 19 ++++++++++++-------
    1 file changed, 12 insertions(+), 7 deletions(-)

    diff --git a/drivers/char/random.c b/drivers/char/random.c
    index ffd61aadb7614..a094704033062 100644
    --- a/drivers/char/random.c
    +++ b/drivers/char/random.c
    @@ -924,12 +924,14 @@ static void numa_crng_init(void) {}

    /*
    * crng_fast_load() can be called by code in the interrupt service
    - * path. So we can't afford to dilly-dally.
    + * path. So we can't afford to dilly-dally. Returns the number of
    + * bytes processed from cp.
    */
    -static int crng_fast_load(const char *cp, size_t len)
    +static size_t crng_fast_load(const char *cp, size_t len)
    {
    unsigned long flags;
    char *p;
    + size_t ret = 0;

    if (!spin_trylock_irqsave(&primary_crng.lock, flags))
    return 0;
    @@ -940,7 +942,7 @@ static int crng_fast_load(const char *cp, size_t len)
    p = (unsigned char *) &primary_crng.state[4];
    while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) {
    p[crng_init_cnt % CHACHA_KEY_SIZE] ^= *cp;
    - cp++; crng_init_cnt++; len--;
    + cp++; crng_init_cnt++; len--; ret++;
    }
    spin_unlock_irqrestore(&primary_crng.lock, flags);
    if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
    @@ -949,7 +951,7 @@ static int crng_fast_load(const char *cp, size_t len)
    wake_up_interruptible(&crng_init_wait);
    pr_notice("random: fast init done\n");
    }
    - return 1;
    + return ret;
    }

    /*
    @@ -1334,7 +1336,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
    if (unlikely(crng_init == 0)) {
    if ((fast_pool->count >= 64) &&
    crng_fast_load((char *) fast_pool->pool,
    - sizeof(fast_pool->pool))) {
    + sizeof(fast_pool->pool)) > 0) {
    fast_pool->count = 0;
    fast_pool->last = now;
    }
    @@ -2480,8 +2482,11 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
    struct entropy_store *poolp = &input_pool;

    if (unlikely(crng_init == 0)) {
    - crng_fast_load(buffer, count);
    - return;
    + size_t ret = crng_fast_load(buffer, count);
    + count -= ret;
    + buffer += ret;
    + if (!count || crng_init == 0)
    + return;
    }

    /* Suspend writing if we're above the trickle threshold.
    --
    2.34.1
    \
     
     \ /
      Last update: 2022-01-18 04:19    [W:4.246 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site