Skip to content

Commit ca22001

Browse files
committed
Test if selfmem can write to RX page
Also open only one `/proc/self/mem`. There are apparently two instances of `RTDyldMemoryManagerJL` created. Fix #22082
1 parent 9b9c93b commit ca22001

File tree

1 file changed

+24
-12
lines changed

1 file changed

+24
-12
lines changed

src/cgmemmgr.cpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,9 @@ static void *alloc_shared_page(size_t size, size_t *id, bool exec)
264264
#ifdef _OS_LINUX_
265265
// Using `/proc/self/mem`, A.K.A. Keno's remote memory manager.
266266

267-
static int self_mem_fd = -1;
268-
269-
static int init_self_mem()
267+
// Do not call this directly.
268+
// Use `get_self_mem_fd` which has a guard to call this only once.
269+
static int _init_self_mem()
270270
{
271271
struct utsname kernel;
272272
uname(&kernel);
@@ -288,22 +288,34 @@ static int init_self_mem()
288288
return -1;
289289
fcntl(fd, F_SETFD, FD_CLOEXEC);
290290
#endif
291-
// buffer to check if write works;
292-
volatile uint64_t buff = 0;
293-
uint64_t v = 0x12345678;
294-
int ret = pwrite(fd, (void*)&v, sizeof(uint64_t), (uintptr_t)&buff);
295-
if (ret != sizeof(uint64_t) || buff != 0x12345678) {
291+
292+
// Check if we can write to a RX page
293+
void *test_pg = mmap(nullptr, jl_page_size, PROT_READ | PROT_EXEC,
294+
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
295+
// We can ignore this though failure to allocate executable memory would be a bigger problem.
296+
assert(test_pg != MAP_FAILED && "Cannot allocate executable memory");
297+
298+
const uint64_t v = 0xffff000012345678u;
299+
int ret = pwrite(fd, (const void*)&v, sizeof(uint64_t), (uintptr_t)test_pg);
300+
if (ret != sizeof(uint64_t) || *(volatile uint64_t*)test_pg != v) {
301+
munmap(test_pg, jl_page_size);
296302
close(fd);
297303
return -1;
298304
}
299-
self_mem_fd = fd;
305+
munmap(test_pg, jl_page_size);
306+
return fd;
307+
}
308+
309+
static int get_self_mem_fd()
310+
{
311+
static int fd = _init_self_mem();
300312
return fd;
301313
}
302314

303315
static void write_self_mem(void *dest, void *ptr, size_t size)
304316
{
305317
while (size > 0) {
306-
ssize_t ret = pwrite(self_mem_fd, ptr, size, (uintptr_t)dest);
318+
ssize_t ret = pwrite(get_self_mem_fd(), ptr, size, (uintptr_t)dest);
307319
if ((size_t)ret == size)
308320
return;
309321
if (ret == -1 && (errno == EAGAIN || errno == EINTR))
@@ -657,7 +669,7 @@ class SelfMemAllocator : public ROAllocator<exec> {
657669
: ROAllocator<exec>(),
658670
temp_buff()
659671
{
660-
assert(self_mem_fd != -1);
672+
assert(get_self_mem_fd() != -1);
661673
}
662674
void finalize() override
663675
{
@@ -717,7 +729,7 @@ class RTDyldMemoryManagerJL : public SectionMemoryManager {
717729
code_allocated(false)
718730
{
719731
#ifdef _OS_LINUX_
720-
if (!ro_alloc && init_self_mem() != -1) {
732+
if (!ro_alloc && get_self_mem_fd() != -1) {
721733
ro_alloc.reset(new SelfMemAllocator<false>());
722734
exe_alloc.reset(new SelfMemAllocator<true>());
723735
}

0 commit comments

Comments
 (0)