Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 22 Jun 2017 14:18:33 +0200
From: Marcus Meissner <meissner@...e.de>
To: oss-security@...ts.openwall.com
Cc: Vasily Averin <vvs@...tuozzo.com>,
	Konstantin Khorenko <khorenko@...tuozzo.com>
Subject: Re: stackguard fix in Red Hat and Ubuntu kernels

Hi,

Yes, we at SUSE are seeing similar crashes. Thanks for the reproducer!

Ciao, Marcus
On Thu, Jun 22, 2017 at 02:13:30PM +0200, Solar Designer wrote:
> I think the below should be in here regardless of whether it was already
> known or not, so forwarding.
> 
> I've re-attached the reproducer program.
> 
> Thanks, Vasily and Konstantin.
> 
> (And yes, I've verified that both Vasily's and Konstantin's e-mail
> addresses here were already publicly known.  It's something everyone
> should do before forwarding stuff to a public mailing list.)
> 
> ----- Forwarded message from Vasily Averin <vvs@...tuozzo.com> -----
> 
> From: Vasily Averin <vvs@...tuozzo.com>
> To: Solar Designer <solar@...nwall.com>
> Cc: Konstantin Khorenko <khorenko@...tuozzo.com>
> Subject: stackguard fix in RedHat and Ubuntu kernels
> Date: Thu, 22 Jun 2017 14:40:02 +0300
> 
> Dear Alexander,
> probably it is already known,
> otherwise please share it in oss-security@
> I've noticed the problem on Red Hat kernels first, and reported to Red Hat already,
> but now I've found the same problem on Ubuntu kernels.
> It does not affect mainline patch "mm: larger stack guard gap, between vmas"
> but seems distributors have used some other incorrect patch (shared in linux-distros@ ??? )
> 
> Description of problem:
> mmap(MAP_GROUWSDOWN) works incorrectly on Red Hat and Ubuntu kernels with stackguard fix.
> 
> We have application that creates stack by using MAP_GROUWSDOWN , provide this area into clone(), 
> where it fails on access to mapped area.
> 
> Steps to Reproduce:
> execute attached reproducer.
> It maps 2 pages with MAP_GROUWSDOWN, an access to 2nd page mapped page triggers SIGBUS or SIGSEGV
> 
> Actual results:
> - access to end of mapped area generated SIGBUS or SIGSEGV
> - /proc/<pid>/maps shows incorrect start address for allocated area
> please see details below
> 
> Expected results:
> on previous Ubuntu/RHEL kernels this testcase works well without crashes
> http://man7.org/linux/man-pages/man2/mmap.2.html
> 
>        MAP_GROWSDOWN
>               This flag is used for stacks.  It indicates to the kernel
>               virtual memory system that the mapping should extend downward
>               in memory.  The return address is one page lower than the
>               memory area that is actually created in the process's virtual
>               address space.  Touching an address in the "guard" page below
>               the mapping will cause the mapping to grow by a page.  This
>               growth can be repeated until the mapping grows to within a
>               page of the high end of the next lower mapping, at which point
>               touching the "guard" page will result in a SIGSEGV signal.
> 
> On new Ubuntu kernel 4.4.0-81-generic (with stackguard fix)
> 
> 20	        unsigned char *stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
> (gdb) n
> 
> (changes in /proc/<pid>/maps)
>  7ffff7dd3000-7ffff7dd7000 rw-p 00000000 00:00 0 
>  7ffff7dd7000-7ffff7dfd000 r-xp 00000000 fc:00 524776                     /lib/x86_64-linux-gnu/ld-2.23.so
>  7ffff7feb000-7ffff7fee000 rw-p 00000000 00:00 0 
> +7ffff80f4000-7ffff7ff6000 rw-p 00000000 00:00 0  <<<< incorrect start address is shown here 
>  7ffff7ff6000-7ffff7ff8000 rw-p 00000000 00:00 0 
>  7ffff7ff8000-7ffff7ffa000 r--p 00000000 00:00 0                          [vvar]
>  7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]
> 
> 23		printf("stack = %p\n", stack);
> (gdb) n
> stack = 0x7ffff7ff4000
> 24		end = stack + STACK_SIZE - 8;
> (gdb) n
> 25		printf("end = %p\n", end);
> (gdb) n
> end = 0x7ffff7ff5ff8
> 26		printf("write to *end\n");
> (gdb) n
> write to *end
> 27		*end = 0;
> (gdb) n
> 
> Program received signal SIGSEGV, Segmentation fault.
> 0x000000000040062f in main () at sk.c:27
> 
> 
> on Ubuntu 4.4.0-79-generic  -- works as expected
> 
> mmap return address of guard page,
> access to end of mapped area works works correctly,
> touch on guard page grows stack down,
> then touch of previous page grows stack down again.
> 
> 20	        unsigned char *stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
> (gdb) n
> 23		printf("stack = %p\n", stack);
> (gdb) n
> stack = 0x7ffff7ff4000
> 
>  7ffff7dd3000-7ffff7dd7000 rw-p 00000000 00:00 0 
>  7ffff7dd7000-7ffff7dfd000 r-xp 00000000 08:01 27001906                   /lib/x86_64-linux-gnu/ld-2.23.so
>  7ffff7fc8000-7ffff7fcb000 rw-p 00000000 00:00 0 
> +7ffff7ff5000-7ffff7ff6000 rw-p 00000000 00:00 0 
>  7ffff7ff6000-7ffff7ff8000 rw-p 00000000 00:00 0 
>  7ffff7ff8000-7ffff7ffa000 r--p 00000000 00:00 0                          [vvar]
>  7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]
> 
> 24		end = stack + STACK_SIZE - 8;
> (gdb) n
> 25		printf("end = %p\n", end);
> (gdb) n
> end = 0x7ffff7ff5ff8
> 26		printf("write to *end\n");
> (gdb) n
> write to *end
> 27		*end = 0;
> (gdb) n
> 28		printf("write to *stack\n");
> (gdb) n
> write to *stack
> 29		*(stack) = 0;
> (gdb) n
> 
> -7ffff7ff5000-7ffff7ff6000 rw-p 00000000 00:00 0 
> +7ffff7ff4000-7ffff7ff6000 rw-p 00000000 00:00 0   <<<< Stack grow down
> 
> 30		printf("write to *(stack-1)\n");
> (gdb) n
> write to *(stack-1)
> 31		*(stack-1) = 0;
> (gdb) n
> 32	}
> 
> -7ffff7ff4000-7ffff7ff6000 rw-p 00000000 00:00 0 
> +7ffff7ff3000-7ffff7ff6000 rw-p 00000000 00:00 0 <<<< Stack grows down again
> 
> ----- End forwarded message -----

> 
> #define _GNU_SOURCE
> 
> #include <stdio.h>
> #include <errno.h>
> #include <string.h>
> #include <unistd.h>
> #include <stdlib.h>
> #include <sys/stat.h>
> #include <sys/types.h>
> #include <sys/param.h>
> #include <sys/mman.h>
> 
> #define STACK_SIZE	2*4096
> 
> int main()
> {
> 	unsigned char *end;
> 	/* Allocate stack */
>         unsigned char *stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
> 			MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN, 0, 0);
> 
> 	printf("stack = %p\n", stack);
> 	end = stack + STACK_SIZE - 8;
> 	printf("end = %p\n", end);
> 	printf("write to *end\n");
> 	*end = 0;
> 	printf("write to *stack\n");
> 	*(stack) = 0;
> 	printf("write to *(stack-1)\n");
> 	*(stack-1) = 0;
> }


-- 
Marcus Meissner,SUSE LINUX GmbH; Maxfeldstrasse 5; D-90409 Nuernberg; Zi. 3.1-33,+49-911-740 53-432,,serv=loki,mail=wotan,type=real <meissner@...e.de>

Powered by blists - more mailing lists

Your e-mail address:

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.