lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20110307174934.15811.qmail@science.horizon.com>
Date:	7 Mar 2011 12:49:34 -0500
From:	"George Spelvin" <linux@...izon.com>
To:	penberg@...nel.org
Cc:	linux-kernel@...r.kernel.org, linux-mm@...ck.org, linux@...izon.com
Subject: Re: [PATCH] Make /proc/slabinfo 0400

To go with my earlier code, here's a (proof of concept) more efficient
random number generator for a series of small values.  A bit more code,
but a lot less calls to half_md4_transform.

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 773007d..6b3fd4e 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1658,6 +1658,84 @@ unsigned int get_random_int(void)
 	return ret;
 }
 
+struct random_mod_state {
+	unsigned int x, lim;	/* Invariant: 0 <= x < lim, and random */
+	__u8 const *seed;
+	unsigned len;
+};
+
+void
+get_random_mod_start(struct random_mod_state *s)
+{
+	s->x = 0;
+	s->lim = 0;
+	s->len = 0;
+
+	preempt_disable();	/* For access to percpu variables */
+}
+
+/*
+ * Return a random 0 <= x < m.  This is exacctly uniformly distributed,
+ * which "random() % m" is not, and it is economical with seed entropy.
+ * For example, this can shuffle 27 elements (27! > 2^93) with only
+ * one call to half_md4_transform.
+ *
+ * This is limited to 24-bit moduli m; larger values risk overflow.
+ */
+unsigned
+get_random_mod(struct random_mod_state *s, unsigned m)
+{
+        unsigned x = s->x, lim = x->lim;
+
+        for (;;) {
+		unsigned k;
+
+		/* Ensure lim >= m */
+		while (lim < m) {
+			/* Invoke underlying random bit source */
+			if (!s->len--) {
+				__u32 *h = __get_cpu_var(get_random_int_hash);
+				struct keydata const *keyptr = get_keyptr();
+				cycles_t c = get_cycles();
+
+				/* Throw in some extra seed material */
+				h[0] += (__u32)c;
+				h[1] += (__u32)(c>>16>>16); /* 32-bit safe */
+				h[2] += current->pid + jiffies;
+
+				half_md4_transform(h, keyptr->secret);
+
+				/* And use last 12 bytes as random numbers */
+				s->seed = (__u8 *)(h + 1);
+				s->len = 11;	/* Pre-decremented */
+			}
+			/* Add one byte to state */
+			x = x<<8 | *s->seed++;
+			lim <<= 8;
+		}
+		/*
+		 * Core loop.  We occasionally have to discard and regenerate
+		 * to ensure uniformity.
+		 */
+		k = lim % m;
+		if (x >= k) {
+			x -= k;		lim -= k;
+			/* Final result: Return x % m, keep x / m */
+			s->x = x/m;	s->lim = lim/m;
+			return x % m;
+		}
+		/* Non-uniform: keep fractional part and try again */
+		lim = k;
+	}
+}
+
+void
+get_random_mod_stop(struct random_mod_state *s)
+{
+	(void)s;
+	preempt_enable();	/* Drop lock on s->seed */
+}
+
 /*
  * randomize_range() returns a start address such that
  *
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