Re: [PATCH] mm: larger stack guard gap, between vmas

Michal Hocko
2017-07-04T10:51:37Z

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

On Tue 04-07-17 12:46:52, Michal Hocko wrote:
[...]
> Tested with the attached program.

Err, attached now for real.
--
Michal Hocko
SUSE Labs

[-- Attachment #2: stack_crash.c --]
[-- Type: text/x-csrc, Size: 2471 bytes --]

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <alloca.h>
#include <signal.h>
#include <stdlib.h>

#define PAGE_SIZE sysconf(_SC_PAGESIZE)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define GAP (20UL<<20)
#define SIGNAL_STACK_SIZE (1UL<<20)

#define MAPING_PROT PROT_NONE

void recurse(void)
{
void * ptr = alloca(10);
recurse();
}

#define MAPPED_LEN PAGE_SIZE
static unsigned long mapped_addr;

void segv_handler(int sig, siginfo_t *info, void *data)
{
unsigned long addr = (unsigned long)info->si_addr;
unsigned long mmap_end = mapped_addr + MAPPED_LEN;
unsigned long diff;
char cmd[128];

#ifndef CONFIG_STACK_GROWSUP
diff = addr - mmap_end;
#else
diff = mmap_addr - addr;
#endif
printf("address:0x%lx aligned:0x%lx mapped:[%lx,%lx] diff:%ld\n", addr, addr & PAGE_MASK, mapped_addr, mapped_addr+PAGE_SIZE, (long)diff);
snprintf(cmd, sizeof(cmd) - 1, "cat /proc/%d/smaps | grep -A5 -B21 -A20 '\\[stack\\]'", getpid());
system(cmd);
abort();
}

int main(int argc, char **argv)
{
void *addr;
stack_t signal_stack;
struct sigaction segv_sig = {.sa_sigaction = segv_handler, .sa_flags = SA_ONSTACK|SA_SIGINFO};
int stack_top;
unsigned long mmap_gap = GAP;
struct rlimit rlim = {.rlim_cur = 2*GAP, .rlim_max = RLIM_INFINITY};
unsigned long stack_addr = (unsigned long)&stack_top;

if (argc > 1) {
char *endptr;
mmap_gap = strtoul(argv[1], &endptr, 0);
if (*endptr) {
fprintf(stderr, "Unrecognized mmap gap %s\n", argv[1]);
return 1;
}
}

#ifndef CONFIG_STACK_GROWSUP
mapped_addr = stack_addr-mmap_gap;
#else
mapped_addr = stack_addr+mmap_gap;
#endif
mapped_addr &= PAGE_MASK;
addr = mmap((void *)mapped_addr, MAPPED_LEN,
MAPING_PROT,
MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
if (addr == MAP_FAILED) {
perror("mmap:");
return 1;
}
printf("Stack top:0x%lx mmap:0x%lx\n", stack_addr, mapped_addr);

/* Make sure that our SEGV handler will have a stack to run on */
signal_stack.ss_sp = malloc(SIGNAL_STACK_SIZE);
if (!signal_stack.ss_sp) {
perror("alternate stack allocation");
return 1;
}
signal_stack.ss_size = SIGNAL_STACK_SIZE;
signal_stack.ss_flags = 0;
if (sigaltstack(&signal_stack, NULL) == -1) {
perror("sigaltstack");
return 1;
}
sigaction(SIGSEGV, &segv_sig, NULL);
sigaction(SIGBUS, &segv_sig, NULL);

setrlimit(RLIMIT_STACK, &rlim);
recurse();
/* Should never return */
return 1;
}