193 lines
6.7 KiB
Diff
193 lines
6.7 KiB
Diff
Backport http://codereview.chromium.org/8800025 to fix issues with noexec /dev/shm
|
|
diff --git a/base/file_util.h b/base/file_util.h
|
|
index 90ec1ae..78827e9 100644
|
|
--- a/base/file_util.h
|
|
+++ b/base/file_util.h
|
|
@@ -259,7 +259,7 @@ BASE_EXPORT bool IsDirectoryEmpty(const FilePath& dir_path);
|
|
BASE_EXPORT bool GetTempDir(FilePath* path);
|
|
// Get a temporary directory for shared memory files.
|
|
// Only useful on POSIX; redirects to GetTempDir() on Windows.
|
|
-BASE_EXPORT bool GetShmemTempDir(FilePath* path);
|
|
+BASE_EXPORT bool GetShmemTempDir(FilePath* path, bool executable);
|
|
|
|
// Get the home directory. This is more complicated than just getenv("HOME")
|
|
// as it knows to fall back on getpwent() etc.
|
|
@@ -279,7 +279,10 @@ BASE_EXPORT bool CreateTemporaryFileInDir(const FilePath& dir,
|
|
// Returns a handle to the opened file or NULL if an error occured.
|
|
BASE_EXPORT FILE* CreateAndOpenTemporaryFile(FilePath* path);
|
|
// Like above but for shmem files. Only useful for POSIX.
|
|
-BASE_EXPORT FILE* CreateAndOpenTemporaryShmemFile(FilePath* path);
|
|
+// The executable flag says the file needs to support using
|
|
+// mprotect with PROT_EXEC after mapping.
|
|
+BASE_EXPORT FILE* CreateAndOpenTemporaryShmemFile(FilePath* path,
|
|
+ bool executable);
|
|
// Similar to CreateAndOpenTemporaryFile, but the file is created in |dir|.
|
|
BASE_EXPORT FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir,
|
|
FilePath* path);
|
|
diff --git a/base/file_util_android.cc b/base/file_util_android.cc
|
|
index eff3a46..6807d8d 100644
|
|
--- a/base/file_util_android.cc
|
|
+++ b/base/file_util_android.cc
|
|
@@ -8,7 +8,7 @@
|
|
|
|
namespace file_util {
|
|
|
|
-bool GetShmemTempDir(FilePath* path) {
|
|
+bool GetShmemTempDir(FilePath* path, bool executable) {
|
|
*path = FilePath("/data/local/tmp");
|
|
return true;
|
|
}
|
|
diff --git a/base/file_util_mac.mm b/base/file_util_mac.mm
|
|
index 95d4f25..bb4975d 100644
|
|
--- a/base/file_util_mac.mm
|
|
+++ b/base/file_util_mac.mm
|
|
@@ -1,4 +1,4 @@
|
|
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
|
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
@@ -22,7 +22,7 @@ bool GetTempDir(FilePath* path) {
|
|
return true;
|
|
}
|
|
|
|
-bool GetShmemTempDir(FilePath* path) {
|
|
+bool GetShmemTempDir(FilePath* path, bool executable) {
|
|
return GetTempDir(path);
|
|
}
|
|
|
|
diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc
|
|
index 582f70e..5c14abd 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");
|
|
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
|
|
index 00cacd6..a9f9377 100644
|
|
--- a/base/file_util_unittest.cc
|
|
+++ b/base/file_util_unittest.cc
|
|
@@ -1545,7 +1545,7 @@ TEST_F(FileUtilTest, CreateNewTemporaryDirInDirTest) {
|
|
|
|
TEST_F(FileUtilTest, GetShmemTempDirTest) {
|
|
FilePath dir;
|
|
- EXPECT_TRUE(file_util::GetShmemTempDir(&dir));
|
|
+ EXPECT_TRUE(file_util::GetShmemTempDir(&dir, false));
|
|
EXPECT_TRUE(file_util::DirectoryExists(dir));
|
|
}
|
|
|
|
diff --git a/base/file_util_win.cc b/base/file_util_win.cc
|
|
index 8d9fbde..a6720a5 100644
|
|
--- a/base/file_util_win.cc
|
|
+++ b/base/file_util_win.cc
|
|
@@ -556,7 +556,7 @@ bool GetTempDir(FilePath* path) {
|
|
return true;
|
|
}
|
|
|
|
-bool GetShmemTempDir(FilePath* path) {
|
|
+bool GetShmemTempDir(FilePath* path, bool executable) {
|
|
return GetTempDir(path);
|
|
}
|
|
|
|
@@ -576,7 +576,7 @@ bool CreateTemporaryFile(FilePath* path) {
|
|
return false;
|
|
}
|
|
|
|
-FILE* CreateAndOpenTemporaryShmemFile(FilePath* path) {
|
|
+FILE* CreateAndOpenTemporaryShmemFile(FilePath* path, bool executable) {
|
|
base::ThreadRestrictions::AssertIOAllowed();
|
|
return CreateAndOpenTemporaryFile(path);
|
|
}
|
|
diff --git a/base/shared_memory_posix.cc b/base/shared_memory_posix.cc
|
|
index 030061a..a66c859 100644
|
|
--- a/base/shared_memory_posix.cc
|
|
+++ b/base/shared_memory_posix.cc
|
|
@@ -123,7 +123,7 @@ bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
|
|
DCHECK(!options.open_existing);
|
|
// Q: Why not use the shm_open() etc. APIs?
|
|
// A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU
|
|
- fp = file_util::CreateAndOpenTemporaryShmemFile(&path);
|
|
+ fp = file_util::CreateAndOpenTemporaryShmemFile(&path, options.executable);
|
|
|
|
// Deleting the file prevents anyone else from mapping it in
|
|
// (making it private), and prevents the need for cleanup (once
|
|
@@ -317,7 +317,7 @@ bool SharedMemory::FilePathForMemoryName(const std::string& mem_name,
|
|
DCHECK_EQ(std::string::npos, mem_name.find('\0'));
|
|
|
|
FilePath temp_dir;
|
|
- if (!file_util::GetShmemTempDir(&temp_dir))
|
|
+ if (!file_util::GetShmemTempDir(&temp_dir, false))
|
|
return false;
|
|
|
|
#if !defined(OS_MACOSX)
|
|
--
|
|
1.7.6.1
|
|
|