#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define MAP_AT_ZERO "security.bsd.map_at_zero"
+#ifdef __LP64__
+#define ALLOW_WX "kern.elf64.allow_wx"
+#else
+#define ALLOW_WX "kern.elf32.allow_wx"
+#endif
+
ATF_TC_WITHOUT_HEAD(mmap__map_at_zero);
ATF_TC_BODY(mmap__map_at_zero, tc)
{
size_t len;
unsigned int i;
int map_at_zero;
+ bool allow_wx;
+ int prot_flags;
len = sizeof(map_at_zero);
if (sysctlbyname(MAP_AT_ZERO, &map_at_zero, &len, NULL, 0) == -1) {
return;
}
+ len = sizeof(allow_wx);
+ if (sysctlbyname(ALLOW_WX, &allow_wx, &len, NULL, 0) == -1) {
+ if (errno == ENOENT) {
+ /* Allow W+X if sysctl isn't present */
+ allow_wx = true;
+ } else {
+ atf_tc_skip("sysctl for %s failed: %s\n", ALLOW_WX,
+ strerror(errno));
+ return;
+ }
+ }
+
/* Normalize to 0 or 1 for array access. */
map_at_zero = !!map_at_zero;
for (i = 0; i < nitems(map_at_zero_tests); i++) {
+ prot_flags = PROT_READ | PROT_WRITE;
+ if (allow_wx)
+ prot_flags |= PROT_EXEC;
p = mmap((void *)map_at_zero_tests[i].addr, PAGE_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_FIXED,
- -1, 0);
+ prot_flags, MAP_ANON | MAP_FIXED, -1, 0);
if (p == MAP_FAILED) {
ATF_CHECK_MSG(map_at_zero_tests[i].ok[map_at_zero] == 0,
"mmap(%p, ...) failed", map_at_zero_tests[i].addr);