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