Index: unittests/Support/MemoryTest.cpp =================================================================== --- unittests/Support/MemoryTest.cpp +++ unittests/Support/MemoryTest.cpp @@ -10,13 +10,39 @@ #include "llvm/Support/Memory.h" #include "llvm/Support/Process.h" #include "gtest/gtest.h" +#include #include +#if defined(__NetBSD__) +#include +#include +#include +#include +#endif + using namespace llvm; using namespace sys; namespace { +bool IsMPROTECT() { +#if defined(__NetBSD__) + int mib[3]; + int paxflags; + size_t len = sizeof(paxflags); + + mib[0] = CTL_PROC; + mib[1] = getpid(); + mib[2] = PROC_PID_PAXFLAGS; + + assert(sysctl(mib, 3, &paxflags, &len, NULL, 0) == 0); + + return !!(paxflags & CTL_PROC_PAXFLAGS_MPROTECT); +#else + return false; +#endif +} + class MappedMemoryTest : public ::testing::TestWithParam { public: MappedMemoryTest() { @@ -56,7 +82,16 @@ size_t PageSize; }; +// MPROTECT prevents W+X mmaps +#define CHECK_UNSUPPORTED() \ + do { \ + if ((Flags & Memory::MF_WRITE) && (Flags & Memory::MF_EXEC) && \ + IsMPROTECT()) \ + return; \ + } while (0); \ + TEST_P(MappedMemoryTest, AllocAndRelease) { + CHECK_UNSUPPORTED(); std::error_code EC; MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC); EXPECT_EQ(std::error_code(), EC); @@ -68,6 +103,7 @@ } TEST_P(MappedMemoryTest, MultipleAllocAndRelease) { + CHECK_UNSUPPORTED(); std::error_code EC; MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC); EXPECT_EQ(std::error_code(), EC); @@ -98,6 +134,7 @@ } TEST_P(MappedMemoryTest, BasicWrite) { + CHECK_UNSUPPORTED(); // This test applies only to readable and writeable combinations if (Flags && !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE))) @@ -118,6 +155,7 @@ } TEST_P(MappedMemoryTest, MultipleWrite) { + CHECK_UNSUPPORTED(); // This test applies only to readable and writeable combinations if (Flags && !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE))) @@ -180,6 +218,10 @@ } TEST_P(MappedMemoryTest, EnabledWrite) { + // MPROTECT prevents W+X, and since this test always adds W we need + // to block any variant with X. + if ((Flags && Memory::MF_EXEC) && IsMPROTECT()) + return; std::error_code EC; MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), nullptr, Flags, EC); @@ -237,6 +279,7 @@ } TEST_P(MappedMemoryTest, SuccessiveNear) { + CHECK_UNSUPPORTED(); std::error_code EC; MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC); EXPECT_EQ(std::error_code(), EC); @@ -262,6 +305,7 @@ } TEST_P(MappedMemoryTest, DuplicateNear) { + CHECK_UNSUPPORTED(); std::error_code EC; MemoryBlock Near((void*)(3*PageSize), 16); MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); @@ -284,6 +328,7 @@ } TEST_P(MappedMemoryTest, ZeroNear) { + CHECK_UNSUPPORTED(); std::error_code EC; MemoryBlock Near(nullptr, 0); MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); @@ -310,6 +355,7 @@ } TEST_P(MappedMemoryTest, ZeroSizeNear) { + CHECK_UNSUPPORTED(); std::error_code EC; MemoryBlock Near((void*)(4*PageSize), 0); MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); @@ -336,6 +382,7 @@ } TEST_P(MappedMemoryTest, UnalignedNear) { + CHECK_UNSUPPORTED(); std::error_code EC; MemoryBlock Near((void*)(2*PageSize+5), 0); MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC);