Re: [PATCH, RFC 03/12] random: Allow fractional bits to be tracked

2013-09-22 Thread H. Peter Anvin
On 09/22/2013 09:01 PM, Theodore Ts'o wrote:
> I've added the following changes to this patch since upon testing,
> there were some uses of r->entropy_count that were not properly
> converted from using fractional bits to bits.
> 

Thanks for catching that.

-hpa


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH, RFC 03/12] random: Allow fractional bits to be tracked

2013-09-22 Thread Theodore Ts'o
I've added the following changes to this patch since upon testing,
there were some uses of r->entropy_count that were not properly
converted from using fractional bits to bits.

- Ted

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 1547338..8654b7e 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -286,6 +286,7 @@
  * entropy_count, trickle_thresh
  */
 #define ENTROPY_SHIFT 3
+#define ENTROPY_BITS(r) ((r)->entropy_count >> ENTROPY_SHIFT)
 
 /*
  * The minimum number of bits of entropy before we wake up a read on
@@ -618,7 +619,8 @@ retry:
r->initialized = 1;
}
 
-   trace_credit_entropy_bits(r->name, nbits, entropy_count,
+   trace_credit_entropy_bits(r->name, nbits,
+ entropy_count >> ENTROPY_SHIFT,
  r->entropy_total, _RET_IP_);
 
/* should we wake readers? */
@@ -695,7 +697,7 @@ static void add_timer_randomness(struct timer_rand_state 
*state, unsigned num)
 
preempt_disable();
/* if over the trickle threshold, use only 1 in 4096 samples */
-   if (input_pool.entropy_count > trickle_thresh &&
+   if (ENTROPY_BITS(_pool) > trickle_thresh &&
((__this_cpu_inc_return(trickle_count) - 1) & 0xfff))
goto out;
 
@@ -999,7 +1001,7 @@ static ssize_t extract_entropy(struct entropy_store *r, 
void *buf,
r->last_data_init = true;
spin_unlock_irqrestore(>lock, flags);
trace_extract_entropy(r->name, EXTRACT_SIZE,
- r->entropy_count, _RET_IP_);
+ ENTROPY_BITS(r), _RET_IP_);
xfer_secondary_pool(r, EXTRACT_SIZE);
extract_buf(r, tmp);
spin_lock_irqsave(>lock, flags);
@@ -1008,7 +1010,7 @@ static ssize_t extract_entropy(struct entropy_store *r, 
void *buf,
spin_unlock_irqrestore(>lock, flags);
}
 
-   trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
+   trace_extract_entropy(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, min, reserved);
 
@@ -1041,7 +1043,7 @@ static ssize_t extract_entropy_user(struct entropy_store 
*r, void __user *buf,
ssize_t ret = 0, i;
__u8 tmp[EXTRACT_SIZE];
 
-   trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_);
+   trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, 0, 0);
 
@@ -1213,8 +1215,8 @@ random_read(struct file *file, char __user *buf, size_t 
nbytes, loff_t *ppos)
DEBUG_ENT("sleeping?\n");
 
wait_event_interruptible(random_read_wait,
-   input_pool.entropy_count >=
-random_read_wakeup_thresh);
+   ENTROPY_BITS(_pool) >=
+   random_read_wakeup_thresh);
 
DEBUG_ENT("awake\n");
 
@@ -1250,9 +1252,9 @@ random_poll(struct file *file, poll_table * wait)
poll_wait(file, _read_wait, wait);
poll_wait(file, _write_wait, wait);
mask = 0;
-   if (input_pool.entropy_count >= random_read_wakeup_thresh)
+   if (ENTROPY_BITS(_pool) >= random_read_wakeup_thresh)
mask |= POLLIN | POLLRDNORM;
-   if (input_pool.entropy_count < random_write_wakeup_thresh)
+   if (ENTROPY_BITS(_pool) < random_write_wakeup_thresh)
mask |= POLLOUT | POLLWRNORM;
return mask;
 }
