Skip to content
This repository has been archived by the owner on Sep 25, 2019. It is now read-only.

Commit

Permalink
Adaptively use temp dir instead of /dev/shm for executable shmem file…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
mcgrathr@chromium.org committed Dec 6, 2011
1 parent 6f12151 commit 33331a2
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 18 deletions.
7 changes: 5 additions & 2 deletions base/file_util.h
Expand Up @@ -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.
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion base/file_util_android.cc
Expand Up @@ -8,7 +8,7 @@

namespace file_util {

bool GetShmemTempDir(FilePath* path) {
bool GetShmemTempDir(FilePath* path, bool executable) {
*path = FilePath("/data/local/tmp");
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions 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.

Expand All @@ -22,7 +22,7 @@ bool GetTempDir(FilePath* path) {
return true;
}

bool GetShmemTempDir(FilePath* path) {
bool GetShmemTempDir(FilePath* path, bool executable) {
return GetTempDir(path);
}

Expand Down
53 changes: 45 additions & 8 deletions base/file_util_posix.cc
Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion base/file_util_unittest.cc
Expand Up @@ -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));
}

Expand Down
4 changes: 2 additions & 2 deletions base/file_util_win.cc
Expand Up @@ -556,7 +556,7 @@ bool GetTempDir(FilePath* path) {
return true;
}

bool GetShmemTempDir(FilePath* path) {
bool GetShmemTempDir(FilePath* path, bool executable) {
return GetTempDir(path);
}

Expand All @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions base/shared_memory_posix.cc
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 33331a2

Please sign in to comment.