mmap(2) fingerprinting on amd64
Marcin Cieslak
saper at SYSTEM.PL
Mon Sep 18 17:09:24 PDT 2006
Attached please find a very simple brute-force mmap(2) testing program.
1. It would be nice if somebody could run this on real amd64 linux machine.
and under FreeBSD linuxolator on amd64 machine. Please mail results to me.
2. I don't know how to include simple test for PROT_EXEC behaviour
(there should be at least one case more in the mapprots[] plus somehow execute
something in the access_test().
--
<< Marcin Cieslak // saper at system.pl >>
-------------- next part --------------
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
struct intdesc {
const int val;
const char *desc;
};
static char TESTFILE[] = "/tmp/test";
static sigjmp_buf env;
static char nofile[] = "anonymous";
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);
}
static void
access_test(void *ptr)
{
char *qp = (char *)ptr;
struct sigaction newsig = {
.sa_handler = &handle_sig,
.sa_flags = 0,
.sa_mask = 0,
};
struct sigaction oldsegv;
struct sigaction oldbus;
sigsegv = buserr = othersig = 0;
sigaction(SIGSEGV, &newsig, &oldsegv);
sigaction(SIGBUS, &newsig, &oldbus);
printf("read: ");
if (sigsetjmp(env, 1) == 0) {
printf("0x%02x", qp[0]);
} else {
if (sigsegv) printf("sigsegv");
if (buserr) printf("buserr");
if (othersig) printf("sig%02d", othersig);
};
sigsegv = buserr = othersig = 0;
printf(" write: ");
if (sigsetjmp(env, 1) == 0) {
qp[0] = 'B';
printf("OK");
} else {
if (sigsegv) { printf("sigsegv"); };
if (buserr) { printf("buserr"); };
}
sigaction(SIGSEGV, &oldsegv, NULL);
sigaction(SIGBUS, &oldbus, NULL);
}
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()
{
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_READ|PROT_WRITE, "PROT_READ|PROT_WRITE"},
{-1, NULL},
};
char *qp;
int fd, caseid, anon;
fd = open(TESTFILE, O_CREAT|O_WRONLY, 0644);
write(fd, "ABCD");
if (fd > -1)
close(fd);
run_cases(filemodes, mapmodes, mapprots,
&mmap_test, &access_test, &unmap_test);
};
More information about the freebsd-emulation
mailing list