linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* AT_ENTROPY1 and AT_ENTROPY2 values for include/linux/auxvec.h
@ 2007-06-17 23:40 Alexander Gabert
  2007-06-18  1:06 ` Arjan van de Ven
  0 siblings, 1 reply; 17+ messages in thread
From: Alexander Gabert @ 2007-06-17 23:40 UTC (permalink / raw)
  To: libc-alpha, linux-kernel; +Cc: hardened

Hello glibc and kernel maintainers,

could you please add two AT_ entries to include/linux/auxvec.h in the 
upstream kernel and the respective elf/elf.h definitions in glibc.

#define AT_ENTROPY1 24   /* kernel entropy in auxiliary vector */
#define AT_ENTROPY2 25   /* second field for kernel entropy */

The accompanying kernel patch follows, it is basically a config option 
to give userland entropy.
We are using the appended patch for Gentoo Hardened.
You don't have to put it into the upstream linux kernel, it is only 
there for explaining what i need the AT_ values for.
Also the patch contains a subtle "bug" because the repetive call to 
get_random_int()
seems to yield the same result when done immediately after another:

$$ od -tx8 /proc/self/auxv
0000000 ffffe40000000020 ffffe00000000021
0000020 0383f9ff00000010 0000100000000006
0000040 0000006400000011 8000003400000003
0000060 0000002000000004 0000000a00000005
0000100 b7ef200000000007 0000000000000008
0000120 800013f000000009 000000000000000b
0000140 000000000000000c 000000000000000d
0000160 000000000000000e 0000000000000017
0000200 0c1f4d8100000018 0c1f4d8100000019
0000220 bfa7da8b0000000f 0000000000000000
0000240


However, this is just a proof of concept, all i'm asking for is to get 
the two numbers into the upstream
kernel and glibc auxvec.h to avoid future clashes with the numbers, thx 
in advance.

-- patch --

diff -Nru linux-2.6.21.5.ORIG/fs/binfmt_elf.c linux-2.6.21.5/fs/binfmt_elf.c
--- linux-2.6.21.5.ORIG/fs/binfmt_elf.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/fs/binfmt_elf.c	2007-06-18 00:22:59.000000000 +0200
@@ -201,6 +201,13 @@
 	NEW_AUX_ENT(AT_GID, tsk->gid);
 	NEW_AUX_ENT(AT_EGID, tsk->egid);
  	NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
+#if defined(CONFIG_AT_ENTROPY1)
+  NEW_AUX_ENT(AT_ENTROPY1, get_random_int());
+#endif
+#if defined(CONFIG_AT_ENTROPY2)
+  NEW_AUX_ENT(AT_ENTROPY2, get_random_int());
+#endif
+
 	if (k_platform) {
 		NEW_AUX_ENT(AT_PLATFORM,
 			    (elf_addr_t)(unsigned long)u_platform);
diff -Nru linux-2.6.21.5.ORIG/include/linux/auxvec.h linux-2.6.21.5/include/linux/auxvec.h
--- linux-2.6.21.5.ORIG/include/linux/auxvec.h	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/include/linux/auxvec.h	2007-06-18 00:19:57.000000000 +0200
@@ -26,6 +26,9 @@
 
 #define AT_SECURE 23   /* secure mode boolean */
 
-#define AT_VECTOR_SIZE  44 /* Size of auxiliary table.  */
+#define AT_ENTROPY1 24   /* kernel entropy in auxiliary vector */
+#define AT_ENTROPY2 25   /* second field for kernel entropy */
+
+#define AT_VECTOR_SIZE  46 /* Size of auxiliary table.  */
 
 #endif /* _LINUX_AUXVEC_H */
diff -Nru linux-2.6.21.5.ORIG/security/Kconfig linux-2.6.21.5/security/Kconfig
--- linux-2.6.21.5.ORIG/security/Kconfig	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/security/Kconfig	2007-06-18 00:32:57.000000000 +0200
@@ -4,6 +4,24 @@
 
 menu "Security options"
 
+config AT_ENTROPY1
+  bool "Enable kernel entropy in the auxiliary vector"
+  help
+    This option provides support for kernel-generated entropy handed
+    to processes via the auxiliary vector table in /proc/self/auxv.
+    Most notably userlands with heavy usage of stack smashing protection
+    benefit from kernel entropy because /dev/urandom is less likely to
+    become depleted due to the extensive need for randomized SSP __guard.
+
+config AT_ENTROPY2
+  bool "Enable additional kernel entropy in the auxiliary vector"
+  depends on AT_ENTROPY1
+  help
+    This option provides support for an additional field of kernel-generated
+    entropy for userland processes.  It can be used for an extension to SSP
+    where a second guard value is necessary for XOR encoding control data
+    residing in the stack frame of userland processes.
+
 config KEYS
 	bool "Enable access key retention support"
 	help

-- /patch --

also available at

http://dev.gentoo.org/~pappy/ssp/AT_ENTROPY/linux-2.6.21.5_AT_ENTROPY.patch


Thanks again,


Alex

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

* Re: AT_ENTROPY1 and AT_ENTROPY2 values for include/linux/auxvec.h
  2007-06-17 23:40 AT_ENTROPY1 and AT_ENTROPY2 values for include/linux/auxvec.h Alexander Gabert
@ 2007-06-18  1:06 ` Arjan van de Ven
  2007-06-18  1:28   ` Alexander Gabert
  0 siblings, 1 reply; 17+ messages in thread
From: Arjan van de Ven @ 2007-06-18  1:06 UTC (permalink / raw)
  To: Alexander Gabert; +Cc: libc-alpha, linux-kernel, hardened

On Mon, 2007-06-18 at 01:40 +0200, Alexander Gabert wrote:
> Hello glibc and kernel maintainers,
> 
> could you please add two AT_ entries to include/linux/auxvec.h in the 
> upstream kernel and the respective elf/elf.h definitions in glibc.


while I'm not per se against adding such aux vectors, I think it's a bad
mistake to make them a config option (and 2 options at that!!)

Stack protector is very widely deployed today
(Fedora,RHEL,SLES,OpenSUSE,Gentoo etc), so I can sure see the point of
helping it a bit... but I'd like to see a little more data on how the
current approach isn't sufficient.



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

* Re: AT_ENTROPY1 and AT_ENTROPY2 values for include/linux/auxvec.h
  2007-06-18  1:06 ` Arjan van de Ven
@ 2007-06-18  1:28   ` Alexander Gabert
  2007-06-18  1:38     ` Arjan van de Ven
  0 siblings, 1 reply; 17+ messages in thread
From: Alexander Gabert @ 2007-06-18  1:28 UTC (permalink / raw)
  To: Arjan van de Ven, libc-alpha, linux-kernel, hardened

Arjan van de Ven schrieb:
> On Mon, 2007-06-18 at 01:40 +0200, Alexander Gabert wrote:
>   
>> Hello glibc and kernel maintainers,
>>
>> could you please add two AT_ entries to include/linux/auxvec.h in the 
>> upstream kernel and the respective elf/elf.h definitions in glibc.
>>     
>
>
> while I'm not per se against adding such aux vectors, I think it's a bad
> mistake to make them a config option (and 2 options at that!!)
>   
Well our glibc patch (still under development, here comes a snippet) 
will conditionally check for the auxv and if not "fall back" to normal 
SSP entropy:

-  /* Set up the stack checker's canary.  */
-  uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
+  /* Set up the stack checker's canary, optional kernel entropy  */
+  uintptr_t stack_chk_guard;
+
+  if (GLRO(dl_entropy) != 0) {
+    stack_chk_guard = GLRO(dl_entropy);
+  }
+  else {
+    stack_chk_guard = _dl_setup_stack_chk_guard ();
+  }

