diff options
author | mcgrathr@chromium.org <mcgrathr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-06 18:07:05 +0000 |
---|---|---|
committer | mcgrathr@chromium.org <mcgrathr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-06 18:07:05 +0000 |
commit | 103dccfa2877fed72cdcd7daafba3c81a51ab923 (patch) | |
tree | d45afb9c2a47c9fe53c0e98dfd0f3d02f4dd173d | |
parent | a1cff7858ed955e9792955dce46277ba57b2cb81 (diff) | |
download | chromium_src-103dccfa2877fed72cdcd7daafba3c81a51ab923.zip chromium_src-103dccfa2877fed72cdcd7daafba3c81a51ab923.tar.gz chromium_src-103dccfa2877fed72cdcd7daafba3c81a51ab923.tar.bz2 |
Adaptively use temp dir instead of /dev/shm for executable shmem file on Linux
On some Linux systems, files from /dev/shm cannot have PROT_EXEC applied to
their mappings. This depends on picayune setup details that vary between
distributions and kernels and could vary between installations. So just
use an empirical test of whether it works or not, and fall back to using
generic temporary space instead of /dev/shm for the executable case if needed.
BUG= http://code.google.com/p/chromium/issues/detail?id=103377
TEST= SharedMemory.AnonymousExecutable with /dev/shm mounted noexec
R=mark@chromium.org
Review URL: http://codereview.chromium.org/8800025
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113228 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/file_util.h | 7 | ||||
-rw-r--r-- | base/file_util_android.cc | 2 | ||||
-rw-r--r-- | base/file_util_mac.mm | 4 | ||||
-rw-r--r-- | base/file_util_posix.cc | 53 | ||||
-rw-r--r-- | base/file_util_unittest.cc | 2 | ||||
-rw-r--r-- | base/file_util_win.cc | 4 | ||||
-rw-r--r-- | base/shared_memory_posix.cc | 4 |
7 files changed, 58 insertions, 18 deletions
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 8d9fbdef..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 030061a0..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) |