Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: sandbox/linux/seccomp/trusted_process.cc

Issue 371047: Allow the seccomp sandbox to be enabled, even if the suid sandbox has... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sandbox/linux/seccomp/syscall_table.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
1 #include <dirent.h> 1 #include <dirent.h>
2 #include <map> 2 #include <map>
3 3
4 #include "debug.h" 4 #include "debug.h"
5 #include "sandbox_impl.h" 5 #include "sandbox_impl.h"
6 #include "syscall_table.h" 6 #include "syscall_table.h"
7 7
8 namespace playground { 8 namespace playground {
9 9
10 struct Thread { 10 struct Thread {
11 int fdPub, fd; 11 int fdPub, fd;
12 SecureMem::Args* mem; 12 SecureMem::Args* mem;
13 }; 13 };
14 14
15 SecureMem::Args* Sandbox::getSecureMem() { 15 SecureMem::Args* Sandbox::getSecureMem() {
16 if (!secureMemPool_.empty()) { 16 if (!secureMemPool_.empty()) {
17 SecureMem::Args* rc = secureMemPool_.back(); 17 SecureMem::Args* rc = secureMemPool_.back();
18 secureMemPool_.pop_back(); 18 secureMemPool_.pop_back();
19 return rc; 19 return rc;
20 } 20 }
21 return NULL; 21 return NULL;
22 } 22 }
23 23
24 void Sandbox::trustedProcess(int parentProc, int processFdPub, int sandboxFd, 24 void Sandbox::trustedProcess(int parentMapsFd, int processFdPub, int sandboxFd,
25 int cloneFd, SecureMem::Args* secureArena) { 25 int cloneFd, SecureMem::Args* secureArena) {
26 std::map<long long, struct Thread> threads; 26 std::map<long long, struct Thread> threads;
27 SysCalls sys; 27 SysCalls sys;
28 long long cookie = 0; 28 long long cookie = 0;
29 29
30 // The very first entry in the secure memory arena has been assigned to the 30 // The very first entry in the secure memory arena has been assigned to the
31 // initial thread. The remaining entries are available for allocation. 31 // initial thread. The remaining entries are available for allocation.
32 SecureMem::Args* startAddress = secureArena; 32 SecureMem::Args* startAddress = secureArena;
33 SecureMem::Args* nextThread = startAddress; 33 SecureMem::Args* nextThread = startAddress;
34 for (int i = 0; i < kMaxThreads-1; i++) { 34 for (int i = 0; i < kMaxThreads-1; i++) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 die("Received request from unknown thread"); 92 die("Received request from unknown thread");
93 } 93 }
94 struct Thread* currentThread = &iter->second; 94 struct Thread* currentThread = &iter->second;
95 if (header.sysnum > maxSyscall || 95 if (header.sysnum > maxSyscall ||
96 !syscallTable[header.sysnum].trustedProcess) { 96 !syscallTable[header.sysnum].trustedProcess) {
97 die("Trusted process encountered unexpected system call"); 97 die("Trusted process encountered unexpected system call");
98 } 98 }
99 99
100 // Dispatch system call to handler function. Treat both exit() and clone() 100 // Dispatch system call to handler function. Treat both exit() and clone()
101 // specially. 101 // specially.
102 if (syscallTable[header.sysnum].trustedProcess(parentProc, 102 if (syscallTable[header.sysnum].trustedProcess(parentMapsFd,
103 sandboxFd, 103 sandboxFd,
104 currentThread->fdPub, 104 currentThread->fdPub,
105 currentThread->fd, 105 currentThread->fd,
106 currentThread->mem) && 106 currentThread->mem) &&
107 header.sysnum == __NR_clone) { 107 header.sysnum == __NR_clone) {
108 nextThread = currentThread->mem->newSecureMem; 108 nextThread = currentThread->mem->newSecureMem;
109 goto newThreadCreated; 109 goto newThreadCreated;
110 } else if (header.sysnum == __NR_exit) { 110 } else if (header.sysnum == __NR_exit) {
111 NOINTR_SYS(sys.close(iter->second.fdPub)); 111 NOINTR_SYS(sys.close(iter->second.fdPub));
112 NOINTR_SYS(sys.close(iter->second.fd)); 112 NOINTR_SYS(sys.close(iter->second.fd));
113 SecureMem::Args* secureMem = currentThread->mem; 113 SecureMem::Args* secureMem = currentThread->mem;
114 threads.erase(iter); 114 threads.erase(iter);
115 secureMemPool_.push_back(secureMem); 115 secureMemPool_.push_back(secureMem);
116 } 116 }
117 } 117 }
118 } 118 }
119 119
120 void Sandbox::initializeProtectedMap(int fd) { 120 int Sandbox::initializeProtectedMap(int fd) {
121 int mapsFd; 121 int mapsFd;
122 if (!getFd(fd, &mapsFd, NULL, NULL, NULL)) { 122 if (!getFd(fd, &mapsFd, NULL, NULL, NULL)) {
123 maps_failure: 123 maps_failure:
124 die("Cannot access /proc/self/maps"); 124 die("Cannot access /proc/self/maps");
125 } 125 }
126 126
127 // Read the memory mappings as they were before the sandbox takes effect. 127 // Read the memory mappings as they were before the sandbox takes effect.
128 // These mappings cannot be changed by the sandboxed process. 128 // These mappings cannot be changed by the sandboxed process.
129 char line[80]; 129 char line[80];
130 FILE *fp = fdopen(mapsFd, "r"); 130 FILE *fp = fdopen(mapsFd, "r");
(...skipping 14 matching lines...) Expand all
145 die("Failed to parse /proc/self/maps"); 145 die("Failed to parse /proc/self/maps");
146 } 146 }
147 stop = strtoul(ptr, &ptr, 16); 147 stop = strtoul(ptr, &ptr, 16);
148 if (errno || *ptr++ != ' ') { 148 if (errno || *ptr++ != ' ') {
149 goto parse_failure; 149 goto parse_failure;
150 } 150 }
151 protectedMap_[reinterpret_cast<void *>(start)] = stop - start; 151 protectedMap_[reinterpret_cast<void *>(start)] = stop - start;
152 } 152 }
153 truncated = strchr(line, '\n') == NULL; 153 truncated = strchr(line, '\n') == NULL;
154 } 154 }
155 SysCalls sys;
156 NOINTR_SYS(sys.close(mapsFd));
157 155
158 // Prevent low address memory allocations. Some buggy kernels allow those 156 // Prevent low address memory allocations. Some buggy kernels allow those
159 if (protectedMap_[0] < (64 << 10)) { 157 if (protectedMap_[0] < (64 << 10)) {
160 protectedMap_[0] = 64 << 10; 158 protectedMap_[0] = 64 << 10;
161 } 159 }
162 160
163 // Let the sandbox know that we are done parsing the memory map. 161 // Let the sandbox know that we are done parsing the memory map.
162 SysCalls sys;
164 if (write(sys, fd, &mapsFd, sizeof(mapsFd)) != sizeof(mapsFd)) { 163 if (write(sys, fd, &mapsFd, sizeof(mapsFd)) != sizeof(mapsFd)) {
165 goto maps_failure; 164 goto maps_failure;
166 } 165 }
166
167 return mapsFd;
167 } 168 }
168 169
169 SecureMem::Args* Sandbox::createTrustedProcess(int processFdPub, int sandboxFd, 170 SecureMem::Args* Sandbox::createTrustedProcess(int processFdPub, int sandboxFd,
170 int cloneFdPub, int cloneFd) { 171 int cloneFdPub, int cloneFd) {
171 // Allocate memory that will be used by an arena for storing the secure 172 // Allocate memory that will be used by an arena for storing the secure
172 // memory. While we allow this memory area to be empty at times (e.g. when 173 // memory. While we allow this memory area to be empty at times (e.g. when
173 // not all threads are in use), we make sure that it never gets overwritten 174 // not all threads are in use), we make sure that it never gets overwritten
174 // by user-allocated memory. This happens in initializeProtectedMap() and 175 // by user-allocated memory. This happens in initializeProtectedMap() and
175 // snapshotMemoryMappings(). 176 // snapshotMemoryMappings().
176 SecureMem::Args* secureArena = reinterpret_cast<SecureMem::Args*>( 177 SecureMem::Args* secureArena = reinterpret_cast<SecureMem::Args*>(
177 mmap(NULL, 8192*kMaxThreads, PROT_READ|PROT_WRITE, 178 mmap(NULL, 8192*kMaxThreads, PROT_READ|PROT_WRITE,
178 MAP_SHARED|MAP_ANONYMOUS, -1, 0)); 179 MAP_SHARED|MAP_ANONYMOUS, -1, 0));
179 if (secureArena == MAP_FAILED) { 180 if (secureArena == MAP_FAILED) {
180 die("Failed to allocate secure memory arena"); 181 die("Failed to allocate secure memory arena");
181 } 182 }
182 183
183 // Set up the mutex to be accessible from the trusted process and from 184 // Set up the mutex to be accessible from the trusted process and from
184 // children of the trusted thread(s) 185 // children of the trusted thread(s)
185 if (mmap(&syscall_mutex_, 4096, PROT_READ|PROT_WRITE, 186 if (mmap(&syscall_mutex_, 4096, PROT_READ|PROT_WRITE,
186 MAP_SHARED|MAP_ANONYMOUS|MAP_FIXED, -1, 0) != &syscall_mutex_) { 187 MAP_SHARED|MAP_ANONYMOUS|MAP_FIXED, -1, 0) != &syscall_mutex_) {
187 die("Failed to initialize secure mutex"); 188 die("Failed to initialize secure mutex");
188 } 189 }
189 syscall_mutex_ = 0x80000000; 190 syscall_mutex_ = 0x80000000;
190 191
191 192
192 // Hold on to a file handle in the parent's process directory. We can use
193 // this later to reliably tell if the parent died.
194 int parentProc = open("/proc/self/", O_RDONLY|O_DIRECTORY);
195 if (parentProc < 0) {
196 die("Failed to access /proc/self");
197 }
198
199 // Create a trusted process that can evaluate system call parameters and 193 // Create a trusted process that can evaluate system call parameters and
200 // decide whether a system call should execute. This process runs outside of 194 // decide whether a system call should execute. This process runs outside of
201 // the seccomp sandbox. It communicates with the sandbox'd process through 195 // the seccomp sandbox. It communicates with the sandbox'd process through
202 // a socketpair() and through securely shared memory. 196 // a socketpair() and through securely shared memory.
203 pid_t pid = fork(); 197 pid_t pid = fork();
204 if (pid < 0) { 198 if (pid < 0) {
205 die("Failed to create trusted process"); 199 die("Failed to create trusted process");
206 } 200 }
207 if (!pid) { 201 if (!pid) {
208 // Close all file handles except for sandboxFd, cloneFd, and stdio 202 // Close all file handles except for sandboxFd, cloneFd, and stdio
209 DIR *dir = opendir("/proc/self/fd"); 203 DIR *dir = opendir("/proc/self/fd");
210 if (dir == 0) { 204 if (dir == 0) {
211 // If we don't know the list of our open file handles, just try closing 205 // If we don't know the list of our open file handles, just try closing
212 // all valid ones. 206 // all valid ones.
213 for (int fd = sysconf(_SC_OPEN_MAX); --fd > 2; ) { 207 for (int fd = sysconf(_SC_OPEN_MAX); --fd > 2; ) {
214 if (fd != parentProc && fd != sandboxFd && fd != cloneFd) { 208 if (fd != sandboxFd && fd != cloneFd) {
215 close(fd); 209 close(fd);
216 } 210 }
217 } 211 }
218 } else { 212 } else {
219 // If available, if is much more efficient to just close the file 213 // If available, if is much more efficient to just close the file
220 // handles that show up in /proc/self/fd/ 214 // handles that show up in /proc/self/fd/
221 struct dirent de, *res; 215 struct dirent de, *res;
222 while (!readdir_r(dir, &de, &res) && res) { 216 while (!readdir_r(dir, &de, &res) && res) {
223 if (res->d_name[0] < '0') 217 if (res->d_name[0] < '0')
224 continue; 218 continue;
225 int fd = atoi(res->d_name); 219 int fd = atoi(res->d_name);
226 if (fd > 2 && 220 if (fd > 2 &&
227 fd != parentProc && fd != sandboxFd && fd != cloneFd && 221 fd != sandboxFd && fd != cloneFd && fd != dirfd(dir)) {
228 fd != dirfd(dir)) {
229 close(fd); 222 close(fd);
230 } 223 }
231 } 224 }
232 closedir(dir); 225 closedir(dir);
233 } 226 }
234 227
235 // Initialize secure memory used for threads 228 // Initialize secure memory used for threads
236 for (int i = 0; i < kMaxThreads; i++) { 229 for (int i = 0; i < kMaxThreads; i++) {
237 SecureMem::Args* args = secureArena + i; 230 SecureMem::Args* args = secureArena + i;
238 args->self = args; 231 args->self = args;
239 #ifndef NDEBUG 232 #ifndef NDEBUG
240 args->allowAllSystemCalls= Debug::isEnabled(); 233 args->allowAllSystemCalls= Debug::isEnabled();
241 #endif 234 #endif
242 } 235 }
243 236
244 initializeProtectedMap(sandboxFd); 237 int parentMapsFd = initializeProtectedMap(sandboxFd);
245 trustedProcess(parentProc, processFdPub, sandboxFd, cloneFd, secureArena); 238 trustedProcess(parentMapsFd, processFdPub, sandboxFd,
239 cloneFd, secureArena);
246 die(); 240 die();
247 } 241 }
248 242
249 // We are still in the untrusted code. Deny access to restricted resources. 243 // We are still in the untrusted code. Deny access to restricted resources.
250 mprotect(secureArena, 8192*kMaxThreads, PROT_NONE); 244 mprotect(secureArena, 8192*kMaxThreads, PROT_NONE);
251 mprotect(&syscall_mutex_, 4096, PROT_NONE); 245 mprotect(&syscall_mutex_, 4096, PROT_NONE);
252 close(parentProc);
253 close(sandboxFd); 246 close(sandboxFd);
254 247
255 return secureArena; 248 return secureArena;
256 } 249 }
257 250
258 } // namespace 251 } // namespace
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp/syscall_table.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698