@@ -1303,7 +1305,7 @@ static long random_ioctl(struct file *f, unsigned int 
cmd, unsigned long arg)
switch (cmd) {
case RNDGETENTCNT:
/* inherently racy, no point locking */
-   ent_count = input_pool.entropy_count >> ENTROPY_SHIFT;
+   ent_count = ENTROPY_BITS(_pool);
if (put_user(ent_count, p))
return -EFAULT;
return 0;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH, RFC 03/12] random: Allow fractional bits to be tracked

2013-09-22 Thread Theodore Ts'o
From: "H. Peter Anvin" 

Allow fractional bits of entropy to be tracked by scaling the entropy
counter (fixed point).  This will be used in a subsequent patch that
accounts for entropy lost due to overwrites.

Signed-off-by: H. Peter Anvin 
Cc: 
Signed-off-by: Theodore Ts'o 
---
 drivers/char/random.c | 118 ++
 1 file changed, 81 insertions(+), 37 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index e973658..1547338 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -280,6 +280,14 @@
 #define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
 
 /*
+ * To allow fractional bits to be tracked, the following fields contain
+ * this many fractional bits:
+ *
+ * entropy_count, trickle_thresh
+ */
+#define ENTROPY_SHIFT 3
+
+/*
  * The minimum number of bits of entropy before we wake up a read on
  * /dev/random.  Should be enough to do a significant reseed.
  */
@@ -296,8 +304,7 @@ static int random_write_wakeup_thresh = 128;
  * When the input pool goes over trickle_thresh, start dropping most
  * samples to avoid wasting CPU time and reduce lock contention.
  */
-
-static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28;
+static const int trickle_thresh = (INPUT_POOL_WORDS * 28) << ENTROPY_SHIFT;
 
 static DEFINE_PER_CPU(int, trickle_count);
 
@@ -311,8 +318,8 @@ static DEFINE_PER_CPU(int, trickle_count);
  */
 
 static struct poolinfo {
-   int poolbitshift, poolwords, poolbytes, poolbits;
-#define S(x) ilog2(x)+5, (x), (x)*4, (x)*32
+   int poolbitshift, poolwords, poolbytes, poolbits, poolfracbits;
+#define S(x) ilog2(x)+5, (x), (x)*4, (x)*32, (x) << (ENTROPY_SHIFT+5)
int tap1, tap2, tap3, tap4, tap5;
 } poolinfo_table[] = {
/* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
@@ -581,7 +588,9 @@ static void fast_mix(struct fast_pool *f, const void *in, 
int nbytes)
 }
 
 /*
- * Credit (or debit) the entropy store with n bits of entropy
+ * Credit (or debit) the entropy store with n bits of entropy.
+ * Use credit_entropy_bits_safe() if the value comes from userspace
+ * or otherwise should be checked for extreme values.
  */
 static void credit_entropy_bits(struct entropy_store *r, int nbits)
 {
@@ -593,13 +602,13 @@ static void credit_entropy_bits(struct entropy_store *r, 
int nbits)
DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
 retry:
entropy_count = orig = ACCESS_ONCE(r->entropy_count);
-   entropy_count += nbits;
+   entropy_count += nbits << ENTROPY_SHIFT;
 
if (entropy_count < 0) {
DEBUG_ENT("negative entropy/overflow\n");
entropy_count = 0;
-   } else if (entropy_count > r->poolinfo->poolbits)
-   entropy_count = r->poolinfo->poolbits;
+   } else if (entropy_count > r->poolinfo->poolfracbits)
+   entropy_count = r->poolinfo->poolfracbits;
if (cmpxchg(>entropy_count, orig, entropy_count) != orig)
goto retry;
 
@@ -613,12 +622,24 @@ retry:
  r->entropy_total, _RET_IP_);
 
/* should we wake readers? */
-   if (r == _pool && entropy_count >= random_read_wakeup_thresh) {
+   if (r == _pool &&
+   (entropy_count >> ENTROPY_SHIFT) >= random_read_wakeup_thresh) {
wake_up_interruptible(_read_wait);
kill_fasync(, SIGIO, POLL_IN);
}
 }
 
