Chromium Code Reviews| Index: base/file_util_posix.cc |
| diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc |
| index 582f70ed7c6450c7e3e3b228368abaebcc2f4cb3..d40b6ab2d93cadd44b795b321719d6569189e721 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,66 @@ 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. |
| +// |
| +// Do this once the first time we need to know. The global variable |
| +// storing the state is not locked, so there is the possibility of a race |
| +// here. But it should be a harmless one, since the answer should come back |
| +// the same on multiple attempts. |
| + |
| +namespace { |
| + |
| +enum DevShmExecutable { |
| + DevShmExecutableUnknown, |
| + DevShmExecutableYes, |
| + DevShmExecutableNo |
| +} g_dev_shm_executable; |
| + |
| +DevShmExecutable DetermineDevShmExecutable() { |
| + if (g_dev_shm_executable == DevShmExecutableUnknown) { |
| + FilePath path; |
| + int fd = CreateAndOpenFdForTemporaryFile(FilePath("/dev/shm"), &path); |
|
Mark Mentovai
2011/12/05 23:44:47
A ScopedFDClose would be a good idea here.
|
| + if (fd < 0) { |
| + g_dev_shm_executable = DevShmExecutableNo; |
| + } else { |
| + Delete(path, false); |
| + size_t pagesize = sysconf(_SC_PAGESIZE); |
| + void *mapping = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0); |
| + if (mapping == MAP_FAILED) { |
| + g_dev_shm_executable = DevShmExecutableNo; |
| + } else { |
| + if (mprotect(mapping, pagesize, PROT_READ | PROT_EXEC) == 0) |
| + g_dev_shm_executable = DevShmExecutableYes; |
| + else |
| + g_dev_shm_executable = DevShmExecutableNo; |
| + munmap(mapping, pagesize); |
| + } |
| + close(fd); |
| + } |
| + } |
| + return g_dev_shm_executable; |
| } |
| + |
| +}; // namespace |
| +#endif // defined(OS_LINUX) |
| + |
| +bool GetShmemTempDir(FilePath* path, bool executable) { |
| +#if defined(OS_LINUX) |
| + if (!executable || |
|
Mark Mentovai
2011/12/05 23:44:47
It might be better to do:
DevShmExecutable dev_
|
| + DetermineDevShmExecutable() == DevShmExecutableYes) { |
| + *path = FilePath("/dev/shm"); |
| + return true; |
| + } |
| #endif |
| + return GetTempDir(path); |
| +} |
| +#endif // !defined(OS_ANDROID) |
| FilePath GetHomeDir() { |
| const char* home_dir = getenv("HOME"); |