The two main test programs being used for xonly assessment, as
attachments.  They will eventually head towards src/regress but for
now, people can play with them.

#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
#include <dlfcn.h>
#include <string.h>
#include <err.h>
#include <wchar.h>

int	main(int argc, char *argv[]);

void *s_ldso(void);
void *s_mmap_xz(void);
void *s_mmap_x(void);
void *s_mmap_nrx(void);
void *s_mmap_nwx(void);
void *s_mmap_xnwx(void);

struct readable {
	char *name;
	void *(*setup)(void);
	int isfn;
	void *addr;
	int uu, ku;
	int skip;
} readables[] = {
	{ "ld.so",		s_ldso, 1,			},
	{ "mmap xz",		s_mmap_xz, 0,			},
	{ "mmap x",		s_mmap_x, 0,			},
	{ "mmap nrx",		s_mmap_nrx, 0,			},
	{ "mmap nwx",		s_mmap_nwx, 0,			},
	{ "mmap xnwx",		s_mmap_xnwx, 0,			},
	{ "main",		NULL, 1,	&main		},
	{ "libc unmapped?",	NULL, 1,	&wcstol		},
	{ "libc mapped",	NULL, 1,	&mmap		}
};

jmp_buf fail;

void
sigsegv(int _unused)
{
	longjmp(fail, 1);
}

void *
s_mmap_xz(void)
{
	return mmap(NULL, getpagesize(), PROT_EXEC,
	    MAP_ANON | MAP_PRIVATE, -1, 0);
	/* no data written. tests read-fault of an unbacked exec-only page */
}

void *
s_mmap_x(void)
{
	char *addr;

	addr = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
	    MAP_ANON | MAP_PRIVATE, -1, 0);
	explicit_bzero(addr, getpagesize());
	mprotect(addr, getpagesize(), PROT_EXEC);
	return addr;
}

void *
s_mmap_nrx(void)
{
	char *addr;

	addr = mmap(NULL, getpagesize(), PROT_NONE,
	    MAP_ANON | MAP_PRIVATE, -1, 0);
	mprotect(addr, getpagesize(), PROT_READ | PROT_WRITE);
	explicit_bzero(addr, getpagesize());
	mprotect(addr, getpagesize(), PROT_EXEC);
	return addr;
}

void *
s_mmap_nwx(void)
{
	char *addr;

	addr = mmap(NULL, getpagesize(), PROT_NONE,
	    MAP_ANON | MAP_PRIVATE, -1, 0);
	mprotect(addr, getpagesize(), PROT_WRITE);
	explicit_bzero(addr, getpagesize());
	mprotect(addr, getpagesize(), PROT_EXEC);
	return addr;
}

void *
s_mmap_xnwx(void)
{
	char *addr;

	addr = mmap(NULL, getpagesize(), PROT_EXEC,
	    MAP_ANON | MAP_PRIVATE, -1, 0);
	mprotect(addr, getpagesize(), PROT_NONE);
	mprotect(addr, getpagesize(), PROT_WRITE);
	explicit_bzero(addr, getpagesize());
	mprotect(addr, getpagesize(), PROT_EXEC);
	return addr;
}

void *
s_ldso(void)
{
	void *handle, *dlopenp;

	handle = dlopen("ld.so", RTLD_NOW);
	if (handle == NULL)
		*(volatile char *)0 = 0;
	dlopenp = dlsym(handle, "dlopen");
	return dlopenp;
}

void
s_table()
{
	int i;

	for (i = 0; i < sizeof(readables)/sizeof(readables[0]); i++) {

		if (setjmp(fail) == 0) {
			if (readables[i].setup)
				readables[i].addr = readables[i].setup();
		} else
			readables[i].skip = 1;
#ifdef __hppa__
		/* hppa ptable headers point at the instructions */
		if (readables[i].isfn)
			readables[i].addr = (void *)*(u_int *)
			    ((u_int)readables[i].addr & ~3);
#endif
	}
}

int
main(int argc, char *argv[])
{
	int p[2], i;

	signal(SIGSEGV, sigsegv);
	signal(SIGBUS, sigsegv);

	s_table();

	for (i = 0; i < sizeof(readables)/sizeof(readables[0]); i++) {
		struct readable *r = &readables[i];
		char c;

		if (r->skip)
			continue;
		pipe(p);
		fcntl(p[0], F_SETFL, O_NONBLOCK);

		if (write(p[1], r->addr, 1) == 1 && read(p[0], &c, 1) == 1)
			r->ku = 1;

		if (setjmp(fail) == 0) {
			volatile int x = *(int *)(r->addr);
			r->uu = 1;
		}

		close(p[0]);
		close(p[1]);
	}

	printf("%-16s  userland   kernel\n", "");	
	for (i = 0; i < sizeof(readables)/sizeof(readables[0]); i++) {
		struct readable *r = &readables[i];

		if (r->skip)
			printf("%-16s  %-10s %-10s\n", r->name,
			    "skipped", "skipped");
		else
			printf("%-16s  %-10s %-10s\n", r->name,
			    r->uu ? "readable" : "unreadable",
			    r->ku ? "readable" : "unreadable");
	}
}
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/exec_elf.h>
#include <dlfcn.h>
#include <link.h>
#include <setjmp.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#define        roundup(x, y)   ((((x)+((y)-1))/(y))*(y))

int pgsize;
jmp_buf fail;

void
sigsegv(int _unused)
{
        longjmp(fail, 1);
}

int
callback(struct dl_phdr_info *info, size_t size, void *cookie)
{
	Elf_Addr start, end, p;
	Elf_Off len;
	void *test;
	int i, count, total, col;

	/* Find all text segments */
	for (i = 0; i < info->dlpi_phnum; i++) {
		if (info->dlpi_phdr[i].p_type == PT_LOAD &&
		    info->dlpi_phdr[i].p_flags & PF_X) {
			start = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr;
			len = info->dlpi_phdr[i].p_memsz;
			end = start + len;
			printf("%s %llx-%llx (%llx, %lld pg) prot %s\n\t",
			    info->dlpi_name,
			    (uint64_t)start, (uint64_t)end, (uint64_t)len,
			    ((uint64_t)len + pgsize) / pgsize,
			    (info->dlpi_phdr[i].p_flags & PF_R) ? "RX" : "X");

			test = malloc(pgsize);
			count = total = col = 0;

			/* attempt to read the entire text segment */
			for (p = start; p < end; p += pgsize) {
				total++;
				if (setjmp(fail) == 0) {
					memcpy(test, (char *)p, pgsize);
					printf("y");
					count++;
				} else {
					printf("n");
				}
				if (++col % 64 == 0)
					printf("\n\t");
			}
			printf("\n");
			printf("\tread %d pages of %d\n", count, total);
			if (count != total)
				printf("\tcannot read the whole\n");
			free(test);
		}
	}
	return 0;
}

int
main()
{
	pgsize = getpagesize();

	signal(SIGSEGV, sigsegv);
	signal(SIGBUS, sigsegv);

	dl_iterate_phdr(callback, NULL);
}

Reply via email to