Skip to content

Commit 3788712

Browse files
author
moisesferreira
committed
Allocate executable JIT code to read+execute memory directly
This prevents a sensitive transition from read+write to read+execute
1 parent a605162 commit 3788712

3 files changed

Lines changed: 32 additions & 21 deletions

File tree

src/utils/ExecutableMemory.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,22 +57,20 @@ void ExecutableMemory::init(uint8_t const *const data) {
5757
return;
5858
}
5959

60-
MemUtils::MmapMemory const mmapMemory{MemUtils::allocPagedMemory(size_)};
61-
uint8_t *const readWriteMemory{mmapMemory.ptr};
60+
MemUtils::MmapMemory const mmapMemory{MemUtils::allocPagedMemory(size_, data)};
61+
uint8_t *const readWriteOrExecuteMemory{mmapMemory.ptr};
6262

63-
if (readWriteMemory != nullptr) {
63+
if (readWriteOrExecuteMemory != nullptr) {
6464
fd_ = mmapMemory.fd;
65-
MemUtils::memcpyAndClearInstrCache(readWriteMemory, data, size_);
65+
data_ = readWriteOrExecuteMemory;
6666
} else {
6767
throw std::bad_alloc(); // GCOVR_EXCL_LINE
6868
}
6969

70-
#ifdef __linux__
71-
uint8_t *const readExecuteMemory{MemUtils::mapRXMemory(size_, fd_)};
72-
data_ = readExecuteMemory;
73-
MemUtils::freePagedMemory(readWriteMemory, size_);
70+
#if defined(__linux__) || defined(__QNX__)
71+
MemUtils::clearInstructionCache(readWriteOrExecuteMemory, size_);
7472
#else
75-
data_ = readWriteMemory;
73+
MemUtils::memcpyAndClearInstrCache(data_, data, size_);
7674
MemUtils::setPermissionRX(data_, size_);
7775
#endif
7876
}

src/utils/MemUtils.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,15 @@ static void *alignedReduce(void *const ptr, size_t const size, size_t const alig
169169
/// @brief wrapper of mmap, throw std::bad_alloc when mmap failed
170170
/// @param addr bypass to mmap
171171
/// @param length bypass to mmap
172-
/// @param port bypass to mmap
172+
/// @param prot bypass to mmap
173173
/// @param flags bypass to mmap
174174
/// @param fd bypass to mmap
175175
/// @param offset bypass to mmap
176176
/// @return result of mmap when mmap success
177177
/// @throw throw std::bad_alloc when mmap failed
178-
static uint8_t *wrapperMmap(void *const addr, size_t const length, int32_t const port, int32_t const flags, int32_t const fd, off_t const offset) {
178+
static uint8_t *wrapperMmap(void *const addr, size_t const length, int32_t const prot, int32_t const flags, int32_t const fd, off_t const offset) {
179179
// coverity[autosar_cpp14_a16_2_3_violation]
180-
void *const ptr{mmap(addr, length, port, flags, fd, offset)};
180+
void *const ptr{mmap(addr, length, prot, flags, fd, offset)};
181181
// coverity[autosar_cpp14_a16_2_3_violation]
182182
// coverity[autosar_cpp14_a5_2_2_violation]
183183
// coverity[autosar_cpp14_m5_2_9_violation]
@@ -381,35 +381,43 @@ void memcpyAndClearInstrCache(uint8_t *const dest, uint8_t const *const source,
381381
clearInstructionCache(dest, size);
382382
}
383383

384-
MmapMemory allocPagedMemory(size_t const size) {
384+
MmapMemory allocPagedMemory(size_t const size, uint8_t const *const data) {
385385
MmapMemory mmapMemory{nullptr, -1};
386386
#ifdef VB_WIN32
387387
mmapMemory.ptr = allocAlignedMemory(size, getOSMemoryPageSize());
388388
return mmapMemory;
389389
#else
390390
size_t const alignedSize{roundUpToOSMemoryPageSize(size)};
391-
#ifdef __linux__
391+
#if defined(__linux__) || defined(__QNX__)
392392
static std::atomic<uint64_t> fileCounter{0U}; ///< counter of mmap files
393393
// coverity[autosar_cpp14_a16_2_3_violation]
394394
std::stringstream ss{};
395395
uint64_t const localCounter{fileCounter};
396396
fileCounter++;
397397
ss << getpid() << "_vb_wasm_mem" << localCounter;
398+
#if defined(__linux__)
398399
int32_t const jitCodeMapFile{
399400
// coverity[autosar_cpp14_a16_2_3_violation]
400401
static_cast<int32_t>(syscall(__NR_memfd_create, ss.str().c_str(), MFD_CLOEXEC))}; // NOLINT(cppcoreguidelines-pro-type-vararg)
402+
#elif defined __QNX__
403+
// Instead of SHM_ANON, let's name the file
404+
int32_t const jitCodeMapFile{shm_open(ss.str().c_str(), O_RDWR | O_CREAT, 0600)};
405+
#endif
406+
401407
if (jitCodeMapFile == -1) {
402408
return mmapMemory;
403409
}
404410

405-
int32_t error{ftruncate(jitCodeMapFile, static_cast<off_t>(alignedSize))};
411+
int32_t ftruncate_error{ftruncate(jitCodeMapFile, static_cast<off_t>(alignedSize))};
412+
ssize_t write_error{write(jitCodeMapFile, data, size)};
406413

407-
if (error != 0) {
408-
error = close(jitCodeMapFile);
409-
static_cast<void>(error);
410-
assert(error == 0 && "close file failed");
414+
if ((ftruncate_error != 0) || (write_error == -1)) {
415+
ftruncate_error = close(jitCodeMapFile);
416+
static_cast<void>(ftruncate_error);
417+
assert(ftruncate_error == 0 && "close file failed");
411418
return mmapMemory;
412419
}
420+
413421
// coverity[autosar_cpp14_a16_2_3_violation]
414422
constexpr int32_t flag{MAP_SHARED};
415423
mmapMemory.fd = jitCodeMapFile;
@@ -419,7 +427,11 @@ MmapMemory allocPagedMemory(size_t const size) {
419427
constexpr int32_t flag = static_cast<int32_t>(uflag);
420428
#endif
421429
// coverity[autosar_cpp14_a16_2_3_violation]
422-
constexpr uint32_t prot{static_cast<uint32_t>(PROT_READ) | static_cast<uint32_t>(PROT_WRITE)};
430+
uint32_t prot{static_cast<uint32_t>(PROT_READ) | static_cast<uint32_t>(PROT_WRITE)};
431+
if(data != nullptr)
432+
{
433+
prot = static_cast<uint32_t>(PROT_READ) | static_cast<uint32_t>(PROT_EXEC);
434+
}
423435
mmapMemory.ptr = wrapperMmap(nullptr, alignedSize, static_cast<int32_t>(prot), static_cast<int32_t>(flag), mmapMemory.fd, 0);
424436

425437
return mmapMemory;

src/utils/MemUtils.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,11 @@ struct MmapMemory final {
113113
/// @brief Allocate page aligned memory
114114
///
115115
/// @param size size of to be allocated memory
116+
/// @param data data to be mapped as an anonymous file
116117
/// @throw std::bad_alloc memory allocation failed
117118
/// @return MmapMemory
118119
///
119-
MmapMemory allocPagedMemory(size_t const size);
120+
MmapMemory allocPagedMemory(size_t const size, uint8_t const *const data = nullptr);
120121
///
121122
/// @brief Free page aligned memory
122123
///

0 commit comments

Comments
 (0)