Date: Fri, 19 Jan 2007 18:51:03 -0500 From: Jung-uk Kim <jkim@FreeBSD.org> To: freebsd-emulation@FreeBSD.org Subject: A new mmap finger printer Message-ID: <200701191851.08685.jkim@FreeBSD.org>
next in thread | raw e-mail | index | archive | help
--Boundary-00=_slVsFRjAyW28ZgI Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline I added PROT_EXEC test and cleaned up Marcin Cieslak's mmap finger printer. Can any one try this on a real Linux/i386 box and send me the output? Thanks, Jung-uk Kim --Boundary-00=_slVsFRjAyW28ZgI Content-Type: text/plain; charset="iso-8859-1"; name="mmap_test.c" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="mmap_test.c" #include <errno.h> #include <fcntl.h> #include <setjmp.h> #include <signal.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/mman.h> struct intdesc { const int val; const char *desc; }; static sigjmp_buf env; static char nofile[] = "anonymous"; static char testfile[] = "/tmp/test.XXXXXX"; #if defined(__amd64__) || defined(__x86_64__) static char testfunc[] = { 0x55, /* push %rbp */ 0x48, 0x89, 0xe5, /* mov %rsp,%rbp */ 0xc7, 0x45, 0xfc, 0x42, 0x00, 0x00, 0x00, /* movl $0x42,-4(%rbp) */ 0xc9, /* leaveq */ 0xc3 /* retq */ }; #define TOFFSET 7 #elif defined(__i386__) static char testfunc[] = { 0x55, /* push %ebp */ 0x89, 0xe5, /* mov %esp,%ebp */ 0x83, 0xec, 0x04, /* sub $0x4,%esp */ 0xc7, 0x45, 0xfc, 0x42, 0x00, 0x00, 0x00, /* movl $0x42,-4(%ebp) */ 0xc9, /* leave */ 0xc3 /* ret */ }; #define TOFFSET 9 #else #warn "Sorry, this platform is not supported." #endif static char * mmap_test(int map_prot, int map_mode, int fd) { char *qp; qp = mmap(0, 1024, map_prot, map_mode, fd, 0); if (qp != MAP_FAILED) { printf("mmap OK "); return (qp); } else { printf("mmap error (%d)", errno); return (NULL); } } static void unmap_test(void *ptr) { if (ptr != NULL) munmap(ptr, 1024); } static int sigsegv = 0; static int buserr = 0; static int othersig = 0; static void handle_sig(int sig) { switch(sig) { case SIGSEGV: sigsegv ++; break; case SIGBUS: buserr ++; break; default: othersig = sig; } siglongjmp(env, 1); } #define PRINT_SIGNAL() \ do { \ if (sigsegv) \ printf("sigsegv"); \ if (buserr) \ printf("buserr"); \ if (othersig) \ printf("sig%02d", othersig); \ } while(0) static void access_test(void *ptr) { struct sigaction newsig = { .sa_handler = &handle_sig, .sa_flags = 0, .sa_mask = 0, }; struct sigaction oldsegv; struct sigaction oldbus; char *qp = (char *)ptr; /* read test */ sigsegv = buserr = othersig = 0; sigaction(SIGSEGV, &newsig, &oldsegv); sigaction(SIGBUS, &newsig, &oldbus); printf("read: "); if (sigsetjmp(env, 1) == 0) printf("0x%02x", qp[TOFFSET]); else PRINT_SIGNAL(); /* write test */ sigsegv = buserr = othersig = 0; printf(" write: "); if (sigsetjmp(env, 1) == 0) { memcpy(qp, testfunc, sizeof(testfunc)); qp[TOFFSET] = 0x41; printf("OK"); } else PRINT_SIGNAL(); /* exec test */ sigsegv = buserr = othersig = 0; printf(" exec: "); if (sigsetjmp(env, 1) == 0) { ((void (*)())qp)(); printf("OK"); } else PRINT_SIGNAL(); sigaction(SIGSEGV, &oldsegv, NULL); sigaction(SIGBUS, &oldbus, NULL); } #undef PRINT_SIGNAL static void run_cases(struct intdesc filemodes[], struct intdesc mapmodes[], struct intdesc mapprots[], char *(*mapfunc)(int, int, int), void (*accessfunc)(void *), void (*unmapfunc)(void *)) { struct intdesc *filemode, *map_mode, *map_prot; int fd, caseid, anon; void *region; caseid = 1; for (filemode = filemodes; filemode->desc != NULL; filemode++) { for (map_mode = mapmodes; map_mode->desc != NULL; map_mode++) { for (map_prot = mapprots; map_prot->desc != NULL; map_prot++) { if (filemode->desc != nofile) { anon = 0; if ((fd = open(testfile, filemode->val, 0644)) < 0 ) { perror("open testfile"); return; } } else { fd = -1; anon = MAP_ANON; } printf("%04d: mmap(0, 1024, %s, %s%s, ...)\n" " for filemode %s: ", caseid, map_prot->desc, anon ? "MAP_ANON|" : "", map_mode->desc, filemode->desc); region = (*mapfunc)(map_prot->val, anon | map_mode->val, fd); if (region) { (*accessfunc)(region); (*unmapfunc)(region); } caseid++; if (fd >= 0) close(fd); printf("\n"); } } } } int main(void) { struct intdesc filemodes[] = { {O_RDONLY, "O_RDONLY"}, {O_WRONLY, "O_WRONLY"}, {O_RDWR, "O_RDWR"}, {-1, nofile}, {-1, NULL}, }; struct intdesc mapmodes[] = { #if 0 {0, "none"}, #endif {MAP_SHARED, "MAP_SHARED"}, {MAP_PRIVATE, "MAP_PRIVATE"}, {-1, NULL}, }; struct intdesc mapprots[] = { {PROT_NONE, "PROT_NONE"}, {PROT_READ, "PROT_READ"}, {PROT_WRITE, "PROT_WRITE"}, {PROT_EXEC, "PROT_EXEC"}, {PROT_READ|PROT_WRITE, "PROT_READ|PROT_WRITE"}, {PROT_READ|PROT_EXEC, "PROT_READ|PROT_EXEC"}, {PROT_WRITE|PROT_EXEC, "PROT_WRITE|PROT_EXEC"}, {PROT_READ|PROT_WRITE|PROT_EXEC, "PROT_READ|PROT_WRITE|PROT_EXEC"}, {-1, NULL}, }; int fd; fd = mkstemp(testfile); if (fd < 0) { perror("open testfile"); return (-1); } if (write(fd, testfunc, sizeof(testfunc)) != sizeof(testfunc)) { perror("write testfile"); return (-1); } close(fd); run_cases(filemodes, mapmodes, mapprots, &mmap_test, &access_test, &unmap_test); unlink(testfile); return (0); } --Boundary-00=_slVsFRjAyW28ZgI--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200701191851.08685.jkim>