linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH] Make /proc/slabinfo 040
@ 2011-03-07 14:19 George Spelvin
  2011-03-07 17:49 ` [PATCH] Make /proc/slabinfo 0400 George Spelvin
  0 siblings, 1 reply; 2+ messages in thread
From: George Spelvin @ 2011-03-07 14:19 UTC (permalink / raw)
  To: penberg; +Cc: linux, linux-kernel, linux-mm

> Yeah, maybe. I've attached a proof of concept patch that attempts to
> randomize object layout in individual slabs. I'm don't completely
> understand the attack vector so I don't make any claims if the patch
> helps or not.

+	while (!bitmap_empty(bitmap, page->objects)) {
+		unsigned long idx;
+		void *p;
+
+		idx	= get_random_int() % page->objects;
+
+		idx	= find_next_bit(bitmap, page->objects, idx);
+
+		if (idx >= page->objects)
+			continue;
+
+		clear_bit(idx, bitmap);
+
+		p = start + idx * s->size;
+		setup_object(s, page, last);
+		set_freepointer(s, last, p);
+		last = p;
+	}
+	setup_object(s, page, last);
+	set_freepointer(s, last, NULL);

There's actually a far more efficient way to set up a linked list in
random order.

Start with a 1-element cycle, and repeatedly insert new elements at a
random position in the cycle.  At the end, set the list head to a random
position in the cycle.  It goes like this:

	void *p = start;
	set_freepointer(s, p, p);

	for (n = 1; n < s->size; n++) {
		void *q = start + n * s->size;
		/* p points to a random object in the list; link in after */
		set_freepointer(s, q, get_freepointer(s, p));
		set_freepointer(s, p, q);
		p = start + s->size * (get_random_int() % (n+1));
	}
	page->freelist = get_freepointer(s, p);
	set_freepointer(s, p, NULL);

Hope it helps.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* Re: [PATCH] Make /proc/slabinfo 0400
  2011-03-07 14:19 [PATCH] Make /proc/slabinfo 040 George Spelvin
@ 2011-03-07 17:49 ` George Spelvin
  0 siblings, 0 replies; 2+ messages in thread
From: George Spelvin @ 2011-03-07 17:49 UTC (permalink / raw)
  To: penberg; +Cc: linux-kernel, linux-mm, linux

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, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

end of thread, other threads:[~2011-03-07 17:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-07 14:19 [PATCH] Make /proc/slabinfo 040 George Spelvin
2011-03-07 17:49 ` [PATCH] Make /proc/slabinfo 0400 George Spelvin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox