[VM runtime] Use memfd_create instead of shm_open for dual mapping of code.
Detect both at compile time and runtime for memfd_create support and disable
dual code mapping if not available.
Change-Id: I6908e6c116a60218bb5002378470011dfe76a257
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/96845
Commit-Queue: Régis Crelier <regis@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 21fc4b3..07d2d03 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -352,19 +352,6 @@
#error Unknown architecture.
#endif
-// Determine whether dual mapping of code pages is supported.
-#if !defined(USING_SIMULATOR) && \
- (defined(HOST_OS_LINUX) || defined(HOST_OS_FUCHSIA)) && \
- !defined(TARGET_OS_ANDROID) && !defined(TARGET_ARCH_IA32)
-#define DUAL_MAPPING_SUPPORTED 1
-#endif
-
-// Disable background threads by default on armv5te. The relevant
-// implementations are uniprocessors.
-#if !defined(TARGET_ARCH_ARM_5TE)
-#define ARCH_IS_MULTI_CORE 1
-#endif
-
#if !defined(TARGET_OS_ANDROID) && !defined(TARGET_OS_FUCHSIA) && \
!defined(TARGET_OS_MACOS_IOS) && !defined(TARGET_OS_LINUX) && \
!defined(TARGET_OS_MACOS) && !defined(TARGET_OS_WINDOWS)
@@ -387,6 +374,19 @@
#endif
#endif
+// Determine whether dual mapping of code pages is supported.
+// We test dual mapping on linux x64 and deploy it on fuchsia.
+#if defined(TARGET_OS_LINUX) && defined(TARGET_ARCH_X64) || \
+ defined(TARGET_OS_FUCHSIA)
+#define DUAL_MAPPING_SUPPORTED 1
+#endif
+
+// Disable background threads by default on armv5te. The relevant
+// implementations are uniprocessors.
+#if !defined(TARGET_ARCH_ARM_5TE)
+#define ARCH_IS_MULTI_CORE 1
+#endif
+
// Short form printf format specifiers
#define Pd PRIdPTR
#define Pu PRIuPTR
diff --git a/runtime/vm/virtual_memory_posix.cc b/runtime/vm/virtual_memory_posix.cc
index bf22734..985d5b6 100644
--- a/runtime/vm/virtual_memory_posix.cc
+++ b/runtime/vm/virtual_memory_posix.cc
@@ -11,6 +11,7 @@
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#include <sys/syscall.h>
#include <unistd.h>
#include "platform/assert.h"
@@ -31,8 +32,6 @@
#undef MAP_FAILED
#define MAP_FAILED reinterpret_cast<void*>(-1)
-#define DART_SHM_NAME "/dart_shm"
-
DECLARE_FLAG(bool, dual_map_code);
DECLARE_FLAG(bool, write_protect_code);
@@ -42,25 +41,29 @@
page_size_ = getpagesize();
#if defined(DUAL_MAPPING_SUPPORTED)
- shm_unlink(DART_SHM_NAME); // Could be left over from a previous crash.
-
// Detect dual mapping exec permission limitation on some platforms,
// such as on docker containers, and disable dual mapping in this case.
+ // Also detect for missing support of memfd_create syscall.
if (FLAG_dual_map_code) {
intptr_t size = page_size_;
intptr_t alignment = 256 * 1024; // e.g. heap page size.
VirtualMemory* vm = AllocateAligned(size, alignment, true, NULL);
+ if (vm == NULL) {
+ LOG_INFO("memfd_create not supported; disabling dual mapping of code.\n");
+ FLAG_dual_map_code = false;
+ return;
+ }
void* region = reinterpret_cast<void*>(vm->region_.start());
void* alias = reinterpret_cast<void*>(vm->alias_.start());
if (region == alias ||
mprotect(region, size, PROT_READ) != 0 || // Remove PROT_WRITE.
mprotect(alias, size, PROT_READ | PROT_EXEC) != 0) { // Add PROT_EXEC.
- LOG_INFO("disabling dual mapping of code\n");
+ LOG_INFO("mprotect fails; disabling dual mapping of code.\n");
FLAG_dual_map_code = false;
}
delete vm;
}
-#endif // defined(DUAL_MAPPING_SUPPORTED)
+#endif // defined(DUAL_MAPPING_SUPPORTED)
}
static void unmap(uword start, uword end) {
@@ -80,6 +83,16 @@
}
#if defined(DUAL_MAPPING_SUPPORTED)
+// Wrapper to call memfd_create syscall.
+static inline int memfd_create(const char* name, unsigned int flags) {
+#if !defined(__NR_memfd_create)
+ errno = ENOSYS;
+ return -1;
+#else
+ return syscall(__NR_memfd_create, name, flags);
+#endif
+}
+
static void* MapAligned(int fd,
int prot,
intptr_t size,
@@ -130,14 +143,11 @@
const bool dual_mapping =
is_executable && FLAG_write_protect_code && FLAG_dual_map_code;
if (dual_mapping) {
- // Create a shared memory object for dual mapping.
- // There is a small conflict window, i.e. another Dart process
- // simultaneously opening an object with the same name.
- do {
- fd = shm_open(DART_SHM_NAME, O_RDWR | O_CREAT | O_EXCL, S_IRWXU);
- } while ((fd == -1) && (errno == EEXIST));
- shm_unlink(DART_SHM_NAME);
- if ((fd == -1) || (ftruncate(fd, size) == -1)) {
+ fd = memfd_create("dart_vm", 0);
+ if (fd == -1) {
+ return NULL;
+ }
+ if (ftruncate(fd, size) == -1) {
close(fd);
return NULL;
}