Closed seanbruno closed 7 years ago
Sounds like it is going to require a lot of work on qemu-user and will prevent us from from cross-building ports with poudriere for a while, right?
Maybe. I'm looking to see what has to be done now that I have a test program from kib. If this file is built and compiled in a mips64 jail (or any for that matter), it will abort instead of crashing (which it should do).
/* $Id: map_hole.c,v 1.6 2014/06/16 05:52:03 kostik Exp kostik $ */
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ucontext.h>
#include <unistd.h>
#ifndef MAP_GUARD
#define MAP_GUARD 0x00002000 /* no backing pages */
#endif
#if 0
static void
sighandler(int signo, siginfo_t *info, void *uap1)
{
static char scratch;
ucontext_t *uap;
uap = uap1;
printf("SIG%s(%d) at %p (%%eax %p)\n",
signo < sys_nsig ? sys_signame[signo] : "SOME", signo,
info->si_addr, (void *)(uintptr_t)uap->uc_mcontext.mc_eax);
uap->uc_mcontext.mc_eax = (uintptr_t)&scratch;
}
#endif
static void
access_addr(char *addr)
{
char r;
r = '1';
printf("accessing %p\n", addr);
*(volatile char *)addr = 0;
//__asm __volatile("movb %0,(%%eax)" : : "i"(r), "a"(addr) : "memory");
printf("done\n");
}
static int pagesz;
static void
test_access(char *addr)
{
struct rusage ru;
long majflt, minflt;
if (getrusage(RUSAGE_THREAD, &ru) == -1)
err(1, "getrusage");
majflt = ru.ru_majflt;
minflt = ru.ru_minflt;
access_addr(addr);
if (mprotect(addr, pagesz, PROT_READ | PROT_WRITE) == -1)
warn("mprotect");
access_addr(addr);
if (getrusage(RUSAGE_THREAD, &ru) == -1)
err(1, "getrusage");
majflt = ru.ru_majflt - majflt;
minflt = ru.ru_minflt - minflt;
printf("majflt %ld minflt %ld\n", majflt, minflt);
}
int
main(void)
{
// struct sigaction sa;
char *addr;
char cmd[128];
#if 0
bzero(&sa, sizeof(sa));
sa.sa_sigaction = sighandler;
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &sa, NULL) == -1)
err(1, "sigaction");
#endif
pagesz = getpagesize();
printf("MAP_GUARD\n");
addr = mmap(NULL, pagesz, PROT_NONE, MAP_GUARD, -1, 0);
if (addr == (char *)MAP_FAILED)
err(1, "mmap(MAP_GUARD)");
test_access(addr);
printf("PROT_NONE wire\n");
addr = mmap(NULL, pagesz, PROT_NONE, MAP_ANON, -1, 0);
if (addr == (char *)MAP_FAILED)
err(1, "mmap(PROT_NONE)");
if (mlock(addr, pagesz) == -1)
err(1, "mlock");
test_access(addr);
snprintf(cmd, sizeof(cmd), "procstat -v %d", getpid());
system(cmd);
return (0);
}
I think I've fixed this in commit 03c9fa89842557afb9301d4baa7f3d4ef5ac825f
I have a more comprehensive change if you want to take a look. https://github.com/guyyur/qemu-bsd-user/commit/380cfc201bbe99a3a47ec391c477f9fa8fb09bde
qemu assumes MAP_ANONYMOUS is the only case of no fd. MAP_STACK and MAP_GUARD also mean no fd so the code that works on fd only if not MAP_ANONYMOUS needs to take them into account too.
On 07/06/17 16:31, Guy Yur wrote:
I have a more comprehensive change if you want to take a look. guyyur/qemu-bsd-user@380cfc2 https://github.com/guyyur/qemu-bsd-user/commit/380cfc201bbe99a3a47ec391c477f9fa8fb09bde
qemu assumes MAP_ANONYMOUS is the only case of no fd. MAP_STACK and MAP_GUARD also mean no fd so the code that works on fd only if not MAP_ANONYMOUS needs to take them into account too.
This is definitely more complete. I'd still like to leave the "#ifdef MAX_GUARD" checks to use "#ifdef FreeBSD_version" as a bread crumb for a developer in the future, even if they are equivalent.
Want to do that and send me a pull req?
sean
After svn r320318 MAP_GUARD support is mandatory and qemu-user doesn't support it at all. All attempts to MAP_GUARD fail.