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.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