Submitted By: Robert Connolly <robert at linuxfromscratch dot org> (ashes)
Date: 2007-04-25
Initial Package Version: 2.5
Upstream Status: From Upstream
Origin: sysdeps/unix/sysv/linux/dl-osinfo.h revision 1.14.2.6
        elf/tst-stackguard1.c revision 1.1.2.3
	nptl/tst-stackguard1.c revision 1.1.2.2
Description: Use high precision timing with SSP if /dev/urandom fails,
and don't let the test suite complain about it.

diff -Naur glibc-2.5.orig/elf/tst-stackguard1.c glibc-2.5/elf/tst-stackguard1.c
--- glibc-2.5.orig/elf/tst-stackguard1.c	2005-06-26 18:08:36.000000000 +0000
+++ glibc-2.5/elf/tst-stackguard1.c	2007-04-25 04:51:38.000000000 +0000
@@ -160,17 +160,21 @@
      the 16 runs, something is very wrong.  */
   int ndifferences = 0;
   int ndefaults = 0;
+  int npartlyrandomized = 0;
   for (i = 0; i < N; ++i) 
     {
       if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1])
 	ndifferences++;
       else if (child_stack_chk_guards[i] == default_guard)
 	ndefaults++;
+      else if (*(char *) &child_stack_chk_guards[i] == 0)
+	npartlyrandomized++;
     }
 
-  printf ("differences %d defaults %d\n", ndifferences, ndefaults);
+  printf ("differences %d defaults %d partly randomized %d\n",
+	  ndifferences, ndefaults, npartlyrandomized);
 
-  if (ndifferences < N / 2 && ndefaults < N / 2)
+  if ((ndifferences + ndefaults + npartlyrandomized) < 3 * N / 4)
     {
       puts ("stack guard canaries are not randomized enough");
       puts ("nor equal to the default canary value");
diff -Naur glibc-2.5.orig/nptl/tst-stackguard1.c glibc-2.5/nptl/tst-stackguard1.c
--- glibc-2.5.orig/nptl/tst-stackguard1.c	2005-06-26 17:44:14.000000000 +0000
+++ glibc-2.5/nptl/tst-stackguard1.c	2007-04-25 04:53:20.000000000 +0000
@@ -190,17 +190,21 @@
      the 16 runs, something is very wrong.  */
   int ndifferences = 0;
   int ndefaults = 0;
+  int npartlyrandomized = 0;
   for (i = 0; i < N; ++i) 
     {
       if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1])
 	ndifferences++;
       else if (child_stack_chk_guards[i] == default_guard)
 	ndefaults++;
+      else if (*(char *) &child_stack_chk_guards[i] == 0)
+	npartlyrandomized++;
     }
 
-  printf ("differences %d defaults %d\n", ndifferences, ndefaults);
+  printf ("differences %d defaults %d partly randomized %d\n",
+	  ndifferences, ndefaults, npartlyrandomized);
 
-  if (ndifferences < N / 2 && ndefaults < N / 2)
+  if ((ndifferences + ndefaults + npartlyrandomized) < 3 * N / 4)
     {
       puts ("stack guard canaries are not randomized enough");
       puts ("nor equal to the default canary value");
diff -Naur glibc-2.5.orig/sysdeps/unix/sysv/linux/dl-osinfo.h glibc-2.5/sysdeps/unix/sysv/linux/dl-osinfo.h
--- glibc-2.5.orig/sysdeps/unix/sysv/linux/dl-osinfo.h	2006-08-01 06:55:27.000000000 +0000
+++ glibc-2.5/sysdeps/unix/sysv/linux/dl-osinfo.h	2007-04-25 04:43:46.000000000 +0000
@@ -18,11 +18,14 @@
    02111-1307 USA.  */
 
 #include <string.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <sys/utsname.h>
 #include <kernel-features.h>
 #include <dl-sysdep.h>
 #include <stdint.h>
+#include <hp-timing.h>
+#include <endian.h>
 
 #ifndef MIN
 # define MIN(a,b) (((a)<(b))?(a):(b))
@@ -176,5 +179,31 @@
   unsigned char *p = (unsigned char *) &ret;
   p[sizeof (ret) - 1] = 255;
   p[sizeof (ret) - 2] = '\n';
+#ifdef HP_TIMING_NOW
+  hp_timing_t hpt;
+  HP_TIMING_NOW (hpt);
+  hpt = (hpt & 0xffff) << 8;
+  ret ^= hpt;
+#endif
+  uintptr_t stk;
+  /* Avoid GCC being too smart.  */
+  asm ("" : "=r" (stk) : "r" (p));
+  stk &= 0x7ffff0;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  stk <<= (__WORDSIZE - 23);
+#elif __WORDSIZE == 64
+  stk <<= 31;
+#endif
+  ret ^= stk;
+  /* Avoid GCC being too smart.  */
+  p = (unsigned char *) &errno;
+  asm ("" : "=r" (stk) : "r" (p));
+  stk &= 0x7fff00;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  stk <<= (__WORDSIZE - 29);
+#else
+  stk >>= 8;
+#endif
+  ret ^= stk;
   return ret;
 }
