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
#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;
}

Reply via email to