+static void credit_entropy_bits_safe(struct entropy_store *r, int nbits)
+{
+   const int nbits_max = (int)(~0U >> (ENTROPY_SHIFT + 1));
+
+   /* Cap the value to avoid overflows */
+   nbits = min(nbits,  nbits_max);
+   nbits = max(nbits, -nbits_max);
+
+   credit_entropy_bits(r, nbits);
+}
+
 /*
  *
  * Entropy input management
@@ -813,8 +834,9 @@ static void xfer_secondary_pool(struct entropy_store *r, 
size_t nbytes)
 {
__u32   tmp[OUTPUT_POOL_WORDS];
 
-   if (r->pull && r->entropy_count < nbytes * 8 &&
-   r->entropy_count < r->poolinfo->poolbits) {
+   if (r->pull &&
+   r->entropy_count < (nbytes << (ENTROPY_SHIFT + 3)) &&
+   r->entropy_count < r->poolinfo->poolfracbits) {
/* If we're limited, always leave two wakeup worth's BITS */
int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4;
int bytes = nbytes;
@@ -826,7 +848,8 @@ static void xfer_secondary_pool(struct entropy_store *r, 
size_t nbytes)
 
DEBUG_ENT("going to reseed %s with %d bits "
  "(%zu of %d requested)\n",
- r->name, bytes * 8, nbytes * 8, r->entropy_count);
+ r->name, bytes * 8, nbytes * 8,
+ r->entropy_count >> ENTROPY_SHIFT);
 
