summaryrefslogtreecommitdiff
blob: 2c4c2b7eaace29b539dca110b6208376c58beddc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
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