// SPDX-License-Identifier: MPL-2.0 #define _GNU_SOURCE #include #include #include #include #include "../test.h" #define PAGE_SIZE 4096 const char *filename = "testfile"; FN_TEST(mprotect_shared_writable_mapping_on_read_only_file) { int fd = TEST_SUCC(open(filename, O_RDWR | O_CREAT | O_TRUNC, 0600)); TEST_SUCC(ftruncate(fd, PAGE_SIZE)); TEST_SUCC(write(fd, "AAAA", 5)); TEST_SUCC(close(fd)); fd = TEST_SUCC(open(filename, O_RDONLY)); char *addr = TEST_SUCC(mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, fd, 0)); TEST_ERRNO(mprotect(addr, PAGE_SIZE, PROT_READ | PROT_WRITE), EACCES); TEST_SUCC(munmap(addr, PAGE_SIZE)); TEST_SUCC(close(fd)); TEST_SUCC(unlink(filename)); } END_TEST() FN_TEST(mprotect_private_writable_mapping_copy_on_write) { int fd = TEST_SUCC(open(filename, O_RDWR | O_CREAT | O_TRUNC, 0600)); TEST_SUCC(ftruncate(fd, PAGE_SIZE)); TEST_SUCC(write(fd, "AAAA", 5)); char *addr1 = TEST_SUCC(mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, 0)); char *addr2 = TEST_SUCC(mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, 0)); TEST_RES(strcmp(addr1, "AAAA"), _ret == 0); TEST_RES(strcmp(addr2, "AAAA"), _ret == 0); TEST_SUCC(mprotect(addr1, PAGE_SIZE, PROT_READ | PROT_WRITE)); memcpy(addr1, "BBBB", 5); TEST_RES(strcmp(addr1, "BBBB"), _ret == 0); TEST_RES(strcmp(addr2, "AAAA"), _ret == 0); TEST_SUCC(munmap(addr1, PAGE_SIZE)); TEST_SUCC(munmap(addr2, PAGE_SIZE)); TEST_SUCC(close(fd)); TEST_SUCC(unlink(filename)); } END_TEST() FN_TEST(mprotect_invalid_permission) { #define PROT_INVALID 0x20 void *addr = TEST_SUCC(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_INVALID, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); TEST_SUCC(mprotect(addr, PAGE_SIZE, PROT_READ | PROT_EXEC)); TEST_ERRNO(mprotect(addr, PAGE_SIZE, PROT_READ | PROT_INVALID), EINVAL); TEST_SUCC(munmap(addr, PAGE_SIZE)); } END_TEST() FN_TEST(mprotect_merge_after_split_mapping) { void *addr = TEST_SUCC(mmap(NULL, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); // Split the mapping into two. TEST_SUCC(mprotect(addr, PAGE_SIZE, PROT_READ)); // After the first mapping is protected, the two mappings will merge. TEST_SUCC(mprotect(addr, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE)); TEST_SUCC(munmap(addr, 2 * PAGE_SIZE)); } END_TEST()