147b72404SMichael Jones //===-- Unittests for mprotect --------------------------------------------===//
247b72404SMichael Jones //
347b72404SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
447b72404SMichael Jones // See https://llvm.org/LICENSE.txt for license information.
547b72404SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
647b72404SMichael Jones //
747b72404SMichael Jones //===----------------------------------------------------------------------===//
847b72404SMichael Jones
940c443e2SSiva Chandra Reddy #include "src/errno/libc_errno.h"
1047b72404SMichael Jones #include "src/sys/mman/mmap.h"
1147b72404SMichael Jones #include "src/sys/mman/mprotect.h"
1247b72404SMichael Jones #include "src/sys/mman/munmap.h"
134f1fe19dSSiva Chandra Reddy #include "test/UnitTest/ErrnoSetterMatcher.h"
14af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h"
1547b72404SMichael Jones
16736e215cSMichael Jones #include <signal.h>
1747b72404SMichael Jones #include <sys/mman.h>
1847b72404SMichael Jones
19b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
20b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
2147b72404SMichael Jones
TEST(LlvmLibcMProtectTest,NoError)2247b72404SMichael Jones TEST(LlvmLibcMProtectTest, NoError) {
2347b72404SMichael Jones size_t alloc_size = 128;
24*3eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0;
25b6bc9d72SGuillaume Chatelet void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ,
2647b72404SMichael Jones MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2728699e38Slntue ASSERT_ERRNO_SUCCESS();
2847b72404SMichael Jones EXPECT_NE(addr, MAP_FAILED);
2947b72404SMichael Jones
3047b72404SMichael Jones int *array = reinterpret_cast<int *>(addr);
3147b72404SMichael Jones // Reading from the memory should not crash the test.
3247b72404SMichael Jones // Since we used the MAP_ANONYMOUS flag, the contents of the newly
3347b72404SMichael Jones // allocated memory should be initialized to zero.
3447b72404SMichael Jones EXPECT_EQ(array[0], 0);
3547b72404SMichael Jones
3647b72404SMichael Jones // By setting the memory protection to read and write, we should be able to
3747b72404SMichael Jones // modify that memory.
38b6bc9d72SGuillaume Chatelet EXPECT_THAT(
39b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::mprotect(addr, alloc_size, PROT_READ | PROT_WRITE),
4047b72404SMichael Jones Succeeds());
4147b72404SMichael Jones array[0] = 1;
4247b72404SMichael Jones EXPECT_EQ(array[0], 1);
4347b72404SMichael Jones
44b6bc9d72SGuillaume Chatelet EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, alloc_size), Succeeds());
4547b72404SMichael Jones }
4647b72404SMichael Jones
47c46a465eSMichael Jones // This test is disabled currently due to flakeyness. It will be re-enabled once
48c46a465eSMichael Jones // it is less flakey.
49c46a465eSMichael Jones /*
5047b72404SMichael Jones TEST(LlvmLibcMProtectTest, Error_InvalidWrite) {
5147b72404SMichael Jones // attempting to write to a read-only protected part of memory should cause a
5247b72404SMichael Jones // segfault.
5347b72404SMichael Jones EXPECT_DEATH(
5447b72404SMichael Jones [] {
5547b72404SMichael Jones size_t alloc_size = 128;
5647b72404SMichael Jones void *addr =
57b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ | PROT_WRITE,
5847b72404SMichael Jones MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
59b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::mprotect(addr, alloc_size, PROT_READ);
6047b72404SMichael Jones
6147b72404SMichael Jones (reinterpret_cast<char *>(addr))[0] = 'A';
6247b72404SMichael Jones },
6347b72404SMichael Jones WITH_SIGNAL(SIGSEGV));
6447b72404SMichael Jones // Reading from a write only segment may succeed on some platforms, so there's
6547b72404SMichael Jones // no test to check that.
6647b72404SMichael Jones }
67c46a465eSMichael Jones */
68