bytes = extract_entropy(r->pull, tmp, bytes,

[PATCH, RFC 03/12] random: Allow fractional bits to be tracked

2013-09-22 Thread Theodore Ts'o
From: H. Peter Anvin h...@zytor.com

Allow fractional bits of entropy to be tracked by scaling the entropy
counter (fixed point).  This will be used in a subsequent patch that
accounts for entropy lost due to overwrites.

Signed-off-by: H. Peter Anvin h...@linux.intel.com
Cc: sta...@vger.kernel.org
Signed-off-by: Theodore Ts'o ty...@mit.edu
---
 drivers/char/random.c | 118 ++
 1 file changed, 81 insertions(+), 37 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index e973658..1547338 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -280,6 +280,14 @@
 #define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
 
 /*
+ * To allow fractional bits to be tracked, the following fields contain
+ * this many fractional bits:
+ *
+ * entropy_count, trickle_thresh
+ */
+#define ENTROPY_SHIFT 3
+
+/*
  * The minimum number of bits of entropy before we wake up a read on
  * /dev/random.  Should be enough to do a significant reseed.
  */
@@ -296,8 +304,7 @@ static int random_write_wakeup_thresh = 128;
  * When the input pool goes over trickle_thresh, start dropping most
  * samples to avoid wasting CPU time and reduce lock contention.
  */
-
-static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28;
+static const int trickle_thresh = (INPUT_POOL_WORDS * 28)  ENTROPY_SHIFT;
 
 static DEFINE_PER_CPU(int, trickle_count);
 
@@ -311,8 +318,8 @@ static DEFINE_PER_CPU(int, trickle_count);
  */
 
 static struct poolinfo {
-   int poolbitshift, poolwords, poolbytes, poolbits;
-#define S(x) ilog2(x)+5, (x), (x)*4, (x)*32
+   int poolbitshift, poolwords, poolbytes, poolbits, poolfracbits;
+#define S(x) ilog2(x)+5, (x), (x)*4, (x)*32, (x)  (ENTROPY_SHIFT+5)
int tap1, tap2, tap3, tap4, tap5;
 } poolinfo_table[] = {
/* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
@@ -581,7 +588,9 @@ static void fast_mix(struct fast_pool *f, const void *in, 
int nbytes)
 }
 
 /*
- * Credit (or debit) the entropy store with n bits of entropy
+ * Credit (or debit) the entropy store with n bits of entropy.
+ * Use credit_entropy_bits_safe() if the value comes from userspace
+ * or otherwise should be checked for extreme values.
  */
 static void credit_entropy_bits(struct entropy_store *r, int nbits)
 {
@@ -593,13 +602,13 @@ static void credit_entropy_bits(struct entropy_store *r, 
int nbits)
DEBUG_ENT(added %d entropy credits to %s\n, nbits, r-name);
 retry:
entropy_count = orig = ACCESS_ONCE(r-entropy_count);
-   entropy_count += nbits;
+   entropy_count += nbits  ENTROPY_SHIFT;
 
if (entropy_count  0) {
DEBUG_ENT(negative entropy/overflow\n);
entropy_count = 0;
-   } else if (entropy_count  r-poolinfo-poolbits)
-   entropy_count = r-poolinfo-poolbits;
+   } else if (entropy_count  r-poolinfo-poolfracbits)
+   entropy_count = r-poolinfo-poolfracbits;
if (cmpxchg(r-entropy_count, orig, entropy_count) != orig)
goto retry;
 
@@ -613,12 +622,24 @@ retry:
  r-entropy_total, _RET_IP_);
 
/* should we wake readers? */
-   if (r == input_pool  entropy_count = random_read_wakeup_thresh) {
+   if (r == input_pool 
+   (entropy_count  ENTROPY_SHIFT) = random_read_wakeup_thresh) {
wake_up_interruptible(random_read_wait);
kill_fasync(fasync, SIGIO, POLL_IN);
}
 }
 
+static void credit_entropy_bits_safe(struct entropy_store *r, int nbits)
+{
+   const int nbits_max = (int)(~0U  (ENTROPY_SHIFT + 1));
+
+   /* Cap the value to avoid overflows */
+   nbits = min(nbits,  nbits_max);
+   nbits = max(nbits, -nbits_max);
+
+   credit_entropy_bits(r, nbits);
+}
+
 /*
  *
  * Entropy input management
@@ -813,8 +834,9 @@ static void xfer_secondary_pool(struct entropy_store *r, 
size_t nbytes)
 {
__u32   tmp[OUTPUT_POOL_WORDS];
 
-   if (r-pull  r-entropy_count  nbytes * 8 
-   r-entropy_count  r-poolinfo-poolbits) {
+   if (r-pull 
+   r-entropy_count  (nbytes  (ENTROPY_SHIFT + 3)) 
+   r-entropy_count  r-poolinfo-poolfracbits) {
/* If we're limited, always leave two wakeup worth's BITS */
int rsvd = r-limit ? 0 : random_read_wakeup_thresh/4;
int bytes = nbytes;
@@ -826,7 +848,8 @@ static void xfer_secondary_pool(struct entropy_store *r, 
size_t nbytes)
 
DEBUG_ENT(going to reseed %s with %d bits 
  (%zu of %d requested)\n,
- r-name, bytes * 8, nbytes * 8, r-entropy_count);
+ r-name, bytes * 8, nbytes * 8,
+ r-entropy_count  ENTROPY_SHIFT);
 
