10static int anonymous_residency(
void) {
12 const size_t p = vm_page;
14 mmap(NULL, 4 * p, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
15 unsigned char* output =
16 mmap(NULL, 2 * p, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
17 unsigned char vector[6];
18 CHECK(area != MAP_FAILED && output != MAP_FAILED);
19 memset(vector, 0xa5,
sizeof(vector));
20 CHECK(mincore(area, 4 * p - 1, vector + 1) == 0 && vector[0] == 0xa5 && vector[5] == 0xa5);
21 CHECK(vm_uniform(vector + 1, 4, 0));
22 CHECK(mincore(area, 4 * p, vector + 1) == 0 && vm_uniform(vector + 1, 4, 0));
24 CHECK(mprotect(area + p, 2 * p, PROT_NONE) == 0);
25 CHECK(mincore(area, 4 * p, vector) == 0 && vector[0] == 0 && vector[1] == 1 && vector[2] == 0 &&
28 CHECK(mincore(area, 4 * p, vector) == 0 && vector[0] == 1 && vector[1] == 1 && vector[2] == 0 &&
30 CHECK(mprotect(area + p, p, PROT_READ | PROT_WRITE) == 0 && area[p] == 0xb1);
31 CHECK(mincore(area + 1, p, vector) == -1 && errno == EINVAL);
32 CHECK(mprotect(output + p, p, PROT_NONE) == 0);
33 CHECK(mincore(area, p, output + p) == -1 && errno == EFAULT);
35 CHECK(mincore(area, 2 * p, output + p - 1) == -1 && errno == EFAULT && output[p - 1] == 0xa5);
36 CHECK(mincore(area, 0, output + p) == 0);
37 CHECK(mincore(area, 4 * p, vector) == 0 && vector[2] == 0 && vector[3] == 0);
38 CHECK(munmap(area + 3 * p, p) == 0);
39 CHECK(mincore(area, 4 * p, vector) == -1 && errno == ENOMEM);
40 CHECK(mincore(area + 3 * p, p, vector) == -1 && errno == ENOMEM);
42 if (area != MAP_FAILED)
44 if (output != MAP_FAILED)
45 munmap(output, 2 * p);
49static int file_residency(
void) {
50 int failed = 0, fd = -1;
51 const size_t p = vm_page;
53 unsigned char *area = MAP_FAILED, *alias = MAP_FAILED;
54 unsigned char vector[3], byte;
56 CHECK((fd = vm_file(1, NULL)) >= 0);
57 CHECK(fchmod(fd, 0600) == 0);
58 CHECK(fstat(fd, &metadata) == 0 && (metadata.st_mode & 0777) == 0600);
59 CHECK((area = mmap(NULL, 3 * p, PROT_NONE, MAP_PRIVATE, fd, 0)) != MAP_FAILED);
60 CHECK((alias = mmap(NULL, p, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED);
61 CHECK(pread(fd, &
byte, 1, 0) == 1 &&
byte == 0x20);
62 CHECK(mincore(area, 3 * p, vector) == 0 && vector[0] == 1 && vector[1] == 0 && vector[2] == 0);
63 CHECK(alias[0] == 0x20);
64 CHECK(madvise(alias, p, MADV_DONTNEED) == 0);
65 CHECK(mincore(alias, p, vector) == 0 && vector[0] == 1);
66 CHECK(mincore(area, 3 * p, vector) == 0 && vector[0] == 1 && vector[1] == 0 && vector[2] == 0);
68 CHECK((child = fork()) >= 0);
71 if (setgid(65534) || setuid(65534))
74 const int before = errno;
75 const int result = mincore(area, 3 * p, vector);
76 const int after = errno;
77 if (result || after != EDOM || !vm_uniform(vector, 3, 1)) {
79 "VM-EXPANSION-CONTRACT: residency masked mincore=%d errno=%d->%d "
80 "uid=%lu euid=%lu gid=%lu egid=%lu vector=%u,%u,%u\n",
81 result, before, after, (
unsigned long)getuid(), (
unsigned long)geteuid(),
82 (
unsigned long)getgid(), (
unsigned long)getegid(), (
unsigned)vector[0],
83 (
unsigned)vector[1], (
unsigned)vector[2]);
88 int status = vm_reap(child, 4000);
91 CHECK(mincore(area, 3 * p, vector) == 0 && vector[1] == 0 && vector[2] == 0);
93 puts(
"VM-EXPANSION-CONTRACT: SKIP residency credential masking requires root");
102 if (area != MAP_FAILED)
104 if (alias != MAP_FAILED)
109int vm_test_residency(
void) {
110 return anonymous_residency() || file_residency();