Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Sep 2006 02:09:09 +0200
From:      Marcin Cieslak <saper@SYSTEM.PL>
To:        emulation@freebsd.org
Subject:   mmap(2) fingerprinting on amd64
Message-ID:  <450F3525.5080305@SYSTEM.PL>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------020603020907000609080904
Content-Type: text/plain; charset=ISO-8859-2; format=flowed
Content-Transfer-Encoding: 7bit

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@system.pl >>

--------------020603020907000609080904
Content-Type: text/plain;
 name="mmap_test.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="mmap_test.c"

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


--------------020603020907000609080904--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?450F3525.5080305>