linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] random: use proper cycle_t type for random_get_entropy()
@ 2022-02-24 17:39 Jason A. Donenfeld
  2022-02-24 21:30 ` [PATCH v2] random: unify cycles_t and jiffies usage and types Jason A. Donenfeld
  0 siblings, 1 reply; 6+ messages in thread
From: Jason A. Donenfeld @ 2022-02-24 17:39 UTC (permalink / raw)
  To: linux-kernel; +Cc: Jason A. Donenfeld, Theodore Ts'o, Dominik Brodowski

random_get_entropy() returns a cycles_t, not an unsigned long, which is
sometimes 64 bits on various 32-bit platforms, including x86.
Conversely, jiffies is always unsigned long. This commit fixes things to
use cycles_t for fields that use random_get_entropy() and unsigned long
for fields that use jiffies.

Cc: Theodore Ts'o <tytso@mit.edu>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
 drivers/char/random.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 19bf44b9ba0f..4e37b8e2acc1 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1002,7 +1002,7 @@ int __init rand_initialize(void)
 
 /* There is one of these per entropy source */
 struct timer_rand_state {
-	cycles_t last_time;
+	unsigned long last_time;
 	long last_delta, last_delta2;
 };
 
@@ -1016,7 +1016,7 @@ struct timer_rand_state {
  */
 void add_device_randomness(const void *buf, size_t size)
 {
-	unsigned long time = random_get_entropy() ^ jiffies;
+	cycles_t time = random_get_entropy() ^ jiffies;
 	unsigned long flags;
 
 	if (crng_init == 0 && size)
@@ -1042,8 +1042,8 @@ EXPORT_SYMBOL(add_device_randomness);
 static void add_timer_randomness(struct timer_rand_state *state, unsigned int num)
 {
 	struct {
+		cycles_t cycles;
 		long jiffies;
-		unsigned int cycles;
 		unsigned int num;
 	} sample;
 	long delta, delta2, delta3;
@@ -1356,7 +1356,7 @@ static void entropy_timer(struct timer_list *t)
 static void try_to_generate_entropy(void)
 {
 	struct {
-		unsigned long now;
+		cycles_t now;
 		struct timer_list timer;
 	} stack;
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2] random: unify cycles_t and jiffies usage and types
  2022-02-24 17:39 [PATCH] random: use proper cycle_t type for random_get_entropy() Jason A. Donenfeld
@ 2022-02-24 21:30 ` Jason A. Donenfeld
  2022-02-25  6:58   ` Dominik Brodowski
  0 siblings, 1 reply; 6+ messages in thread
From: Jason A. Donenfeld @ 2022-02-24 21:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: Jason A. Donenfeld, Theodore Ts'o, Dominik Brodowski

random_get_entropy() returns a cycles_t, not an unsigned long, which is
sometimes 64 bits on various 32-bit platforms, including x86.
Conversely, jiffies is always unsigned long. This commit fixes things to
use cycles_t for fields that use random_get_entropy() and unsigned long
for fields that use jiffies. It's also good to mix in a cycles_t and a
jiffies in the same way for both add_device_randomness and
add_timer_randomness, rather than using xor in one case. Finally, we
unify the order of these volatile reads, always reading the more precise
cycles counter, and then jiffies, so that the cycle counter is as close
to the event as possible.

Cc: Theodore Ts'o <tytso@mit.edu>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
Changes v1->v2:
- [Dominik] Use unsigned long, not long, for jiffies, except when it
  represents a delta.
- Also unify how jiffies and cycles combine, where they're used, and the
  order in which they're read.
- Stylistic fixes.

 drivers/char/random.c | 46 +++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 19bf44b9ba0f..12a1b2cfd702 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1000,12 +1000,6 @@ int __init rand_initialize(void)
 	return 0;
 }
 
-/* There is one of these per entropy source */
-struct timer_rand_state {
-	cycles_t last_time;
-	long last_delta, last_delta2;
-};
-
 /*
  * Add device- or boot-specific data to the input pool to help
  * initialize it.
@@ -1016,19 +1010,26 @@ struct timer_rand_state {
  */
 void add_device_randomness(const void *buf, size_t size)
 {
-	unsigned long time = random_get_entropy() ^ jiffies;
-	unsigned long flags;
+	cycles_t cycles = random_get_entropy();
+	unsigned long now = jiffies, flags;
 
 	if (crng_init == 0 && size)
 		crng_pre_init_inject(buf, size, false);
 
 	spin_lock_irqsave(&input_pool.lock, flags);
+	_mix_pool_bytes(&cycles, sizeof(cycles));
+	_mix_pool_bytes(&now, sizeof(now));
 	_mix_pool_bytes(buf, size);
-	_mix_pool_bytes(&time, sizeof(time));
 	spin_unlock_irqrestore(&input_pool.lock, flags);
 }
 EXPORT_SYMBOL(add_device_randomness);
 
+/* There is one of these per entropy source */
+struct timer_rand_state {
+	unsigned long last_time;
+	long last_delta, last_delta2;
+};
+
 /*
  * This function adds entropy to the entropy "pool" by using timing
  * delays.  It uses the timer_rand_state structure to make an estimate
@@ -1037,29 +1038,26 @@ EXPORT_SYMBOL(add_device_randomness);
  * The number "num" is also added to the pool - it should somehow describe
  * the type of event which just happened.  This is currently 0-255 for
  * keyboard scan codes, and 256 upwards for interrupts.
- *
  */
 static void add_timer_randomness(struct timer_rand_state *state, unsigned int num)
 {
-	struct {
-		long jiffies;
-		unsigned int cycles;
-		unsigned int num;
-	} sample;
+	cycles_t cycles = random_get_entropy();
+	unsigned long now = jiffies, flags;
 	long delta, delta2, delta3;
 
-	sample.jiffies = jiffies;
-	sample.cycles = random_get_entropy();
-	sample.num = num;
-	mix_pool_bytes(&sample, sizeof(sample));
+	spin_lock_irqsave(&input_pool.lock, flags);
+	_mix_pool_bytes(&cycles, sizeof(cycles));
+	_mix_pool_bytes(&now, sizeof(now));
+	_mix_pool_bytes(&num, sizeof(num));
+	spin_unlock_irqrestore(&input_pool.lock, flags);
 
 	/*
 	 * Calculate number of bits of randomness we probably added.
 	 * We take into account the first, second and third-order deltas
 	 * in order to make our estimate.
 	 */
-	delta = sample.jiffies - READ_ONCE(state->last_time);
-	WRITE_ONCE(state->last_time, sample.jiffies);
+	delta = now - READ_ONCE(state->last_time);
+	WRITE_ONCE(state->last_time, now);
 
 	delta2 = delta - READ_ONCE(state->last_delta);
 	WRITE_ONCE(state->last_delta, delta);
@@ -1291,10 +1289,10 @@ static void mix_interrupt_randomness(struct work_struct *work)
 void add_interrupt_randomness(int irq)
 {
 	enum { MIX_INFLIGHT = 1U << 31 };
+	cycles_t cycles = random_get_entropy();
+	unsigned long now = jiffies;
 	struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
 	struct pt_regs *regs = get_irq_regs();
-	unsigned long now = jiffies;
-	cycles_t cycles = random_get_entropy();
 	unsigned int new_count;
 
 	if (cycles == 0)
@@ -1356,7 +1354,7 @@ static void entropy_timer(struct timer_list *t)
 static void try_to_generate_entropy(void)
 {
 	struct {
-		unsigned long now;
+		cycles_t now;
 		struct timer_list timer;
 	} stack;
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] random: unify cycles_t and jiffies usage and types
  2022-02-24 21:30 ` [PATCH v2] random: unify cycles_t and jiffies usage and types Jason A. Donenfeld