Hence the config option for the kernel- it's philosophy at Gentoo to 
make choices available to users how they want their systems to behave, 
even on the expense of added complexity and need to "understand" how 
things work in the first place.

If you add the aux vector behaviour as a default, there would surely be 
a backport of the default behaviour to the more "Gentoo flavoured" 
choice-based system of activating/deactivating it to your own needs.

For your second question, why two config options: entropy is a precious 
resource and many critical apps rely on it.
Until SSPx (http://dev.gentoo.org/~pappy/sspx/ssxp.pdf) is not 
available, we don't want to force users to have two vector entries with 
one containing unneeded (wasted?) entropy.  SSP already works good, so 
if this stuff makes it's way into the kernel or kernel and glibc folks 
tell me which numbers i can use, i can make my patches and add the logic 
to Gentoo kernel sources and glibc.

Sincere thanks,


Alex

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

* Re: AT_ENTROPY1 and AT_ENTROPY2 values for include/linux/auxvec.h
  2007-06-18  1:28   ` Alexander Gabert
@ 2007-06-18  1:38     ` Arjan van de Ven
  2007-06-18 10:36       ` Alexander Gabert
  0 siblings, 1 reply; 17+ messages in thread
From: Arjan van de Ven @ 2007-06-18  1:38 UTC (permalink / raw)
  To: Alexander Gabert; +Cc: libc-alpha, linux-kernel, hardened


> Hence the config option for the kernel- it's philosophy at Gentoo to 
> make choices available to users how they want their systems to behave, 
> even on the expense of added complexity and need to "understand" how 
> things work in the first place.

While I am not opposed to choice, I am opposed to having too finegrained
kernel config options. In your view, every single kernel patch would be
a config option... I much rather have config options for "important" big
changes, not for something this small. Another argument is that this
kind of userspace interface is better off being always there or never;
making this variable serves no-one.



-- 
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org


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

* Re: AT_ENTROPY1 and AT_ENTROPY2 values for include/linux/auxvec.h
  2007-06-18  1:38     ` Arjan van de Ven
@ 2007-06-18 10:36       ` Alexander Gabert
  2007-06-20 15:34         ` [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5 Alexander Gabert
  0 siblings, 1 reply; 17+ messages in thread
From: Alexander Gabert @ 2007-06-18 10:36 UTC (permalink / raw)
  To: Arjan van de Ven, libc-alpha, linux-kernel, hardened

Arjan van de Ven schrieb:
>> Hence the config option for the kernel- it's philosophy at Gentoo to 
>> make choices available to users how they want their systems to behave, 
>> even on the expense of added complexity and need to "understand" how 
>> things work in the first place.
>>     
>
> While I am not opposed to choice, I am opposed to having too finegrained
> kernel config options. In your view, every single kernel patch would be
> a config option... I much rather have config options for "important" big
> changes, not for something this small. Another argument is that this
> kind of userspace interface is better off being always there or never;
> making this variable serves no-one.
>
>
>
>   
Hi again,

as said, i'm not voting for getting the specific example patch into 
kernel source.
All i came for and would like to see is the two numbers into the 
upstream header file to avoid future namespace clashes (as said in the 
original mail).

I honestly don't know how to follow the discussion to implement this 
kind of entropy given via auxv to userland- if you (the kernel devs) 
think it makes sense the way you want it you as upstream devs can do it 
all the way you like it- i can always change it with a patch for my own 
needs in my own sources.  I can't say anything at all about all of this 
because i don't know what is important from your point of view as kernel 
maintainers and what is not.  I understand your concerns and know that 
we are talking from different perspectives, thus it is probably normal 
that our interests and technical solutions vary.

However, as said, the only thing important for me is to not use 
"arbitrary" chosen numbers for the AT_ENTROPY1 and 2 values and later 
have problems when my "private" numbers suddenly are assigned to a 
different thing by "official" kernel devs.  That would be bad for me and 
this is what i want to avoid in the first place.

So please tell me what i can do about the requirements and the time and 
what the usual process is for asking how to get the numbers into the 
kernel so i can start using them for my own work.

Thanks in advance,


Alex




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

* [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-18 10:36       ` Alexander Gabert
@ 2007-06-20 15:34         ` Alexander Gabert
  2007-06-20 15:38           ` Arjan van de Ven
                             ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: Alexander Gabert @ 2007-06-20 15:34 UTC (permalink / raw)
  To: Arjan van de Ven, libc-alpha, linux-kernel, hardened; +Cc: torvalds

Hi,

http://dev.gentoo.org/~pappy/kernel/linux-2.6.21.5-get_urandom_long-AT_ENTROPY.patch

this patch adds the function drivers/char/random.c:get_random_long()
and adds an AT_ENTROPY field in the auxv without config option
(the config option was removed as suggested by Arjan on LKML).

README: get_random_long() and AT_ENTROPY support for auxv
NAME: Alexander Gabert
EMAIL: pappy@gentoo.org



diff -Nru linux-2.6.21.5.ORIG/drivers/char/random.c 
linux-2.6.21.5/drivers/char/random.c
--- linux-2.6.21.5.ORIG/drivers/char/random.c    2007-06-11 
20:37:06.000000000 +0200
+++ linux-2.6.21.5/drivers/char/random.c    2007-06-20 
17:00:35.000000000 +0200
@@ -1654,6 +1654,53 @@
 }
 
 /*
+ * get_random_long() returns a randomized unsigned long word.
+ * It recycles it's entropy cache for a given time period and
+ * uses half_md4_transform to generate a unique return value.
+ * Every REKEY_INTERVAL the cache is reloaded with fresh
+ * randomization data using get_random_bytes().
+ * This function is not intended for strong cryptographic routines.
+ */
+unsigned long get_random_long(void)
+{
+  /* remember the last time we refreshed the cache with random entropy */
+  static time_t   rekey_time;
+
+  time_t          t;
+
+  /*
+   * the following data in the buffer is unchanged during REKEY_INTERVAL:
+   * |----|----|KKKK|KKKK|KKKK|KKKK|KKKK|KKKK|----|----|----|----|
+   * ___0____1____2____3____4____5____6____7____8____9___10___11__
+   *
+   * the following data is updated during the first half_md4_transform call
+   * |----|YYYY|----|----|----|----|----|----|ZZZZ|ZZZZ|ZZZZ|ZZZZ|
+   * ___0____1____2____3____4____5____6____7____8____9___10___11__
+   *
+   * the following data is updated during the second half_md4_transform
+   * |XXXX|----|----|----|----|----|----|----|ZZZZ|ZZZZ|ZZZZ|ZZZZ|
+   * ___0____1____2____3____4____5____6____7____8____9___10___11__
+   */
+  static __u32    entropycache[12];
+
+  /* get the current time in seconds */
+  t = get_seconds();
+
+  /* check for REKEY_INTERVAL */
+  if (t && (!rekey_time || ((t - rekey_time) > REKEY_INTERVAL))) {
+    rekey_time = t;
+    /* refresh with random entropy */
+    get_random_bytes(entropycache, sizeof(entropycache));
+  }
+
+  /* transform the buffer to a new state, thus generating new return 
value */
+  entropycache[1] = half_md4_transform(entropycache+8, entropycache);
+  entropycache[0] = half_md4_transform(entropycache+8, entropycache);
+
+  return *(unsigned long *)entropycache;
+}
+
+/*
  * randomize_range() returns a start address such that
  *
  *    [...... <range> .....]
diff -Nru linux-2.6.21.5.ORIG/fs/binfmt_elf.c linux-2.6.21.5/fs/binfmt_elf.c
--- linux-2.6.21.5.ORIG/fs/binfmt_elf.c    2007-06-11 20:37:06.000000000 
+0200
+++ linux-2.6.21.5/fs/binfmt_elf.c    2007-06-20 17:02:59.000000000 +0200
@@ -201,6 +201,7 @@
     NEW_AUX_ENT(AT_GID, tsk->gid);
     NEW_AUX_ENT(AT_EGID, tsk->egid);
      NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
+  NEW_AUX_ENT(AT_ENTROPY, get_random_long());
     if (k_platform) {
         NEW_AUX_ENT(AT_PLATFORM,
                 (elf_addr_t)(unsigned long)u_platform);
diff -Nru linux-2.6.21.5.ORIG/include/linux/auxvec.h 
linux-2.6.21.5/include/linux/auxvec.h
--- linux-2.6.21.5.ORIG/include/linux/auxvec.h    2007-06-11 
20:37:06.000000000 +0200
+++ linux-2.6.21.5/include/linux/auxvec.h    2007-06-20 
16:47:44.000000000 +0200
@@ -26,6 +26,8 @@
 
 #define AT_SECURE 23   /* secure mode boolean */
 
-#define AT_VECTOR_SIZE  44 /* Size of auxiliary table.  */
+#define AT_ENTROPY 24 /* kernel entropy in auxv */
+
+#define AT_VECTOR_SIZE 45 /* Size of auxiliary table in.  */
 
 #endif /* _LINUX_AUXVEC_H */
diff -Nru linux-2.6.21.5.ORIG/include/linux/random.h 
linux-2.6.21.5/include/linux/random.h
--- linux-2.6.21.5.ORIG/include/linux/random.h    2007-06-11 
20:37:06.000000000 +0200
+++ linux-2.6.21.5/include/linux/random.h    2007-06-20 
16:19:02.000000000 +0200
@@ -67,6 +67,9 @@
 #endif
 
 unsigned int get_random_int(void);
+
+unsigned long get_random_long(void);
+
 unsigned long randomize_range(unsigned long start, unsigned long end, 
unsigned long len);
 
 u32 random32(void);




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

* Re: [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-20 15:34         ` [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5 Alexander Gabert
@ 2007-06-20 15:38           ` Arjan van de Ven
  2007-06-20 16:39           ` Linus Torvalds
                             ` (2 subsequent siblings)
  3 siblings, 0 replies; 17+ messages in thread
From: Arjan van de Ven @ 2007-06-20 15:38 UTC (permalink / raw)
  To: Alexander Gabert; +Cc: libc-alpha, linux-kernel, hardened, torvalds

On Wed, 2007-06-20 at 17:34 +0200, Alexander Gabert wrote:
> Hi,
> 
> http://dev.gentoo.org/~pappy/kernel/linux-2.6.21.5-get_urandom_long-AT_ENTROPY.patch
> 
> this patch adds the function drivers/char/random.c:get_random_long()
> and adds an AT_ENTROPY field in the auxv without config option
> (the config option was removed as suggested by Arjan on LKML).

your patch has some whitespace damage it seems...
other than that I can agree with the approach.

-- 
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org


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

* Re: [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-20 15:34         ` [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5 Alexander Gabert
  2007-06-20 15:38           ` Arjan van de Ven
@ 2007-06-20 16:39           ` Linus Torvalds
  2007-06-20 17:04           ` Eric Dumazet
  2007-06-20 20:30           ` Matt Mackall
  3 siblings, 0 replies; 17+ messages in thread
From: Linus Torvalds @ 2007-06-20 16:39 UTC (permalink / raw)
  To: Alexander Gabert; +Cc: Arjan van de Ven, libc-alpha, linux-kernel, hardened



On Wed, 20 Jun 2007, Alexander Gabert wrote:
> 
> this patch adds the function drivers/char/random.c:get_random_long()

It's totally whitespace-damaged, and I wonder why the "int" vs "long" is 
so important. Also, what are the performance implications for execve?

		Linus

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

* Re: [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-20 15:34         ` [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5 Alexander Gabert
  2007-06-20 15:38           ` Arjan van de Ven
  2007-06-20 16:39           ` Linus Torvalds
@ 2007-06-20 17:04           ` Eric Dumazet
  2007-06-20 20:30           ` Matt Mackall
  3 siblings, 0 replies; 17+ messages in thread
From: Eric Dumazet @ 2007-06-20 17:04 UTC (permalink / raw)
  To: Alexander Gabert
  Cc: Arjan van de Ven, libc-alpha, linux-kernel, hardened, torvalds

On Wed, 20 Jun 2007 17:34:13 +0200
Alexander Gabert <pappy@gentoo.org> wrote:

> Hi,

Hello Alexander

> 
> http://dev.gentoo.org/~pappy/kernel/linux-2.6.21.5-get_urandom_long-AT_ENTROPY.patch
> 
> this patch adds the function drivers/char/random.c:get_random_long()
> and adds an AT_ENTROPY field in the auxv without config option
> (the config option was removed as suggested by Arjan on LKML).
> 
> README: get_random_long() and AT_ENTROPY support for auxv
> NAME: Alexander Gabert
> EMAIL: pappy@gentoo.org
> 
> 
> 
> diff -Nru linux-2.6.21.5.ORIG/drivers/char/random.c 
> linux-2.6.21.5/drivers/char/random.c
> --- linux-2.6.21.5.ORIG/drivers/char/random.c    2007-06-11 
> 20:37:06.000000000 +0200
> +++ linux-2.6.21.5/drivers/char/random.c    2007-06-20 
> 17:00:35.000000000 +0200
> @@ -1654,6 +1654,53 @@
>  }
>  
>  /*
> + * get_random_long() returns a randomized unsigned long word.
> + * It recycles it's entropy cache for a given time period and
> + * uses half_md4_transform to generate a unique return value.
> + * Every REKEY_INTERVAL the cache is reloaded with fresh
> + * randomization data using get_random_bytes().
> + * This function is not intended for strong cryptographic routines.
> + */
> +unsigned long get_random_long(void)
> +{
> +  /* remember the last time we refreshed the cache with random entropy */
> +  static time_t   rekey_time;
> +
> +  time_t          t;
> +
> +  /*
> +   * the following data in the buffer is unchanged during REKEY_INTERVAL:
> +   * |----|----|KKKK|KKKK|KKKK|KKKK|KKKK|KKKK|----|----|----|----|
> +   * ___0____1____2____3____4____5____6____7____8____9___10___11__
> +   *
> +   * the following data is updated during the first half_md4_transform call
> +   * |----|YYYY|----|----|----|----|----|----|ZZZZ|ZZZZ|ZZZZ|ZZZZ|
> +   * ___0____1____2____3____4____5____6____7____8____9___10___11__
> +   *
> +   * the following data is updated during the second half_md4_transform
> +   * |XXXX|----|----|----|----|----|----|----|ZZZZ|ZZZZ|ZZZZ|ZZZZ|
> +   * ___0____1____2____3____4____5____6____7____8____9___10___11__
> +   */
> +  static __u32    entropycache[12];
> +
> +  /* get the current time in seconds */
> +  t = get_seconds();
> +
> +  /* check for REKEY_INTERVAL */
> +  if (t && (!rekey_time || ((t - rekey_time) > REKEY_INTERVAL))) {
> +    rekey_time = t;
> +    /* refresh with random entropy */
> +    get_random_bytes(entropycache, sizeof(entropycache));
> +  }

Maybe this rekeying can be added in rekey_seq_generator(), so that you dont have to test rekey_time each time get_random_long() is called. You probably could refresh only 8 values, not the full 12 values.

> +
> +  /* transform the buffer to a new state, thus generating new return 
> value */
> +  entropycache[1] = half_md4_transform(entropycache+8, entropycache);
> +  entropycache[0] = half_md4_transform(entropycache+8, entropycache);
> +
> +  return *(unsigned long *)entropycache;

This is not valid on some arches, as entropycache[] alignment (u32 -> 4) might be smaller then alignment for a long (4 or 8). 

This also adds about 400 instructions (half_md4_transform() is about 200 instructions, about 700 bytes of code on x86_64) in exec() path, but this is probably minor given the cost of exec()

I am not sure why you unconditionally call half_md4_transform() twice, since the entropycache[1] wont be used on 32bits platforms.

I suggest spliting your entropycache into two parts :

One part, with 8 u32, that is read_mostly (and shared by all cpus), updated once every 300 seconds in rekey_seq_generator()
static u32 entropycache_shared[8] __read_mostly;

One part, with (16/sizeof(long)) long, percpu to avoid false sharing between cpus.
static DEFINE_PER_CPU(unsigned long , entropycache_pcpu)[16 / sizeof(unsigned long)];

then call half_md4_transform() once :

half_md4_transform((u32 *)entropycache_pcpu, entropycache_shared);
return entropycache_pcpu[0];


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

* Re: [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-20 15:34         ` [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5 Alexander Gabert
                             ` (2 preceding siblings ...)
  2007-06-20 17:04           ` Eric Dumazet
@ 2007-06-20 20:30           ` Matt Mackall
  2007-06-24 17:45             ` Alexander Gabert
  3 siblings, 1 reply; 17+ messages in thread
From: Matt Mackall @ 2007-06-20 20:30 UTC (permalink / raw)
  To: Alexander Gabert
  Cc: Arjan van de Ven, libc-alpha, linux-kernel, hardened, torvalds

On Wed, Jun 20, 2007 at 05:34:13PM +0200, Alexander Gabert wrote:
> Hi,
> 
> http://dev.gentoo.org/~pappy/kernel/linux-2.6.21.5-get_urandom_long-AT_ENTROPY.patch
> 
> this patch adds the function drivers/char/random.c:get_random_long()
> and adds an AT_ENTROPY field in the auxv without config option
> (the config option was removed as suggested by Arjan on LKML).

One ought to cc: the /dev/random maintainer.

> /*
> + * get_random_long() returns a randomized unsigned long word.
> + * It recycles it's entropy cache for a given time period and
> + * uses half_md4_transform to generate a unique return value.
> + * Every REKEY_INTERVAL the cache is reloaded with fresh
> + * randomization data using get_random_bytes().
> + * This function is not intended for strong cryptographic routines.
> + */

What's the point of this?

-- 
Mathematics is the supreme nostalgia of our time.

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

* Re: [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-20 20:30           ` Matt Mackall
@ 2007-06-24 17:45             ` Alexander Gabert
  2007-06-25  3:45               ` Matt Mackall
  0 siblings, 1 reply; 17+ messages in thread
From: Alexander Gabert @ 2007-06-24 17:45 UTC (permalink / raw)
  To: linux-kernel, torvalds
  Cc: Matt Mackall, Arjan van de Ven, libc-alpha, hardened

[-- Attachment #1: Type: text/plain, Size: 11477 bytes --]

Hi Linus,
hi LKML,

i would like to thank LKML and especially Eric (thanks for the per_cpu 
macro tips and design guidelines!) and the other contributors to this idea.

This time the patch is rather big because it also removes 
get_random_int() and introduces get_random_long() throughout the kernel.
The function get_random_int was primarily used for setting up the 
randomization of memory used for process stacks and initializing a stack 
canary in a tsk.
However, using get_random_long works exactly the same way to generate 
randomization deltas for this purpose and i have applied it to all 
locations where get_random_int was previously used.

Now to explain the reasoning for replacing get_random_int...
My findings with get_random_int was that when i called it two times very 
fast after another because of setting up two SSP randomized guard values 
for the same process, it returned the same, yet randomized, integer number.

I learned that get_random_int uses the current process pid and the 
current jiffies for feeding the half_md4_transform function that's 
following deeper in the code.  However, when called in a relatively 
short timeframe (lesser than a jiffie can increase it's count), this 
information given to the underlying "randomization" generation is not 
changing, which means when you call get_random_int two or more times in 
short time, it will use the same data for generating the randomized 
data, which is the pid of the process and current jiffies.  The returned 
randomized integer numbers are the same because the pid and the jiffies 
used as the input for the randomization function did not change in such 
a short time.  Sorry that i cannot explain it more detailed or in better 
english, you should be able to see it from the code looking at 
get_random_int and how it's working by calling the other function and 
looking at the input to the function.
Also remember that the comment in the function is probably a bit 
outdated because rekeying is happening not every 1 second any more.

This is the url for the patch:
http://dev.gentoo.org/~pappy/kernel/linux-2.6.21.5-get_random_long-AT_ENTROPY.patch

Thanks for the attention and thanks again to all posters for your help!


-Alex

This is the inlined patch, i changed my vimrc and really hope i'm not 
making a whitespace error again:

diff -Nru linux-2.6.21.5.ORIG/arch/i386/kernel/process.c linux-2.6.21.5/arch/i386/kernel/process.c
--- linux-2.6.21.5.ORIG/arch/i386/kernel/process.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/i386/kernel/process.c	2007-06-24 19:00:15.000000000 +0200
@@ -924,6 +924,6 @@
 unsigned long arch_align_stack(unsigned long sp)
 {
 	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-		sp -= get_random_int() % 8192;
+		sp -= get_random_long() % 8192;
 	return sp & ~0xf;
 }
diff -Nru linux-2.6.21.5.ORIG/arch/i386/mm/mmap.c linux-2.6.21.5/arch/i386/mm/mmap.c
--- linux-2.6.21.5.ORIG/arch/i386/mm/mmap.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/i386/mm/mmap.c	2007-06-24 19:00:53.000000000 +0200
@@ -42,7 +42,7 @@
 	unsigned long random_factor = 0;
 
 	if (current->flags & PF_RANDOMIZE)
-		random_factor = get_random_int() % (1024*1024);
+		random_factor = get_random_long() % (1024*1024);
 
 	if (gap < MIN_GAP)
 		gap = MIN_GAP;
diff -Nru linux-2.6.21.5.ORIG/arch/sparc64/kernel/sys_sparc.c linux-2.6.21.5/arch/sparc64/kernel/sys_sparc.c
--- linux-2.6.21.5.ORIG/arch/sparc64/kernel/sys_sparc.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/sparc64/kernel/sys_sparc.c	2007-06-24 19:01:44.000000000 +0200
@@ -362,7 +362,7 @@
 	unsigned long random_factor = 0UL;
 
 	if (current->flags & PF_RANDOMIZE) {
-		random_factor = get_random_int();
+		random_factor = get_random_long();
 		if (test_thread_flag(TIF_32BIT))
 			random_factor &= ((1 * 1024 * 1024) - 1);
 		else
diff -Nru linux-2.6.21.5.ORIG/arch/um/kernel/process.c linux-2.6.21.5/arch/um/kernel/process.c
--- linux-2.6.21.5.ORIG/arch/um/kernel/process.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/um/kernel/process.c	2007-06-24 19:02:08.000000000 +0200
@@ -478,7 +478,7 @@
 unsigned long arch_align_stack(unsigned long sp)
 {
 	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-		sp -= get_random_int() % 8192;
+		sp -= get_random_long() % 8192;
 	return sp & ~0xf;
 }
 #endif
diff -Nru linux-2.6.21.5.ORIG/arch/x86_64/ia32/mmap32.c linux-2.6.21.5/arch/x86_64/ia32/mmap32.c
--- linux-2.6.21.5.ORIG/arch/x86_64/ia32/mmap32.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/x86_64/ia32/mmap32.c	2007-06-24 19:02:34.000000000 +0200
@@ -44,7 +44,7 @@
 	unsigned long random_factor = 0;
 
 	if (current->flags & PF_RANDOMIZE)
-		random_factor = get_random_int() % (1024*1024);
+		random_factor = get_random_long() % (1024*1024);
 
 	if (gap < MIN_GAP)
 		gap = MIN_GAP;
diff -Nru linux-2.6.21.5.ORIG/arch/x86_64/kernel/functionlist linux-2.6.21.5/arch/x86_64/kernel/functionlist
--- linux-2.6.21.5.ORIG/arch/x86_64/kernel/functionlist	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/x86_64/kernel/functionlist	2007-06-24 19:02:48.000000000 +0200
@@ -862,7 +862,7 @@
 *(.text.__ide_dma_end)
 *(.text.hrtimer_get_remaining)
 *(.text.get_task_mm)
-*(.text.get_random_int)
+*(.text.get_random_long)
 *(.text.free_pipe_info)
 *(.text.filemap_write_and_wait_range)
 *(.text.exit_thread)
diff -Nru linux-2.6.21.5.ORIG/arch/x86_64/kernel/process.c linux-2.6.21.5/arch/x86_64/kernel/process.c
--- linux-2.6.21.5.ORIG/arch/x86_64/kernel/process.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/x86_64/kernel/process.c	2007-06-24 19:03:02.000000000 +0200
@@ -885,6 +885,6 @@
 unsigned long arch_align_stack(unsigned long sp)
 {
 	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-		sp -= get_random_int() % 8192;
+		sp -= get_random_long() % 8192;
 	return sp & ~0xf;
 }
diff -Nru linux-2.6.21.5.ORIG/arch/x86_64/mm/mmap.c linux-2.6.21.5/arch/x86_64/mm/mmap.c
--- linux-2.6.21.5.ORIG/arch/x86_64/mm/mmap.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/x86_64/mm/mmap.c	2007-06-24 19:03:47.000000000 +0200
@@ -18,9 +18,9 @@
 	if (current->flags & PF_RANDOMIZE) {
 		/* Add 28bit randomness which is about 40bits of address space
 		   because mmap base has to be page aligned.
- 		   or ~1/128 of the total user VM
-	   	   (total user address space is 47bits) */
-		unsigned rnd = get_random_int() & 0xfffffff;
+		   or ~1/128 of the total user VM
+		   (total user address space is 47bits) */
+		unsigned rnd = get_random_long() & 0xfffffff;
 		mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT;
 	}
 	mm->get_unmapped_area = arch_get_unmapped_area;
diff -Nru linux-2.6.21.5.ORIG/drivers/char/random.c linux-2.6.21.5/drivers/char/random.c
--- linux-2.6.21.5.ORIG/drivers/char/random.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/drivers/char/random.c	2007-06-24 19:04:03.000000000 +0200
@@ -437,6 +437,9 @@
 	.pool = nonblocking_pool_data
 };
 
+static u32 entropycache_shared[8] __read_mostly;
+static DEFINE_PER_CPU(unsigned long , entropycache_pcpu)[16 / sizeof(unsigned long)];
+
 /*
  * This function adds a byte into the entropy "pool".  It does not
  * update the entropy estimate.  The caller should call
@@ -1455,6 +1458,10 @@
 	keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS;
 	smp_wmb();
 	ip_cnt++;
+
+	/* initialize the shared part of the entropy cache */
+	get_random_bytes(entropycache_shared, sizeof(entropycache_shared));
+
 	schedule_delayed_work(&rekey_work, REKEY_INTERVAL);
 }
 
@@ -1637,20 +1644,17 @@
 
 
 /*
- * Get a random word for internal kernel use only. Similar to urandom but
- * with the goal of minimal entropy pool depletion. As a result, the random
- * value is not cryptographically secure but for several uses the cost of
- * depleting entropy is too high
+ * get_random_long() returns a randomized unsigned long word.
+ * The entropy cache is refreshed periodically in rekey_seq_generator.
+ * This function uses half_md4_transform to generate a unique return value
+ * and is not intended for strong cryptographic routines.
  */
-unsigned int get_random_int(void)
+unsigned long get_random_long(void)
 {
-	/*
-	 * Use IP's RNG. It suits our purpose perfectly: it re-keys itself
-	 * every second, from the entropy pool (and thus creates a limited
-	 * drain on it), and uses halfMD4Transform within the second. We
-	 * also mix it with jiffies and the PID:
-	 */
-	return secure_ip_id((__force __be32)(current->pid + jiffies));
+	half_md4_transform((u32 *)__get_cpu_var(entropycache_pcpu),
+				entropycache_shared);
+
+	return __get_cpu_var(entropycache_pcpu)[0];
 }
 
 /*
@@ -1669,5 +1673,5 @@
 
 	if (end <= start + len)
 		return 0;
-	return PAGE_ALIGN(get_random_int() % range + start);
+	return PAGE_ALIGN(get_random_long() % range + start);
 }
diff -Nru linux-2.6.21.5.ORIG/fs/binfmt_elf.c linux-2.6.21.5/fs/binfmt_elf.c
--- linux-2.6.21.5.ORIG/fs/binfmt_elf.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/fs/binfmt_elf.c	2007-06-24 19:04:24.000000000 +0200
@@ -200,7 +200,8 @@
 	NEW_AUX_ENT(AT_EUID, tsk->euid);
 	NEW_AUX_ENT(AT_GID, tsk->gid);
 	NEW_AUX_ENT(AT_EGID, tsk->egid);
- 	NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
+	NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
+	NEW_AUX_ENT(AT_ENTROPY, get_random_long());
 	if (k_platform) {
 		NEW_AUX_ENT(AT_PLATFORM,
 			    (elf_addr_t)(unsigned long)u_platform);
@@ -516,7 +517,7 @@
 
 	if ((current->flags & PF_RANDOMIZE) &&
 		!(current->personality & ADDR_NO_RANDOMIZE)) {
-		random_variable = get_random_int() & STACK_RND_MASK;
+		random_variable = get_random_long() & STACK_RND_MASK;
 		random_variable <<= PAGE_SHIFT;
 	}
 #ifdef CONFIG_STACK_GROWSUP
diff -Nru linux-2.6.21.5.ORIG/include/linux/auxvec.h linux-2.6.21.5/include/linux/auxvec.h
--- linux-2.6.21.5.ORIG/include/linux/auxvec.h	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/include/linux/auxvec.h	2007-06-24 17:39:12.000000000 +0200
@@ -24,8 +24,9 @@
 #define AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
 #define AT_CLKTCK 17	/* frequency at which times() increments */
 
-#define AT_SECURE 23   /* secure mode boolean */
+#define AT_SECURE 23	/* secure mode boolean */
+#define AT_ENTROPY 24	/* kernel entropy in auxv */
 
-#define AT_VECTOR_SIZE  44 /* Size of auxiliary table.  */
+#define AT_VECTOR_SIZE  45 /* Size of auxiliary table.  */
 
 #endif /* _LINUX_AUXVEC_H */
diff -Nru linux-2.6.21.5.ORIG/include/linux/random.h linux-2.6.21.5/include/linux/random.h
--- linux-2.6.21.5.ORIG/include/linux/random.h	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/include/linux/random.h	2007-06-24 18:19:54.000000000 +0200
@@ -66,7 +66,7 @@
 extern const struct file_operations random_fops, urandom_fops;
 #endif
 
-unsigned int get_random_int(void);
+unsigned long get_random_long(void);
 unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
 
 u32 random32(void);
diff -Nru linux-2.6.21.5.ORIG/kernel/fork.c linux-2.6.21.5/kernel/fork.c
--- linux-2.6.21.5.ORIG/kernel/fork.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/kernel/fork.c	2007-06-24 19:05:00.000000000 +0200
@@ -180,7 +180,7 @@
 	setup_thread_stack(tsk, orig);
 
 #ifdef CONFIG_CC_STACKPROTECTOR
-	tsk->stack_canary = get_random_int();
+	tsk->stack_canary = get_random_long();
 #endif
 
 	/* One for us, one for whoever does the "release_task()" (usually parent) */


[-- Attachment #2: linux-2.6.21.5-get_random_long-AT_ENTROPY.patch --]
[-- Type: text/plain, Size: 9147 bytes --]

diff -Nru linux-2.6.21.5.ORIG/arch/i386/kernel/process.c linux-2.6.21.5/arch/i386/kernel/process.c
--- linux-2.6.21.5.ORIG/arch/i386/kernel/process.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/i386/kernel/process.c	2007-06-24 19:00:15.000000000 +0200
@@ -924,6 +924,6 @@
 unsigned long arch_align_stack(unsigned long sp)
 {
 	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-		sp -= get_random_int() % 8192;
+		sp -= get_random_long() % 8192;
 	return sp & ~0xf;
 }
diff -Nru linux-2.6.21.5.ORIG/arch/i386/mm/mmap.c linux-2.6.21.5/arch/i386/mm/mmap.c
--- linux-2.6.21.5.ORIG/arch/i386/mm/mmap.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/i386/mm/mmap.c	2007-06-24 19:00:53.000000000 +0200
@@ -42,7 +42,7 @@
 	unsigned long random_factor = 0;
 
 	if (current->flags & PF_RANDOMIZE)
-		random_factor = get_random_int() % (1024*1024);
+		random_factor = get_random_long() % (1024*1024);
 
 	if (gap < MIN_GAP)
 		gap = MIN_GAP;
diff -Nru linux-2.6.21.5.ORIG/arch/sparc64/kernel/sys_sparc.c linux-2.6.21.5/arch/sparc64/kernel/sys_sparc.c
--- linux-2.6.21.5.ORIG/arch/sparc64/kernel/sys_sparc.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/sparc64/kernel/sys_sparc.c	2007-06-24 19:01:44.000000000 +0200
@@ -362,7 +362,7 @@
 	unsigned long random_factor = 0UL;
 
 	if (current->flags & PF_RANDOMIZE) {
-		random_factor = get_random_int();
+		random_factor = get_random_long();
 		if (test_thread_flag(TIF_32BIT))
 			random_factor &= ((1 * 1024 * 1024) - 1);
 		else
diff -Nru linux-2.6.21.5.ORIG/arch/um/kernel/process.c linux-2.6.21.5/arch/um/kernel/process.c
--- linux-2.6.21.5.ORIG/arch/um/kernel/process.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/um/kernel/process.c	2007-06-24 19:02:08.000000000 +0200
@@ -478,7 +478,7 @@
 unsigned long arch_align_stack(unsigned long sp)
 {
 	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-		sp -= get_random_int() % 8192;
+		sp -= get_random_long() % 8192;
 	return sp & ~0xf;
 }
 #endif
diff -Nru linux-2.6.21.5.ORIG/arch/x86_64/ia32/mmap32.c linux-2.6.21.5/arch/x86_64/ia32/mmap32.c
--- linux-2.6.21.5.ORIG/arch/x86_64/ia32/mmap32.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/x86_64/ia32/mmap32.c	2007-06-24 19:02:34.000000000 +0200
@@ -44,7 +44,7 @@
 	unsigned long random_factor = 0;
 
 	if (current->flags & PF_RANDOMIZE)
-		random_factor = get_random_int() % (1024*1024);
+		random_factor = get_random_long() % (1024*1024);
 
 	if (gap < MIN_GAP)
 		gap = MIN_GAP;
diff -Nru linux-2.6.21.5.ORIG/arch/x86_64/kernel/functionlist linux-2.6.21.5/arch/x86_64/kernel/functionlist
--- linux-2.6.21.5.ORIG/arch/x86_64/kernel/functionlist	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/x86_64/kernel/functionlist	2007-06-24 19:02:48.000000000 +0200
@@ -862,7 +862,7 @@
 *(.text.__ide_dma_end)
 *(.text.hrtimer_get_remaining)
 *(.text.get_task_mm)
-*(.text.get_random_int)
+*(.text.get_random_long)
 *(.text.free_pipe_info)
 *(.text.filemap_write_and_wait_range)
 *(.text.exit_thread)
diff -Nru linux-2.6.21.5.ORIG/arch/x86_64/kernel/process.c linux-2.6.21.5/arch/x86_64/kernel/process.c
--- linux-2.6.21.5.ORIG/arch/x86_64/kernel/process.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/x86_64/kernel/process.c	2007-06-24 19:03:02.000000000 +0200
@@ -885,6 +885,6 @@
 unsigned long arch_align_stack(unsigned long sp)
 {
 	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-		sp -= get_random_int() % 8192;
+		sp -= get_random_long() % 8192;
 	return sp & ~0xf;
 }
diff -Nru linux-2.6.21.5.ORIG/arch/x86_64/mm/mmap.c linux-2.6.21.5/arch/x86_64/mm/mmap.c
--- linux-2.6.21.5.ORIG/arch/x86_64/mm/mmap.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/arch/x86_64/mm/mmap.c	2007-06-24 19:03:47.000000000 +0200
@@ -18,9 +18,9 @@
 	if (current->flags & PF_RANDOMIZE) {
 		/* Add 28bit randomness which is about 40bits of address space
 		   because mmap base has to be page aligned.
- 		   or ~1/128 of the total user VM
-	   	   (total user address space is 47bits) */
-		unsigned rnd = get_random_int() & 0xfffffff;
+		   or ~1/128 of the total user VM
+		   (total user address space is 47bits) */
+		unsigned rnd = get_random_long() & 0xfffffff;
 		mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT;
 	}
 	mm->get_unmapped_area = arch_get_unmapped_area;
diff -Nru linux-2.6.21.5.ORIG/drivers/char/random.c linux-2.6.21.5/drivers/char/random.c
--- linux-2.6.21.5.ORIG/drivers/char/random.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/drivers/char/random.c	2007-06-24 19:04:03.000000000 +0200
@@ -437,6 +437,9 @@
 	.pool = nonblocking_pool_data
 };
 
+static u32 entropycache_shared[8] __read_mostly;
+static DEFINE_PER_CPU(unsigned long , entropycache_pcpu)[16 / sizeof(unsigned long)];
+
 /*
  * This function adds a byte into the entropy "pool".  It does not
  * update the entropy estimate.  The caller should call
@@ -1455,6 +1458,10 @@
 	keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS;
 	smp_wmb();
 	ip_cnt++;
+
+	/* initialize the shared part of the entropy cache */
+	get_random_bytes(entropycache_shared, sizeof(entropycache_shared));
+
 	schedule_delayed_work(&rekey_work, REKEY_INTERVAL);
 }
 
@@ -1637,20 +1644,17 @@
 
 
 /*
- * Get a random word for internal kernel use only. Similar to urandom but
- * with the goal of minimal entropy pool depletion. As a result, the random
- * value is not cryptographically secure but for several uses the cost of
- * depleting entropy is too high
+ * get_random_long() returns a randomized unsigned long word.
+ * The entropy cache is refreshed periodically in rekey_seq_generator.
+ * This function uses half_md4_transform to generate a unique return value
+ * and is not intended for strong cryptographic routines.
  */
-unsigned int get_random_int(void)
+unsigned long get_random_long(void)
 {
-	/*
-	 * Use IP's RNG. It suits our purpose perfectly: it re-keys itself
-	 * every second, from the entropy pool (and thus creates a limited
-	 * drain on it), and uses halfMD4Transform within the second. We
-	 * also mix it with jiffies and the PID:
-	 */
-	return secure_ip_id((__force __be32)(current->pid + jiffies));
+	half_md4_transform((u32 *)__get_cpu_var(entropycache_pcpu),
+				entropycache_shared);
+
+	return __get_cpu_var(entropycache_pcpu)[0];
 }
 
 /*
@@ -1669,5 +1673,5 @@
 
 	if (end <= start + len)
 		return 0;
-	return PAGE_ALIGN(get_random_int() % range + start);
+	return PAGE_ALIGN(get_random_long() % range + start);
 }
diff -Nru linux-2.6.21.5.ORIG/fs/binfmt_elf.c linux-2.6.21.5/fs/binfmt_elf.c
--- linux-2.6.21.5.ORIG/fs/binfmt_elf.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/fs/binfmt_elf.c	2007-06-24 19:04:24.000000000 +0200
@@ -200,7 +200,8 @@
 	NEW_AUX_ENT(AT_EUID, tsk->euid);
 	NEW_AUX_ENT(AT_GID, tsk->gid);
 	NEW_AUX_ENT(AT_EGID, tsk->egid);
- 	NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
+	NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
+	NEW_AUX_ENT(AT_ENTROPY, get_random_long());
 	if (k_platform) {
 		NEW_AUX_ENT(AT_PLATFORM,
 			    (elf_addr_t)(unsigned long)u_platform);
@@ -516,7 +517,7 @@
 
 	if ((current->flags & PF_RANDOMIZE) &&
 		!(current->personality & ADDR_NO_RANDOMIZE)) {
-		random_variable = get_random_int() & STACK_RND_MASK;
+		random_variable = get_random_long() & STACK_RND_MASK;
 		random_variable <<= PAGE_SHIFT;
 	}
 #ifdef CONFIG_STACK_GROWSUP
diff -Nru linux-2.6.21.5.ORIG/include/linux/auxvec.h linux-2.6.21.5/include/linux/auxvec.h
--- linux-2.6.21.5.ORIG/include/linux/auxvec.h	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/include/linux/auxvec.h	2007-06-24 17:39:12.000000000 +0200
@@ -24,8 +24,9 @@
 #define AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
 #define AT_CLKTCK 17	/* frequency at which times() increments */
 
-#define AT_SECURE 23   /* secure mode boolean */
+#define AT_SECURE 23	/* secure mode boolean */
+#define AT_ENTROPY 24	/* kernel entropy in auxv */
 
-#define AT_VECTOR_SIZE  44 /* Size of auxiliary table.  */
+#define AT_VECTOR_SIZE  45 /* Size of auxiliary table.  */
 
 #endif /* _LINUX_AUXVEC_H */
diff -Nru linux-2.6.21.5.ORIG/include/linux/random.h linux-2.6.21.5/include/linux/random.h
--- linux-2.6.21.5.ORIG/include/linux/random.h	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/include/linux/random.h	2007-06-24 18:19:54.000000000 +0200
@@ -66,7 +66,7 @@
 extern const struct file_operations random_fops, urandom_fops;
 #endif
 
-unsigned int get_random_int(void);
+unsigned long get_random_long(void);
 unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
 
 u32 random32(void);
diff -Nru linux-2.6.21.5.ORIG/kernel/fork.c linux-2.6.21.5/kernel/fork.c
--- linux-2.6.21.5.ORIG/kernel/fork.c	2007-06-11 20:37:06.000000000 +0200
+++ linux-2.6.21.5/kernel/fork.c	2007-06-24 19:05:00.000000000 +0200
@@ -180,7 +180,7 @@
 	setup_thread_stack(tsk, orig);
 
 #ifdef CONFIG_CC_STACKPROTECTOR
-	tsk->stack_canary = get_random_int();
+	tsk->stack_canary = get_random_long();
 #endif
 
 	/* One for us, one for whoever does the "release_task()" (usually parent) */

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

* Re: [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-24 17:45             ` Alexander Gabert
@ 2007-06-25  3:45               ` Matt Mackall
  2007-06-25  4:43                 ` Arjan van de Ven
  2007-06-25 15:02                 ` Alexander Gabert
  0 siblings, 2 replies; 17+ messages in thread
From: Matt Mackall @ 2007-06-25  3:45 UTC (permalink / raw)
  To: Alexander Gabert
  Cc: linux-kernel, torvalds, Arjan van de Ven, libc-alpha, hardened

On Sun, Jun 24, 2007 at 07:45:04PM +0200, Alexander Gabert wrote:
> Hi Linus,
> hi LKML,
> 
> i would like to thank LKML and especially Eric (thanks for the per_cpu 
> macro tips and design guidelines!) and the other contributors to this idea.
> 
> This time the patch is rather big because it also removes 
> get_random_int() and introduces get_random_long() throughout the kernel.

Stop right there. You still haven't answered my original question.
What is the point of this exercise in the first place, please?

Am I right in thinking you have three unrelated patches here?

- something to do with aux vector headers
- something to do with get_random_int repeating itself
- sweeping change of get_random_int to get_random_long for no obvious reason

These should be three completely separate patches.

> My findings with get_random_int was that when i called it two times very 
> fast after another because of setting up two SSP randomized guard values 
> for the same process, it returned the same, yet randomized, integer number.

Send me a patch that fixes the above and nothing else, please.

Then we can talk about another patch to change things to get_random_long.

> --- linux-2.6.21.5.ORIG/arch/sparc64/kernel/sys_sparc.c	2007-06-11 
> 20:37:06.000000000 +0200
> +++ linux-2.6.21.5/arch/sparc64/kernel/sys_sparc.c	2007-06-24 
> 19:01:44.000000000 +0200
> @@ -362,7 +362,7 @@
> 	unsigned long random_factor = 0UL;
> 
> 	if (current->flags & PF_RANDOMIZE) {
> -		random_factor = get_random_int();
> +		random_factor = get_random_long();

This probably breaks Sparc64.

-- 
Mathematics is the supreme nostalgia of our time.

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

* Re: [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-25  3:45               ` Matt Mackall
@ 2007-06-25  4:43                 ` Arjan van de Ven
  2007-06-25  5:12                   ` Matt Mackall
  2007-06-25  7:09                   ` Jakub Jelinek
  2007-06-25 15:02                 ` Alexander Gabert
  1 sibling, 2 replies; 17+ messages in thread
From: Arjan van de Ven @ 2007-06-25  4:43 UTC (permalink / raw)
  To: Matt Mackall
  Cc: Alexander Gabert, linux-kernel, torvalds, libc-alpha, hardened

On Sun, 2007-06-24 at 22:45 -0500, Matt Mackall wrote:
> On Sun, Jun 24, 2007 at 07:45:04PM +0200, Alexander Gabert wrote:
> > Hi Linus,
> > hi LKML,
> > 
> > i would like to thank LKML and especially Eric (thanks for the per_cpu 
> > macro tips and design guidelines!) and the other contributors to this idea.
> > 
> > This time the patch is rather big because it also removes 
> > get_random_int() and introduces get_random_long() throughout the kernel.
> 
> Stop right there. You still haven't answered my original question.
> What is the point of this exercise in the first place, please?
> 
> Am I right in thinking you have three unrelated patches here?
> 
> - something to do with aux vector headers

the primary goal is to pass a random value to userspace at process
start; this to save glibc from having to open /dev/urandom on ever
program start (which it does now for all apps compiled with
-fstack-protector, which in various distros is "everything").

> - sweeping change of get_random_int to get_random_long for no obvious reason

and this is because Alexander wants 2 and not 1 random int to be passed
for his own glibc proposed change (combined with get_random_int() being
designed for only 4 bytes per process ;-)

-- 
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org


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

* Re: [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-25  4:43                 ` Arjan van de Ven
@ 2007-06-25  5:12                   ` Matt Mackall
  2007-06-25  7:09                   ` Jakub Jelinek
  1 sibling, 0 replies; 17+ messages in thread
From: Matt Mackall @ 2007-06-25  5:12 UTC (permalink / raw)
  To: Arjan van de Ven
  Cc: Alexander Gabert, linux-kernel, torvalds, libc-alpha, hardened

On Sun, Jun 24, 2007 at 09:43:03PM -0700, Arjan van de Ven wrote:
> On Sun, 2007-06-24 at 22:45 -0500, Matt Mackall wrote:
> > On Sun, Jun 24, 2007 at 07:45:04PM +0200, Alexander Gabert wrote:
> > > Hi Linus,
> > > hi LKML,
> > > 
> > > i would like to thank LKML and especially Eric (thanks for the per_cpu 
> > > macro tips and design guidelines!) and the other contributors to this idea.
> > > 
> > > This time the patch is rather big because it also removes 
> > > get_random_int() and introduces get_random_long() throughout the kernel.
> > 
> > Stop right there. You still haven't answered my original question.
> > What is the point of this exercise in the first place, please?
> > 
> > Am I right in thinking you have three unrelated patches here?
> > 
> > - something to do with aux vector headers
> 
> the primary goal is to pass a random value to userspace at process
> start; this to save glibc from having to open /dev/urandom on ever
> program start (which it does now for all apps compiled with
> -fstack-protector, which in various distros is "everything").

Interesting.

What are our requirements here? Defending against local attackers who
can build exploits on the fly probably means something stronger than get_random_int.
 
> > - sweeping change of get_random_int to get_random_long for no obvious reason
> 
> and this is because Alexander wants 2 and not 1 random int to be passed
> for his own glibc proposed change (combined with get_random_int() being
> designed for only 4 bytes per process ;-)

Sure. Still, separate patches.

-- 
Mathematics is the supreme nostalgia of our time.

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

* Re: [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-25  4:43                 ` Arjan van de Ven
  2007-06-25  5:12                   ` Matt Mackall
@ 2007-06-25  7:09                   ` Jakub Jelinek
  1 sibling, 0 replies; 17+ messages in thread
From: Jakub Jelinek @ 2007-06-25  7:09 UTC (permalink / raw)
  To: Arjan van de Ven
  Cc: Matt Mackall, Alexander Gabert, linux-kernel, torvalds,
	libc-alpha, hardened

On Sun, Jun 24, 2007 at 09:43:03PM -0700, Arjan van de Ven wrote:
> > - something to do with aux vector headers
> 
> the primary goal is to pass a random value to userspace at process
> start; this to save glibc from having to open /dev/urandom on ever
> program start (which it does now for all apps compiled with
> -fstack-protector, which in various distros is "everything").

There are 2 ways to compile -fstack-protector supporting glibc actually,
only one opens /dev/urandom on every program initialization, the other
computes the stack guard from some bits of the stack address (so indirectly
depends on get_random_int() in stack randomization).
Nevertheless, having one random long (32-bit for 32-bit arches, 64-bit
otherwise) in aux vector would be useful.

	Jakub

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

* Re: [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-25  3:45               ` Matt Mackall
  2007-06-25  4:43                 ` Arjan van de Ven
@ 2007-06-25 15:02                 ` Alexander Gabert
  2007-06-25 15:20                   ` Matt Mackall
  1 sibling, 1 reply; 17+ messages in thread
From: Alexander Gabert @ 2007-06-25 15:02 UTC (permalink / raw)
  To: Matt Mackall
  Cc: linux-kernel, torvalds, Arjan van de Ven, libc-alpha, hardened

Hi Matt,
sorry for not answering your questions in the first place, i hope this 
did not mean to make a bad impression
Matt Mackall schrieb:
> On Sun, Jun 24, 2007 at 07:45:04PM +0200, Alexander Gabert wrote:
>   
>> Hi Linus,
>> hi LKML,
>>
>> i would like to thank LKML and especially Eric (thanks for the per_cpu 
>> macro tips and design guidelines!) and the other contributors to this idea.
>>
>> This time the patch is rather big because it also removes 
>> get_random_int() and introduces get_random_long() throughout the kernel.
>>     
>
> Stop right there. You still haven't answered my original question.
> What is the point of this exercise in the first place, please?
>
> Am I right in thinking you have three unrelated patches here?
>   
I don't think so but you may be right nonetheless if my opinion.
> - something to do with aux vector headers
>   
Adding the new field
> - something to do with get_random_int repeating itself
>   
Found while adding the new field and testing it.
> - sweeping change of get_random_int to get_random_long for no obvious reason
>   
It is needed for properly initializing a SSP guard which is (afaik) a 
long value.
> These should be three completely separate patches.
>   
Probably ... but bear in mind that the goal is still the same: allowing 
glibc to use SSP with /proc/self/auxv instead of fopen(/dev/urandom) as 
it is now.
Effectively saving three syscalls (open,read,close) and making life 
easier for glibc because randomization "generated" in the kernel does 
not deplete /dev/urandom too much for high coverage SSP userlands (i.e. 
Gentoo Hardened).

I can imagine that Redhat would do the same with the SSP implementation 
in glibc, i think if this patch moves into kernel, they will bring out a 
glibc patch that is checking for AT_ENTROPY and using the opening of 
/dev/urandom for retrieving randomized data as a fallback for machines 
where such a kernel is not available.  This is a win-win situation for 
both sides- the kernel wins because the pressure on /dev/urandom is 
released a bit (applicable to SSP environments) and the glibc wins 
because it has a reliable, fast, cheap and easy to use source for 
randomization.


Thank you,

Alex


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

* Re: [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5
  2007-06-25 15:02                 ` Alexander Gabert
@ 2007-06-25 15:20                   ` Matt Mackall
  0 siblings, 0 replies; 17+ messages in thread
From: Matt Mackall @ 2007-06-25 15:20 UTC (permalink / raw)
  To: Alexander Gabert
  Cc: linux-kernel, torvalds, Arjan van de Ven, libc-alpha, hardened

On Mon, Jun 25, 2007 at 05:02:01PM +0200, Alexander Gabert wrote:
> >Am I right in thinking you have three unrelated patches here?
> >  
> I don't think so but you may be right nonetheless if my opinion.

The point is: the way we do development here is to break things down
into a series of simple, obvious pieces and send them individually.
Each patch should build and run when applied on top of the earlier
patches. Then each part can be reviewed, tested, and applied on its
own. It also makes figuring out what happened in the future and
tracking down bugs much easier.

So send three patches in this order:

- fix get_random_int
- rename it
- add auxv bits

Also, you might want to drop Linus from the cc: list unless he's
chimed in on this topic already. The likely path here is for the first
two patches to go through me and the last to go through Arjan, then on
to Andrew Morton for his -mm tree, and then to Linus after a bit.

-- 
Mathematics is the supreme nostalgia of our time.

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

end of thread, other threads:[~2007-06-25 15:20 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-17 23:40 AT_ENTROPY1 and AT_ENTROPY2 values for include/linux/auxvec.h Alexander Gabert
2007-06-18  1:06 ` Arjan van de Ven
2007-06-18  1:28   ` Alexander Gabert
2007-06-18  1:38     ` Arjan van de Ven
2007-06-18 10:36       ` Alexander Gabert
2007-06-20 15:34         ` [PATCH] get_random_long() and AT_ENTROPY for auxv, kernel 2.6.21.5 Alexander Gabert
2007-06-20 15:38           ` Arjan van de Ven
2007-06-20 16:39           ` Linus Torvalds
2007-06-20 17:04           ` Eric Dumazet
2007-06-20 20:30           ` Matt Mackall
2007-06-24 17:45             ` Alexander Gabert
2007-06-25  3:45               ` Matt Mackall
2007-06-25  4:43                 ` Arjan van de Ven
2007-06-25  5:12                   ` Matt Mackall
2007-06-25  7:09                   ` Jakub Jelinek
2007-06-25 15:02                 ` Alexander Gabert
2007-06-25 15:20                   ` Matt Mackall

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).