ATF_TC_BODY(mprotect_pax, tc) { const int prot[4] = { PROT_NONE, PROT_READ, PROT_WRITE }; const char *str = NULL; void *map; size_t i; int rv; if (!paxinit() || !paxset(1, 1)) return; /* * As noted in the original PaX documentation [1], * the following restrictions should apply: * * (1) creating executable anonymous mappings * * (2) creating executable/writable file mappings * * (3) making a non-executable mapping executable * * (4) making an executable/read-only file mapping * writable except for performing relocations * on an ET_DYN ELF file (non-PIC shared library) * * The following will test only the case (3). * * [1] http://pax.grsecurity.net/docs/mprotect.txt * * (Sun Apr 3 11:06:53 EEST 2011.) */ for (i = 0; i < __arraycount(prot); i++) { map = mmap(NULL, page, prot[i], MAP_ANON, -1, 0); if (map == MAP_FAILED) continue; rv = mprotect(map, 1, prot[i] | PROT_EXEC); (void)munmap(map, page); if (rv == 0) { str = "non-executable mapping made executable"; goto out; } } out: if (pax_global != -1 && pax_enabled != -1) (void)paxset(pax_global, pax_enabled); if (str != NULL) atf_tc_fail("%s", str); }
static bool paxinit(void) { size_t len = sizeof(int); int rv; rv = sysctlbyname("security.pax.mprotect.global", &pax_global, &len, NULL, 0); if (rv != 0) return false; rv = sysctlbyname("security.pax.mprotect.enabled", &pax_enabled, &len, NULL, 0); if (rv != 0) return false; return paxset(1, 1); }