Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 3046

kernel-2.6.18-238.el5.src.rpm

From: Jiri Pirko <jpirko@redhat.com>
Date: Wed, 27 Aug 2008 18:17:13 +0200
Subject: [net] random32: seeding improvement
Message-id: 20080827181713.0cb2cacf@psychotron.englab.brq.redhat.com
O-Subject: [RHEL5.3 patch] BZ458019 kernel: random32: seeding improvement [rhel-5.3]
Bugzilla: 458019
RH-Acked-by: David Miller <davem@redhat.com>
RH-Acked-by: Eugene Teo <eteo@redhat.com>

BZ458019

Description:
Stephen Hemminger wrote a patch to improve random32() seeding.

The rationale is:
   * use u32 consistently
   * no need to do LCG on values from (better) get_random_bytes
   * use more data from get_random_bytes for secondary seeding
   * don't reduce state space on srandom32()
   * enforce state variable initialization restrictions

Also changed function net_srandom() to let it update the state of all CPUs.
The network stack goes into pains to feed the current IP addresses in,
but it is not very effective if that is only done for some random CPU
instead of all. So it's changed to feed bits into all CPUs. Decided to do
that lockless because well somewhat random results are ok.

Upstream status:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=697f8d0348a652593d195a13dd1067d9df911a82
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=61407f80f72970d52d4339f81c6c3cd03f4ca0f0

Brew build:
https://brewweb.devel.redhat.com/taskinfo?taskID=1441605

Test status:
Booted on x86_64.

Jirka

diff --git a/net/core/utils.c b/net/core/utils.c
index e31c90e..4ca43fb 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -80,23 +80,12 @@ static u32 __net_random(struct nrnd_state *state)
 	return (state->s1 ^ state->s2 ^ state->s3);
 }
 
-static void __net_srandom(struct nrnd_state *state, unsigned long s)
+/*
+ * Handle minimum values for seeds
+ */
+static inline u32 __seed(u32 x, u32 m)
 {
-	if (s == 0)
-		s = 1;      /* default seed is 1 */
-
-#define LCG(n) (69069 * n)
-	state->s1 = LCG(s);
-	state->s2 = LCG(state->s1);
-	state->s3 = LCG(state->s2);
-
-	/* "warm it up" */
-	__net_random(state);
-	__net_random(state);
-	__net_random(state);
-	__net_random(state);
-	__net_random(state);
-	__net_random(state);
+	return (x < m) ? x + m : x;
 }
 
 
@@ -112,9 +101,15 @@ unsigned long net_random(void)
 
 void net_srandom(unsigned long entropy)
 {
-	struct nrnd_state *state = &get_cpu_var(net_rand_state);
-	__net_srandom(state, state->s1^entropy);
-	put_cpu_var(state);
+	int i;
+	/*
+	 * No locking on the CPUs, but then somewhat random results are, well,
+	 * expected.
+	 */
+	for_each_possible_cpu (i) {
+		struct nrnd_state *state = &per_cpu(net_rand_state, i);
+		state->s1 = __seed(state->s1 ^ entropy, 1);
+	}
 }
 
 void __init net_random_init(void)
@@ -123,20 +118,37 @@ void __init net_random_init(void)
 
 	for_each_possible_cpu(i) {
 		struct nrnd_state *state = &per_cpu(net_rand_state,i);
-		__net_srandom(state, i+jiffies);
+
+#define LCG(x) ((x) * 69069)   /* super-duper LCG */
+		state->s1 = __seed(LCG(i + jiffies), 1);
+		state->s2 = __seed(LCG(state->s1), 7);
+		state->s3 = __seed(LCG(state->s2), 15);
+
+		/* "warm it up" */
+		__net_random(state);
+		__net_random(state);
+		__net_random(state);
+		__net_random(state);
+		__net_random(state);
+		__net_random(state);
 	}
 }
 
 static int net_random_reseed(void)
 {
 	int i;
-	unsigned long seed;
 
 	for_each_possible_cpu(i) {
 		struct nrnd_state *state = &per_cpu(net_rand_state,i);
+		u32 seeds[3];
+
+		get_random_bytes(&seeds, sizeof(seeds));
+		state->s1 = __seed(seeds[0], 1);
+		state->s2 = __seed(seeds[1], 7);
+		state->s3 = __seed(seeds[2], 15);
 
-		get_random_bytes(&seed, sizeof(seed));
-		__net_srandom(state, seed);
+		/* mix it in */
+		__net_random(state);
 	}
 	return 0;
 }