bytes = extract_entropy(r-pull, tmp, bytes,

Re: [PATCH, RFC 03/12] random: Allow fractional bits to be tracked

2013-09-22 Thread Theodore Ts'o
I've added the following changes to this patch since upon testing,
there were some uses of r-entropy_count that were not properly
converted from using fractional bits to bits.

- Ted

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 1547338..8654b7e 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -286,6 +286,7 @@
  * entropy_count, trickle_thresh
  */
 #define ENTROPY_SHIFT 3
+#define ENTROPY_BITS(r) ((r)-entropy_count  ENTROPY_SHIFT)
 
 /*
  * The minimum number of bits of entropy before we wake up a read on
@@ -618,7 +619,8 @@ retry:
r-initialized = 1;
}
 
-   trace_credit_entropy_bits(r-name, nbits, entropy_count,
+   trace_credit_entropy_bits(r-name, nbits,
+ entropy_count  ENTROPY_SHIFT,
  r-entropy_total, _RET_IP_);
 
/* should we wake readers? */
@@ -695,7 +697,7 @@ static void add_timer_randomness(struct timer_rand_state 
*state, unsigned num)
 
preempt_disable();
/* if over the trickle threshold, use only 1 in 4096 samples */
-   if (input_pool.entropy_count  trickle_thresh 
+   if (ENTROPY_BITS(input_pool)  trickle_thresh 
((__this_cpu_inc_return(trickle_count) - 1)  0xfff))
goto out;
 
@@ -999,7 +1001,7 @@ static ssize_t extract_entropy(struct entropy_store *r, 
void *buf,
r-last_data_init = true;
spin_unlock_irqrestore(r-lock, flags);
trace_extract_entropy(r-name, EXTRACT_SIZE,
- r-entropy_count, _RET_IP_);
+ ENTROPY_BITS(r), _RET_IP_);
xfer_secondary_pool(r, EXTRACT_SIZE);
extract_buf(r, tmp);
spin_lock_irqsave(r-lock, flags);
@@ -1008,7 +1010,7 @@ static ssize_t extract_entropy(struct entropy_store *r, 
void *buf,
spin_unlock_irqrestore(r-lock, flags);
}
 
-   trace_extract_entropy(r-name, nbytes, r-entropy_count, _RET_IP_);
+   trace_extract_entropy(r-name, nbytes, ENTROPY_BITS(r), _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, min, reserved);
 
@@ -1041,7 +1043,7 @@ static ssize_t extract_entropy_user(struct entropy_store 
*r, void __user *buf,
ssize_t ret = 0, i;
__u8 tmp[EXTRACT_SIZE];
 
-   trace_extract_entropy_user(r-name, nbytes, r-entropy_count, _RET_IP_);
+   trace_extract_entropy_user(r-name, nbytes, ENTROPY_BITS(r), _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, 0, 0);
 
@@ -1213,8 +1215,8 @@ random_read(struct file *file, char __user *buf, size_t 
nbytes, loff_t *ppos)
DEBUG_ENT(sleeping?\n);
 
wait_event_interruptible(random_read_wait,
-   input_pool.entropy_count =
-random_read_wakeup_thresh);
+   ENTROPY_BITS(input_pool) =
+   random_read_wakeup_thresh);
 
DEBUG_ENT(awake\n);
 
@@ -1250,9 +1252,9 @@ random_poll(struct file *file, poll_table * wait)
poll_wait(file, random_read_wait, wait);
poll_wait(file, random_write_wait, wait);
mask = 0;
-   if (input_pool.entropy_count = random_read_wakeup_thresh)
+   if (ENTROPY_BITS(input_pool) = random_read_wakeup_thresh)
mask |= POLLIN | POLLRDNORM;
-   if (input_pool.entropy_count  random_write_wakeup_thresh)
+   if (ENTROPY_BITS(input_pool)  random_write_wakeup_thresh)
mask |= POLLOUT | POLLWRNORM;
return mask;
 }
@@ -1303,7 +1305,7 @@ static long random_ioctl(struct file *f, unsigned int 
cmd, unsigned long arg)
switch (cmd) {
case RNDGETENTCNT:
/* inherently racy, no point locking */
-   ent_count = input_pool.entropy_count  ENTROPY_SHIFT;
+   ent_count = ENTROPY_BITS(input_pool);
if (put_user(ent_count, p))
return -EFAULT;
return 0;
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH, RFC 03/12] random: Allow fractional bits to be tracked

2013-09-22 Thread H. Peter Anvin
On 09/22/2013 09:01 PM, Theodore Ts'o wrote:
 I've added the following changes to this patch since upon testing,
 there were some uses of r-entropy_count that were not properly
 converted from using fractional bits to bits.
 

Thanks for catching that.

-hpa


--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/