diff options
author | GHC GitLab CI <ghc-ci@gitlab-haskell.org> | 2022-01-28 22:33:52 -0500 |
---|---|---|
committer | GHC GitLab CI <ghc-ci@gitlab-haskell.org> | 2022-01-28 22:33:52 -0500 |
commit | 9e6a66911ce4ace4975ffca9e943387f3fc76e62 (patch) | |
tree | 65cfee0b0566d34c8fe02b872d9fa4c1a32643b5 | |
parent | a2466306967c3abc22d631f4a444d41ca3d439bd (diff) | |
download | haskell-9e6a66911ce4ace4975ffca9e943387f3fc76e62.tar.gz |
rts: Generalize mmapForLinkerMarkExecutable
Renamed to mprotectForLinker and allowed setting of arbitrary protection
modes.
-rw-r--r-- | rts/ExecPage.c | 2 | ||||
-rw-r--r-- | rts/Linker.c | 52 | ||||
-rw-r--r-- | rts/LinkerInternals.h | 10 | ||||
-rw-r--r-- | rts/linker/Elf.c | 2 | ||||
-rw-r--r-- | rts/linker/M32Alloc.c | 2 | ||||
-rw-r--r-- | rts/linker/MachO.c | 4 | ||||
-rw-r--r-- | rts/linker/SymbolExtras.c | 2 |
7 files changed, 57 insertions, 17 deletions
diff --git a/rts/ExecPage.c b/rts/ExecPage.c index 6f5b6e281a..24d4d65bad 100644 --- a/rts/ExecPage.c +++ b/rts/ExecPage.c @@ -15,7 +15,7 @@ ExecPage *allocateExecPage() { } void freezeExecPage(ExecPage *page) { - mmapForLinkerMarkExecutable(page, getPageSize()); + mprotectForLinker(page, getPageSize(), MEM_READ_EXECUTE); flushExec(getPageSize(), page); } diff --git a/rts/Linker.c b/rts/Linker.c index 61504fe996..b287a80032 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1084,6 +1084,16 @@ resolveSymbolAddr (pathchar* buffer, int size, #endif /* OBJFORMAT_PEi386 */ } +static const char *memoryAccessDescription(MemoryAccess mode) +{ + switch (mode) { + case MEM_NO_ACCESS: return "no-access"; + case MEM_READ_ONLY: return "read-only"; + case MEM_READ_WRITE: return "read-write"; + case MEM_READ_EXECUTE: return "read-execute"; + } +} + #if defined(mingw32_HOST_OS) // @@ -1112,16 +1122,28 @@ munmapForLinker (void *addr, size_t bytes, const char *caller) } } +/** + * Change the allowed access modes of a region of memory previously allocated + * with mmapAnonForLinker. + */ void -mmapForLinkerMarkExecutable(void *start, size_t len) +mprotectForLinker(void *start, size_t len, MemoryAccess mode) { DWORD old; if (len == 0) { return; } - if (VirtualProtect(start, len, PAGE_EXECUTE_READ, &old) == 0) { - sysErrorBelch("mmapForLinkerMarkExecutable: failed to protect %zd bytes at %p", - len, start); + DWORD prot; + switch (mode) { + case MEM_NO_ACCESS: prot = PAGE_NOACCESS; break; + case MEM_READ_ONLY: prot = PAGE_READONLY; break; + case MEM_READ_WRITE: prot = PAGE_READWRITE; break; + case MEM_READ_EXECUTE: prot = PAGE_EXECUTE_READ; break; + } + + if (VirtualProtect(start, len, prot, &old) == 0) { + sysErrorBelch("mprotectForLinker: failed to protect %zd bytes at %p as %s", + len, start, memoryAccessDescription(mode)); ASSERT(false); } } @@ -1273,7 +1295,7 @@ void munmapForLinker (void *addr, size_t bytes, const char *caller) * * Consequently mmapForLinker now maps its memory with PROT_READ|PROT_WRITE. * After the linker has finished filling/relocating the mapping it must then - * call mmapForLinkerMarkExecutable on the sections of the mapping which + * call mprotectForLinker on the sections of the mapping which * contain executable code. * * Note that the m32 allocator handles protection of its allocations. For this @@ -1289,16 +1311,26 @@ void munmapForLinker (void *addr, size_t bytes, const char *caller) * Mark an portion of a mapping previously reserved by mmapForLinker * as executable (but not writable). */ -void mmapForLinkerMarkExecutable(void *start, size_t len) +void mprotectForLinker(void *start, size_t len, MemoryAccess mode) { if (len == 0) { return; } IF_DEBUG(linker_verbose, - debugBelch("mmapForLinkerMarkExecutable: protecting %" FMT_Word - " bytes starting at %p\n", (W_)len, start)); - if (mprotect(start, len, PROT_READ|PROT_EXEC) == -1) { - barf("mmapForLinkerMarkExecutable: mprotect: %s\n", strerror(errno)); + debugBelch("mprotectForLinker: protecting %" FMT_Word + " bytes starting at %p as %s\n", + (W_)len, start, memoryAccessDescription(mode))); + + int prot; + switch (prot) { + case MEM_NO_ACCESS: prot = 0; break; + case MEM_READ_ONLY: prot = PROT_READ; break; + case MEM_READ_WRITE: prot = PROT_READ | PROT_WRITE; break; + case MEM_READ_EXECUTE: prot = PROT_READ | PROT_EXEC; break; + } + + if (mprotect(start, len, prot) == -1) { + barf("mprotectForLinker: mprotect: %s\n", strerror(errno)); } } #endif diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h index 8c684a0390..3acbb55839 100644 --- a/rts/LinkerInternals.h +++ b/rts/LinkerInternals.h @@ -394,9 +394,17 @@ void exitLinker( void ); void freeObjectCode (ObjectCode *oc); SymbolAddr* loadSymbol(SymbolName *lbl, RtsSymbolInfo *pinfo); +/** Access modes for mprotectForLinker */ +typedef enum { + MEM_NO_ACCESS, + MEM_READ_ONLY, + MEM_READ_WRITE, + MEM_READ_EXECUTE, +} MemoryAccess; + void *mmapAnonForLinker (size_t bytes); void *mmapForLinker (size_t bytes, uint32_t prot, uint32_t flags, int fd, int offset); -void mmapForLinkerMarkExecutable (void *start, size_t len); +void mprotectForLinker(void *start, size_t len, MemoryAccess mode); void munmapForLinker (void *addr, size_t bytes, const char *caller); void addProddableBlock ( ObjectCode* oc, void* start, int size ); diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c index 06afae631d..b437cd6dd2 100644 --- a/rts/linker/Elf.c +++ b/rts/linker/Elf.c @@ -1878,7 +1878,7 @@ ocMprotect_Elf( ObjectCode *oc ) if (section->alloc != SECTION_M32) { // N.B. m32 handles protection of its allocations during // flushing. - mmapForLinkerMarkExecutable(section->mapped_start, section->mapped_size); + mprotectForLinker(section->mapped_start, section->mapped_size, MEM_READ_EXECUTE); } break; default: diff --git a/rts/linker/M32Alloc.c b/rts/linker/M32Alloc.c index a00c9b6a9b..70f8f00efb 100644 --- a/rts/linker/M32Alloc.c +++ b/rts/linker/M32Alloc.c @@ -444,7 +444,7 @@ m32_allocator_flush(m32_allocator *alloc) { ASSERT_PAGE_TYPE(page, FILLED_PAGE); struct m32_page_t *next = m32_filled_page_get_next(page); m32_allocator_push_filled_list(&alloc->protected_list, page); - mmapForLinkerMarkExecutable(page, page->filled_page.size); + mprotectForLinker(page, page->filled_page.size, MEM_READ_EXECUTE); page = next; } alloc->unprotected_list = NULL; diff --git a/rts/linker/MachO.c b/rts/linker/MachO.c index 02f2a30605..79d14a2d55 100644 --- a/rts/linker/MachO.c +++ b/rts/linker/MachO.c @@ -1436,7 +1436,7 @@ ocMprotect_MachO( ObjectCode *oc ) if(segment->size == 0) continue; if(segment->prot == SEGMENT_PROT_RX) { - mmapForLinkerMarkExecutable(segment->start, segment->size); + mprotectForLinker(segment->start, segment->size, MEM_READ_EXECUTE); } } @@ -1451,7 +1451,7 @@ ocMprotect_MachO( ObjectCode *oc ) if(section->alloc == SECTION_M32) continue; switch (section->kind) { case SECTIONKIND_CODE_OR_RODATA: { - mmapForLinkerMarkExecutable(section->mapped_start, section->mapped_size); + mprotectForLinker(section->mapped_start, section->mapped_size, MEM_READ_EXECUTE); break; } default: diff --git a/rts/linker/SymbolExtras.c b/rts/linker/SymbolExtras.c index ddb58e4a4e..5c04e9b3a8 100644 --- a/rts/linker/SymbolExtras.c +++ b/rts/linker/SymbolExtras.c @@ -142,7 +142,7 @@ void ocProtectExtras(ObjectCode* oc) * non-executable. */ } else if (USE_CONTIGUOUS_MMAP || RtsFlags.MiscFlags.linkerAlwaysPic) { - mmapForLinkerMarkExecutable(oc->symbol_extras, sizeof(SymbolExtra) * oc->n_symbol_extras); + mprotectForLinker(oc->symbol_extras, sizeof(SymbolExtra) * oc->n_symbol_extras, MEM_READ_EXECUTE); } else { /* * The symbol extras were allocated via m32. They will be protected when |