Commit f0fb6953 authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Herbert Xu

hwrng: core - use per-rng quality value instead of global setting

The current_quality variable exposed as a module parameter is
fundamentally broken: If it is set at boot time, it is overwritten once
the first hw rng device is loaded; if it is set at runtime, it is
without effect if the hw rng device had its quality value set to 0 (and
no default_quality was set); and if a new rng is selected, it gets
overwritten. Therefore, mark it as obsolete, and replace it by the
per-rng quality setting.

Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 077bb7a1
...@@ -44,14 +44,14 @@ static unsigned short default_quality; /* = 0; default to "off" */ ...@@ -44,14 +44,14 @@ static unsigned short default_quality; /* = 0; default to "off" */
module_param(current_quality, ushort, 0644); module_param(current_quality, ushort, 0644);
MODULE_PARM_DESC(current_quality, MODULE_PARM_DESC(current_quality,
"current hwrng entropy estimation per 1024 bits of input"); "current hwrng entropy estimation per 1024 bits of input -- obsolete");
module_param(default_quality, ushort, 0644); module_param(default_quality, ushort, 0644);
MODULE_PARM_DESC(default_quality, MODULE_PARM_DESC(default_quality,
"default entropy content of hwrng per 1024 bits of input"); "default entropy content of hwrng per 1024 bits of input");
static void drop_current_rng(void); static void drop_current_rng(void);
static int hwrng_init(struct hwrng *rng); static int hwrng_init(struct hwrng *rng);
static void hwrng_manage_rngd(void); static void hwrng_manage_rngd(struct hwrng *rng);
static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size, static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
int wait); int wait);
...@@ -160,11 +160,13 @@ static int hwrng_init(struct hwrng *rng) ...@@ -160,11 +160,13 @@ static int hwrng_init(struct hwrng *rng)
reinit_completion(&rng->cleanup_done); reinit_completion(&rng->cleanup_done);
skip_init: skip_init:
current_quality = rng->quality ? : default_quality; if (!rng->quality)
if (current_quality > 1024) rng->quality = default_quality;
current_quality = 1024; if (rng->quality > 1024)
rng->quality = 1024;
current_quality = rng->quality; /* obsolete */
hwrng_manage_rngd(); hwrng_manage_rngd(rng);
return 0; return 0;
} }
...@@ -429,19 +431,24 @@ static int hwrng_fillfn(void *unused) ...@@ -429,19 +431,24 @@ static int hwrng_fillfn(void *unused)
long rc; long rc;
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
unsigned short quality;
struct hwrng *rng; struct hwrng *rng;
if (!current_quality)
break;
rng = get_current_rng(); rng = get_current_rng();
if (IS_ERR(rng) || !rng) if (IS_ERR(rng) || !rng)
break; break;
mutex_lock(&reading_mutex); mutex_lock(&reading_mutex);
rc = rng_get_data(rng, rng_fillbuf, rc = rng_get_data(rng, rng_fillbuf,
rng_buffer_size(), 1); rng_buffer_size(), 1);
if (current_quality != rng->quality)
rng->quality = current_quality; /* obsolete */
quality = rng->quality;
mutex_unlock(&reading_mutex); mutex_unlock(&reading_mutex);
put_rng(rng); put_rng(rng);
if (!quality)
break;
if (rc <= 0) { if (rc <= 0) {
pr_warn("hwrng: no data available\n"); pr_warn("hwrng: no data available\n");
msleep_interruptible(10000); msleep_interruptible(10000);
...@@ -451,7 +458,7 @@ static int hwrng_fillfn(void *unused) ...@@ -451,7 +458,7 @@ static int hwrng_fillfn(void *unused)
/* If we cannot credit at least one bit of entropy, /* If we cannot credit at least one bit of entropy,
* keep track of the remainder for the next iteration * keep track of the remainder for the next iteration
*/ */
entropy = rc * current_quality * 8 + entropy_credit; entropy = rc * quality * 8 + entropy_credit;
if ((entropy >> 10) == 0) if ((entropy >> 10) == 0)
entropy_credit = entropy; entropy_credit = entropy;
...@@ -463,14 +470,14 @@ static int hwrng_fillfn(void *unused) ...@@ -463,14 +470,14 @@ static int hwrng_fillfn(void *unused)
return 0; return 0;
} }
static void hwrng_manage_rngd(void) static void hwrng_manage_rngd(struct hwrng *rng)
{ {
if (WARN_ON(!mutex_is_locked(&rng_mutex))) if (WARN_ON(!mutex_is_locked(&rng_mutex)))
return; return;
if (current_quality == 0 && hwrng_fill) if (rng->quality == 0 && hwrng_fill)
kthread_stop(hwrng_fill); kthread_stop(hwrng_fill);
if (current_quality > 0 && !hwrng_fill) { if (rng->quality > 0 && !hwrng_fill) {
hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng"); hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng");
if (IS_ERR(hwrng_fill)) { if (IS_ERR(hwrng_fill)) {
pr_err("hwrng_fill thread creation failed\n"); pr_err("hwrng_fill thread creation failed\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment