unofficial mirror of libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* Thread stack and heap caches - CVE-2019-1010024
@ 2019-11-04 11:09 Vinay Kumar
  2019-11-04 12:25 ` Florian Weimer
  2019-11-25 18:10 ` Florian Weimer
  0 siblings, 2 replies; 6+ messages in thread
From: Vinay Kumar @ 2019-11-04 11:09 UTC (permalink / raw)
  To: libc-alpha; +Cc: fweimer, carlos

Hi,

Regarding bug related to Thread stack and heap caches (CVE-2019-1010024).
https://sourceware.org/bugzilla/show_bug.cgi?id=22852

>> One way to harden is to use a tunable for a thread stack cache, and set that to zero.
Below change in glibc allocatestack.c file gives the expected output
with test case. Verified on x86_64 target.
=======================================================
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -186,6 +186,7 @@ get_cached_stack (size_t *sizep, void **memp)
       struct pthread *curr;

       curr = list_entry (entry, struct pthread, list);
+      curr->stackblock_size = 0;
       if (FREE_P (curr) && curr->stackblock_size >= size)
        {
          if (curr->stackblock_size == size)
=======================================================

Output with above patch in glibc trunk:

strace -e mmap,munmap ./thread.out
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x7f387b0df000
mmap(NULL, 139704, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f387b0bc000
mmap(0x7f387b0c3000, 65536, PROT_READ|PROT_EXEC,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x7000) = 0x7f387b0c3000
mmap(0x7f387b0d3000, 20480, PROT_READ,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17000) = 0x7f387b0d3000
mmap(0x7f387b0d9000, 8192, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c000) = 0x7f387b0d9000
mmap(0x7f387b0db000, 12728, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f387b0db000
mmap(NULL, 1774424, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f387af0a000
mmap(0x7f387af2f000, 1277952, PROT_READ|PROT_EXEC,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7f387af2f000
mmap(0x7f387b067000, 303104, PROT_READ,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15d000) = 0x7f387b067000
mmap(0x7f387b0b2000, 24576, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a7000) = 0x7f387b0b2000
mmap(0x7f387b0b8000, 13144, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f387b0b8000
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x7f387af07000
mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK,
-1, 0) = 0x7f387a706000
addr: 0x7f387af03ee0
value deadbeef
malloced 0x7f3874000f70
mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK,
-1, 0) = 0x7f3879f05000
addr: 0x7f387a702ee0
value 0
malloced 0x7f3874000f70
+++ exited with 0 +++

Re-sending due to bounce back of previous mail.

Regards,
Vinay

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

* Re: Thread stack and heap caches - CVE-2019-1010024
  2019-11-04 11:09 Thread stack and heap caches - CVE-2019-1010024 Vinay Kumar
@ 2019-11-04 12:25 ` Florian Weimer
  2019-11-11 10:56   ` Vinay Kumar
  2019-11-25 18:10 ` Florian Weimer
  1 sibling, 1 reply; 6+ messages in thread
From: Florian Weimer @ 2019-11-04 12:25 UTC (permalink / raw)
  To: Vinay Kumar; +Cc: libc-alpha, carlos

* Vinay Kumar:

> Regarding bug related to Thread stack and heap caches (CVE-2019-1010024).
> https://sourceware.org/bugzilla/show_bug.cgi?id=22852
>
>>> One way to harden is to use a tunable for a thread stack cache, and set that to zero.
> Below change in glibc allocatestack.c file gives the expected output
> with test case. Verified on x86_64 target.
> =======================================================
> --- a/nptl/allocatestack.c
> +++ b/nptl/allocatestack.c
> @@ -186,6 +186,7 @@ get_cached_stack (size_t *sizep, void **memp)
>        struct pthread *curr;
>
>        curr = list_entry (entry, struct pthread, list);
> +      curr->stackblock_size = 0;
>        if (FREE_P (curr) && curr->stackblock_size >= size)
>         {
>           if (curr->stackblock_size == size)
> =======================================================

Does this really change the randomization?  Won't the kernel map the new
stack at a predictable address, too?

Thanks,
Florian


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

* Re: Thread stack and heap caches - CVE-2019-1010024
  2019-11-04 12:25 ` Florian Weimer
@ 2019-11-11 10:56   ` Vinay Kumar
  2019-11-25 16:43     ` Vinay Kumar
  0 siblings, 1 reply; 6+ messages in thread
From: Vinay Kumar @ 2019-11-11 10:56 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, carlos

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

Hi Florian,

>> Does this really change the randomization?  Won't the kernel map the new
>> stack at a predictable address, too?

Yes, every time new address is assigned as shown in the below
iterations of output.
Also the attached patch "aslr_glibc.patch" adds glibc configuration
option "--with-aslr" to enable randomization.

Compilation command:
$x86_64-windriver-linux-gcc test.c -g -fpie -pie -Xlinker
-rpath=/home/x86_64-tc/prefix-aslr//x86_64-windriver-linux/lib
-Xlinker -I /home
/x86_64-tc/prefix-aslr/x86_64-windriver-linux/lib/ld-2.30.9000.so -w
-lpthread -o thread.out

Output:

Trial 1:
./thread.out
addr: 0x7f15252bfee0
value deadbeef
malloced 0x7f1520000f70
addr: 0x7f1524abeee0
value 0
malloced 0x7f1520000f70

Trial 2:
./thread.out
addr: 0x7f9091640ee0
value deadbeef
malloced 0x7f908c000f70
addr: 0x7f9090e3fee0
value 0
malloced 0x7f908c000f70

Trial 3:
./thread.out
addr: 0x7f0d923dfee0
value deadbeef
malloced 0x7f0d8c000f70
addr: 0x7f0d91bdeee0
value 0
malloced 0x7f0d8c000f70

Trial 4:
./thread.out
addr: 0x7f146d97dee0
value deadbeef
malloced 0x7f1468000f70
addr: 0x7f146d17cee0
value 0
malloced 0x7f1468000f70

Regards,
Vinay

[-- Attachment #2: aslr_glibc.patch --]
[-- Type: application/octet-stream, Size: 2654 bytes --]

diff --git a/config.h.in b/config.h.in
index 824dfe8..649833e 100644
--- a/config.h.in
+++ b/config.h.in
@@ -255,6 +255,9 @@
 /* PowerPC32 uses fctidz for floating point to long long conversions.  */
 #define HAVE_PPC_FCTIDZ 0
 
+/* Build glibc with ASLR enabled*/
+#define ASLR_ENABLE 0
+
 /* Build glibc with tunables support.  */
 #define HAVE_TUNABLES 0
 
diff --git a/configure b/configure
index 2f44b66..f26d8bd 100755
--- a/configure
+++ b/configure
@@ -688,6 +688,7 @@ enable_timezone_tools
 extra_nonshared_cflags
 use_default_link
 sysheaders
+with_aslr
 ac_ct_CXX
 CXXFLAGS
 CXX
@@ -762,6 +763,7 @@ with_gd_include
 with_gd_lib
 with_binutils
 with_selinux
+with_aslr
 with_headers
 with_default_link
 with_nonshared_cflags
@@ -1482,6 +1484,7 @@ Optional Packages:
   --with-gd-lib=DIR       find libgd library files in DIR
   --with-binutils=PATH    specify location of binutils (as and ld)
   --with-selinux          if building with SELinux support
+  --with-aslr             if building with ASLR support
   --with-headers=PATH     location of system headers to use (for example
                           /usr/src/linux/include) [default=compiler default]
   --with-default-link     do not use explicit linker scripts
@@ -3324,6 +3327,20 @@ else
 fi
 
 
+# Check whether --with-aslr was given.
+if test "${with_aslr+set}" = set; then :
+  withval=$with_aslr; with_aslr=$withval
+else
+  with_aslr=auto
+fi
+
+
+if test "$with_aslr" = yes; then
+  $as_echo "#define ASLR_ENABLE 1" >>confdefs.h
+
+fi
+
+
 
 # Check whether --with-headers was given.
 if test "${with_headers+set}" = set; then :
diff --git a/configure.ac b/configure.ac
index e69c88c..74429b5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -138,6 +138,16 @@ AC_ARG_WITH([selinux],
 			   [if building with SELinux support]),
 	    [with_selinux=$withval],
 	    [with_selinux=auto])
+AC_ARG_WITH([aslr],
+	    AC_HELP_STRING([--with-aslr],
+			   [if building with ASLR support]),
+	    [with_aslr=$withval],
+	    [with_aslr=auto])
+AC_SUBST(with_aslr)
+if test "$with_aslr" = yes; then
+  AC_DEFINE(ASLR_ENABLE)
+fi
+
 
 AC_ARG_WITH([headers],
 	    AC_HELP_STRING([--with-headers=PATH],
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index 64a9ae6..11e5685 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -544,7 +544,9 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 
       /* Try to get a stack from the cache.  */
       reqsize = size;
+      #if !ASLR_ENABLE	
       pd = get_cached_stack (&size, &mem);
+      #endif 	
       if (pd == NULL)
 	{
 	  /* To avoid aliasing effects on a larger scale than pages we

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

* Re: Thread stack and heap caches - CVE-2019-1010024
  2019-11-11 10:56   ` Vinay Kumar
@ 2019-11-25 16:43     ` Vinay Kumar
  0 siblings, 0 replies; 6+ messages in thread
From: Vinay Kumar @ 2019-11-25 16:43 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, carlos

Hi Florian,

Could you please review the last post on randomization.
Bugzilla link : https://sourceware.org/bugzilla/show_bug.cgi?id=22852

Thanks and Regards,
Vinay



On Mon, Nov 11, 2019 at 4:26 PM Vinay Kumar <vinay.m.engg@gmail.com> wrote:
>
> Hi Florian,
>
> >> Does this really change the randomization?  Won't the kernel map the new
> >> stack at a predictable address, too?
>
> Yes, every time new address is assigned as shown in the below
> iterations of output.
> Also the attached patch "aslr_glibc.patch" adds glibc configuration
> option "--with-aslr" to enable randomization.
>
> Compilation command:
> $x86_64-windriver-linux-gcc test.c -g -fpie -pie -Xlinker
> -rpath=/home/x86_64-tc/prefix-aslr//x86_64-windriver-linux/lib
> -Xlinker -I /home
> /x86_64-tc/prefix-aslr/x86_64-windriver-linux/lib/ld-2.30.9000.so -w
> -lpthread -o thread.out
>
> Output:
>
> Trial 1:
> ./thread.out
> addr: 0x7f15252bfee0
> value deadbeef
> malloced 0x7f1520000f70
> addr: 0x7f1524abeee0
> value 0
> malloced 0x7f1520000f70
>
> Trial 2:
> ./thread.out
> addr: 0x7f9091640ee0
> value deadbeef
> malloced 0x7f908c000f70
> addr: 0x7f9090e3fee0
> value 0
> malloced 0x7f908c000f70
>
> Trial 3:
> ./thread.out
> addr: 0x7f0d923dfee0
> value deadbeef
> malloced 0x7f0d8c000f70
> addr: 0x7f0d91bdeee0
> value 0
> malloced 0x7f0d8c000f70
>
> Trial 4:
> ./thread.out
> addr: 0x7f146d97dee0
> value deadbeef
> malloced 0x7f1468000f70
> addr: 0x7f146d17cee0
> value 0
> malloced 0x7f1468000f70
>
> Regards,
> Vinay

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

* Re: Thread stack and heap caches - CVE-2019-1010024
  2019-11-04 11:09 Thread stack and heap caches - CVE-2019-1010024 Vinay Kumar
  2019-11-04 12:25 ` Florian Weimer
@ 2019-11-25 18:10 ` Florian Weimer
  2019-11-25 18:29   ` Vinay Kumar
  1 sibling, 1 reply; 6+ messages in thread
From: Florian Weimer @ 2019-11-25 18:10 UTC (permalink / raw)
  To: Vinay Kumar; +Cc: libc-alpha, carlos

* Vinay Kumar:

> Hi,
>
> Regarding bug related to Thread stack and heap caches (CVE-2019-1010024).
> https://sourceware.org/bugzilla/show_bug.cgi?id=22852
>
>>> One way to harden is to use a tunable for a thread stack cache, and set that to zero.
> Below change in glibc allocatestack.c file gives the expected output
> with test case. Verified on x86_64 target.
> =======================================================
> --- a/nptl/allocatestack.c
> +++ b/nptl/allocatestack.c
> @@ -186,6 +186,7 @@ get_cached_stack (size_t *sizep, void **memp)
>        struct pthread *curr;
>
>        curr = list_entry (entry, struct pthread, list);
> +      curr->stackblock_size = 0;
>        if (FREE_P (curr) && curr->stackblock_size >= size)
>         {
>           if (curr->stackblock_size == size)
> =======================================================

This will just cause crashes (abort in free_statcks).

I tried to emulate the effect with this program:

#include <err.h>
#include <errno.h>
#include <pthread.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>

static void *
thread (void *closure)
{
  uintptr_t *pp = closure;
  *pp = (uintptr_t) &pp;
  return NULL;
}

int
main (void)
{
  pthread_attr_t attr;
  int ret = pthread_attr_init (&attr);
  if (ret != 0)
    {
      errno = ret;
      err (1, "pthread_attr_init");
    }
  ret = pthread_attr_setstacksize (&attr, 128 * 1024 * 1024);
  if (ret != 0)
    {
      errno = ret;
      err (1, "pthread_attr_setstacksize");
    }

  for (int i = 0; i < 20; ++i)
    {
      pthread_t thr;
      uintptr_t ptr;
      ret = pthread_create (&thr, &attr, thread, &ptr);
      if (ret != 0)
        {
          errno = ret;
          err (1, "pthread_create");
        }
      ret = pthread_join (thr, NULL);
      if (ret != 0)
        {
          errno = ret;
          err (1, "pthread_join");
        }
      printf ("%p\n", (void *) ptr);
    }
}

Its stack size is so large that the stack is never cached.  If you run
it with strace, you will see that mmap and munmap is called for each
iteration.

As I suspected, it prints the same address again and again because the
kernel does NOT randomize mappings.  Until that happens, there is not
much value in disabling the stack cache.

Thanks,
Florian


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

* Re: Thread stack and heap caches - CVE-2019-1010024
  2019-11-25 18:10 ` Florian Weimer
@ 2019-11-25 18:29   ` Vinay Kumar
  0 siblings, 0 replies; 6+ messages in thread
From: Vinay Kumar @ 2019-11-25 18:29 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, carlos

Hi Florian,

Thanks for the feed back.

FYI,
I had posted the new patch with added glibc configure option
"--with-aslr" which we will not call "get_cached_stack" function.
Also I have posted the output with the testcase from bugzilla.

Link : https://sourceware.org/ml/libc-alpha/2019-11/msg00349.html
Patch link : https://sourceware.org/ml/libc-alpha/2019-11/msg00349/aslr_glibc.patch

Will verify your feedback with my new patch and update you on the same.

Thanks and regards,
Vinay

Regards,
Vinay

On Mon, Nov 25, 2019 at 11:40 PM Florian Weimer <fweimer@redhat.com> wrote:
>
> * Vinay Kumar:
>
> > Hi,
> >
> > Regarding bug related to Thread stack and heap caches (CVE-2019-1010024).
> > https://sourceware.org/bugzilla/show_bug.cgi?id=22852
> >
> >>> One way to harden is to use a tunable for a thread stack cache, and set that to zero.
> > Below change in glibc allocatestack.c file gives the expected output
> > with test case. Verified on x86_64 target.
> > =======================================================
> > --- a/nptl/allocatestack.c
> > +++ b/nptl/allocatestack.c
> > @@ -186,6 +186,7 @@ get_cached_stack (size_t *sizep, void **memp)
> >        struct pthread *curr;
> >
> >        curr = list_entry (entry, struct pthread, list);
> > +      curr->stackblock_size = 0;
> >        if (FREE_P (curr) && curr->stackblock_size >= size)
> >         {
> >           if (curr->stackblock_size == size)
> > =======================================================
>
> This will just cause crashes (abort in free_statcks).
>
> I tried to emulate the effect with this program:
>
> #include <err.h>
> #include <errno.h>
> #include <pthread.h>
> #include <stddef.h>
> #include <stdint.h>
> #include <stdio.h>
>
> static void *
> thread (void *closure)
> {
>   uintptr_t *pp = closure;
>   *pp = (uintptr_t) &pp;
>   return NULL;
> }
>
> int
> main (void)
> {
>   pthread_attr_t attr;
>   int ret = pthread_attr_init (&attr);
>   if (ret != 0)
>     {
>       errno = ret;
>       err (1, "pthread_attr_init");
>     }
>   ret = pthread_attr_setstacksize (&attr, 128 * 1024 * 1024);
>   if (ret != 0)
>     {
>       errno = ret;
>       err (1, "pthread_attr_setstacksize");
>     }
>
>   for (int i = 0; i < 20; ++i)
>     {
>       pthread_t thr;
>       uintptr_t ptr;
>       ret = pthread_create (&thr, &attr, thread, &ptr);
>       if (ret != 0)
>         {
>           errno = ret;
>           err (1, "pthread_create");
>         }
>       ret = pthread_join (thr, NULL);
>       if (ret != 0)
>         {
>           errno = ret;
>           err (1, "pthread_join");
>         }
>       printf ("%p\n", (void *) ptr);
>     }
> }
>
> Its stack size is so large that the stack is never cached.  If you run
> it with strace, you will see that mmap and munmap is called for each
> iteration.
>
> As I suspected, it prints the same address again and again because the
> kernel does NOT randomize mappings.  Until that happens, there is not
> much value in disabling the stack cache.
>
> Thanks,
> Florian
>

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

end of thread, other threads:[~2019-11-25 18:29 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-04 11:09 Thread stack and heap caches - CVE-2019-1010024 Vinay Kumar
2019-11-04 12:25 ` Florian Weimer
2019-11-11 10:56   ` Vinay Kumar
2019-11-25 16:43     ` Vinay Kumar
2019-11-25 18:10 ` Florian Weimer
2019-11-25 18:29   ` Vinay Kumar

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 read-only IMAP folder(s) and NNTP newsgroup(s).