@ 2022-02-25  6:58   ` Dominik Brodowski
  2022-02-25 13:39     ` Jason A. Donenfeld
  0 siblings, 1 reply; 6+ messages in thread
From: Dominik Brodowski @ 2022-02-25  6:58 UTC (permalink / raw)
  To: Jason A. Donenfeld; +Cc: linux-kernel, Theodore Ts'o

Am Thu, Feb 24, 2022 at 10:30:30PM +0100 schrieb Jason A. Donenfeld:
> @@ -1016,19 +1010,26 @@ struct timer_rand_state {
>   */
>  void add_device_randomness(const void *buf, size_t size)
>  {
> -	unsigned long time = random_get_entropy() ^ jiffies;
> -	unsigned long flags;
> +	cycles_t cycles = random_get_entropy();
> +	unsigned long now = jiffies, flags;

maybe "flags, now = jiffies" is a bit more reader-friendly?

>  static void add_timer_randomness(struct timer_rand_state *state, unsigned int num)
>  {
> -	struct {
> -		long jiffies;
> -		unsigned int cycles;
> -		unsigned int num;
> -	} sample;
> +	cycles_t cycles = random_get_entropy();
> +	unsigned long now = jiffies, flags;

Same here.

> @@ -1291,10 +1289,10 @@ static void mix_interrupt_randomness(struct work_struct *work)
>  void add_interrupt_randomness(int irq)
>  {
>  	enum { MIX_INFLIGHT = 1U << 31 };
> +	cycles_t cycles = random_get_entropy();
> +	unsigned long now = jiffies;
>  	struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
>  	struct pt_regs *regs = get_irq_regs();
> -	unsigned long now = jiffies;
> -	cycles_t cycles = random_get_entropy();
>  	unsigned int new_count;
>  
>  	if (cycles == 0)


Why do you change the ordering here?

Thanks,
	Dominik

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] random: unify cycles_t and jiffies usage and types
  2022-02-25  6:58   ` Dominik Brodowski
@ 2022-02-25 13:39     ` Jason A. Donenfeld
  2022-02-25 13:44       ` [PATCH v3] " Jason A. Donenfeld
  0 siblings, 1 reply; 6+ messages in thread
From: Jason A. Donenfeld @ 2022-02-25 13:39 UTC (permalink / raw)
  To: Dominik Brodowski; +Cc: LKML, Theodore Ts'o

On Fri, Feb 25, 2022 at 8:06 AM Dominik Brodowski
<linux@dominikbrodowski.net> wrote:
> maybe "flags, now = jiffies" is a bit more reader-friendly?

Good idea. Will do.

> >       enum { MIX_INFLIGHT = 1U << 31 };
> > +     cycles_t cycles = random_get_entropy();
> > +     unsigned long now = jiffies;
> >       struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
> >       struct pt_regs *regs = get_irq_regs();
> > -     unsigned long now = jiffies;
> > -     cycles_t cycles = random_get_entropy();
> >       unsigned int new_count;
> >
> >       if (cycles == 0)
>
>
> Why do you change the ordering here?

So that get_cycles() is called as closest to the actual interrupt as
possible, and so that we retain the order as elsewhere of reading
cycles before jiffies.

v+1 on its way.

Jason

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v3] random: unify cycles_t and jiffies usage and types
  2022-02-25 13:39     ` Jason A. Donenfeld
@ 2022-02-25 13:44       ` Jason A. Donenfeld
  2022-02-25 14:16         ` Dominik Brodowski
  0 siblings, 1 reply; 6+ messages in thread
From: Jason A. Donenfeld @ 2022-02-25 13:44 UTC (permalink / raw)
  To: linux-kernel; +Cc: Jason A. Donenfeld, Theodore Ts'o, Dominik Brodowski

random_get_entropy() returns a cycles_t, not an unsigned long, which is
sometimes 64 bits on various 32-bit platforms, including x86.
Conversely, jiffies is always unsigned long. This commit fixes things to
use cycles_t for fields that use random_get_entropy(), named "cycles",
and unsigned long for fields that use jiffies, named "now". It's also
good to mix in a cycles_t and a jiffies in the same way for both
add_device_randomness and add_timer_randomness, rather than using xor in
one case. Finally, we unify the order of these volatile reads, always
reading the more precise cycles counter, and then jiffies, so that the
cycle counter is as close to the event as possible.

Cc: Theodore Ts'o <tytso@mit.edu>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
 drivers/char/random.c | 56 +++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 29 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 1aeaad4e3c9c..d9321b9bd3e3 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1005,12 +1005,6 @@ int __init rand_initialize(void)
 	return 0;
 }
 
-/* There is one of these per entropy source */
-struct timer_rand_state {
-	cycles_t last_time;
-	long last_delta, last_delta2;
-};
-
 /*
  * Add device- or boot-specific data to the input pool to help
  * initialize it.
@@ -1021,19 +1015,26 @@ struct timer_rand_state {
  */
 void add_device_randomness(const void *buf, size_t size)
 {
-	unsigned long time = random_get_entropy() ^ jiffies;
-	unsigned long flags;
+	cycles_t cycles = random_get_entropy();
+	unsigned long flags, now = jiffies;
 
 	if (crng_init == 0 && size)
 		crng_pre_init_inject(buf, size, false);
 
 	spin_lock_irqsave(&input_pool.lock, flags);
+	_mix_pool_bytes(&cycles, sizeof(cycles));
+	_mix_pool_bytes(&now, sizeof(now));
 	_mix_pool_bytes(buf, size);
-	_mix_pool_bytes(&time, sizeof(time));
 	spin_unlock_irqrestore(&input_pool.lock, flags);
 }
 EXPORT_SYMBOL(add_device_randomness);
 
+/* There is one of these per entropy source */
+struct timer_rand_state {
+	unsigned long last_time;
+	long last_delta, last_delta2;
+};
+
 /*
  * This function adds entropy to the entropy "pool" by using timing
  * delays.  It uses the timer_rand_state structure to make an estimate
@@ -1042,29 +1043,26 @@ EXPORT_SYMBOL(add_device_randomness);
  * The number "num" is also added to the pool - it should somehow describe
  * the type of event which just happened.  This is currently 0-255 for
  * keyboard scan codes, and 256 upwards for interrupts.
- *
  */
 static void add_timer_randomness(struct timer_rand_state *state, unsigned int num)
 {
-	struct {
-		long jiffies;
-		unsigned int cycles;
-		unsigned int num;
-	} sample;
+	cycles_t cycles = random_get_entropy();
+	unsigned long flags, now = jiffies;
 	long delta, delta2, delta3;
 
-	sample.jiffies = jiffies;
-	sample.cycles = random_get_entropy();
-	sample.num = num;
-	mix_pool_bytes(&sample, sizeof(sample));
+	spin_lock_irqsave(&input_pool.lock, flags);
+	_mix_pool_bytes(&cycles, sizeof(cycles));
+	_mix_pool_bytes(&now, sizeof(now));
+	_mix_pool_bytes(&num, sizeof(num));
+	spin_unlock_irqrestore(&input_pool.lock, flags);
 
 	/*
 	 * Calculate number of bits of randomness we probably added.
 	 * We take into account the first, second and third-order deltas
 	 * in order to make our estimate.
 	 */
-	delta = sample.jiffies - READ_ONCE(state->last_time);
-	WRITE_ONCE(state->last_time, sample.jiffies);
+	delta = now - READ_ONCE(state->last_time);
+	WRITE_ONCE(state->last_time, now);
 
 	delta2 = delta - READ_ONCE(state->last_delta);
 	WRITE_ONCE(state->last_delta, delta);
@@ -1311,10 +1309,10 @@ static void mix_interrupt_randomness(struct work_struct *work)
 void add_interrupt_randomness(int irq)
 {
 	enum { MIX_INFLIGHT = 1U << 31 };
+	cycles_t cycles = random_get_entropy();
+	unsigned long now = jiffies;
 	struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
 	struct pt_regs *regs = get_irq_regs();
-	unsigned long now = jiffies;
-	cycles_t cycles = random_get_entropy();
 	unsigned int new_count;
 
 	if (cycles == 0)
@@ -1376,28 +1374,28 @@ static void entropy_timer(struct timer_list *t)
 static void try_to_generate_entropy(void)
 {
 	struct {
-		unsigned long now;
+		cycles_t cycles;
 		struct timer_list timer;
 	} stack;
 
-	stack.now = random_get_entropy();
+	stack.cycles = random_get_entropy();
 
 	/* Slow counter - or none. Don't even bother */
-	if (stack.now == random_get_entropy())
+	if (stack.cycles == random_get_entropy())
 		return;
 
 	timer_setup_on_stack(&stack.timer, entropy_timer, 0);
 	while (!crng_ready()) {
 		if (!timer_pending(&stack.timer))
 			mod_timer(&stack.timer, jiffies + 1);
-		mix_pool_bytes(&stack.now, sizeof(stack.now));
+		mix_pool_bytes(&stack.cycles, sizeof(stack.cycles));
 		schedule();
-		stack.now = random_get_entropy();
+		stack.cycles = random_get_entropy();
 	}
 
 	del_timer_sync(&stack.timer);
 	destroy_timer_on_stack(&stack.timer);
-	mix_pool_bytes(&stack.now, sizeof(stack.now));
+	mix_pool_bytes(&stack.cycles, sizeof(stack.cycles));
 }
 
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v3] random: unify cycles_t and jiffies usage and types
  2022-02-25 13:44       ` [PATCH v3] " Jason A. Donenfeld
@ 2022-02-25 14:16         ` Dominik Brodowski
  0 siblings, 0 replies; 6+ messages in thread
From: Dominik Brodowski @ 2022-02-25 14:16 UTC (permalink / raw)
  To: Jason A. Donenfeld; +Cc: linux-kernel, Theodore Ts'o

Am Fri, Feb 25, 2022 at 02:44:08PM +0100 schrieb Jason A. Donenfeld:
> random_get_entropy() returns a cycles_t, not an unsigned long, which is
> sometimes 64 bits on various 32-bit platforms, including x86.
> Conversely, jiffies is always unsigned long. This commit fixes things to
> use cycles_t for fields that use random_get_entropy(), named "cycles",
> and unsigned long for fields that use jiffies, named "now". It's also
> good to mix in a cycles_t and a jiffies in the same way for both
> add_device_randomness and add_timer_randomness, rather than using xor in
> one case. Finally, we unify the order of these volatile reads, always
> reading the more precise cycles counter, and then jiffies, so that the
> cycle counter is as close to the event as possible.
> 
> Cc: Theodore Ts'o <tytso@mit.edu>
> Cc: Dominik Brodowski <linux@dominikbrodowski.net>
> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>

	Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>

Thanks,
	Dominik

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-02-25 14:16 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-24 17:39 [PATCH] random: use proper cycle_t type for random_get_entropy() Jason A. Donenfeld
2022-02-24 21:30 ` [PATCH v2] random: unify cycles_t and jiffies usage and types Jason A. Donenfeld
2022-02-25  6:58   ` Dominik Brodowski
2022-02-25 13:39     ` Jason A. Donenfeld
2022-02-25 13:44       ` [PATCH v3] " Jason A. Donenfeld
2022-02-25 14:16         ` Dominik Brodowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).