Index: base/file_util_posix.cc |
diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc |
index 582f70ed7c6450c7e3e3b228368abaebcc2f4cb3..5c14abd3f253581475b54128f14a062a226b0402 100644 |
--- a/base/file_util_posix.cc |
+++ b/base/file_util_posix.cc |
@@ -481,9 +481,9 @@ bool CreateTemporaryFile(FilePath* path) { |
return true; |
} |
-FILE* CreateAndOpenTemporaryShmemFile(FilePath* path) { |
+FILE* CreateAndOpenTemporaryShmemFile(FilePath* path, bool executable) { |
FilePath directory; |
- if (!GetShmemTempDir(&directory)) |
+ if (!GetShmemTempDir(&directory, executable)) |
return NULL; |
return CreateAndOpenTemporaryFileInDir(directory, path); |
@@ -910,15 +910,52 @@ bool GetTempDir(FilePath* path) { |
} |
#if !defined(OS_ANDROID) |
-bool GetShmemTempDir(FilePath* path) { |
+ |
#if defined(OS_LINUX) |
- *path = FilePath("/dev/shm"); |
- return true; |
-#else |
- return GetTempDir(path); |
-#endif |
+// Determine if /dev/shm files can be mapped and then mprotect'd PROT_EXEC. |
+// This depends on the mount options used for /dev/shm, which vary among |
+// different Linux distributions and possibly local configuration. It also |
+// depends on details of kernel--ChromeOS uses the noexec option for /dev/shm |
+// but its kernel allows mprotect with PROT_EXEC anyway. |
+ |
+namespace { |
+ |
+bool DetermineDevShmExecutable() { |
+ bool result = false; |
+ FilePath path; |
+ int fd = CreateAndOpenFdForTemporaryFile(FilePath("/dev/shm"), &path); |
+ if (fd >= 0) { |
+ ScopedFD shm_fd_closer(&fd); |
+ Delete(path, false); |
+ size_t pagesize = sysconf(_SC_PAGESIZE); |
+ void *mapping = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0); |
+ if (mapping != MAP_FAILED) { |
+ if (mprotect(mapping, pagesize, PROT_READ | PROT_EXEC) == 0) |
+ result = true; |
+ munmap(mapping, pagesize); |
+ } |
+ } |
+ return result; |
} |
+ |
+}; // namespace |
+#endif // defined(OS_LINUX) |
+ |
+bool GetShmemTempDir(FilePath* path, bool executable) { |
+#if defined(OS_LINUX) |
+ bool use_dev_shm = true; |
+ if (executable) { |
+ static const bool s_dev_shm_executable = DetermineDevShmExecutable(); |
+ use_dev_shm = s_dev_shm_executable; |
+ } |
+ if (use_dev_shm) { |
+ *path = FilePath("/dev/shm"); |
+ return true; |
+ } |
#endif |
+ return GetTempDir(path); |
+} |
+#endif // !defined(OS_ANDROID) |
FilePath GetHomeDir() { |
const char* home_dir = getenv("HOME"); |