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

Side by Side Diff: sandbox/linux/suid/sandbox.c

Issue 312003: Allow chrome_sandbox to act as a helper program and find the socket with a gi... (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/suid/linux_util.c ('k') | sandbox/sandbox.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox 5 // http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox
6 6
7 #define _GNU_SOURCE 7 #define _GNU_SOURCE
8 #include <asm/unistd.h> 8 #include <asm/unistd.h>
9 #include <errno.h> 9 #include <errno.h>
10 #include <fcntl.h> 10 #include <fcntl.h>
11 #include <sched.h> 11 #include <sched.h>
12 #include <signal.h> 12 #include <signal.h>
13 #include <stdarg.h> 13 #include <stdarg.h>
14 #include <stdbool.h>
15 #include <stdint.h>
14 #include <stdio.h> 16 #include <stdio.h>
15 #include <stdlib.h> 17 #include <stdlib.h>
16 #include <string.h> 18 #include <string.h>
17 #include <sys/prctl.h> 19 #include <sys/prctl.h>
18 #include <sys/resource.h> 20 #include <sys/resource.h>
19 #include <sys/socket.h> 21 #include <sys/socket.h>
20 #include <sys/stat.h> 22 #include <sys/stat.h>
21 #include <sys/time.h> 23 #include <sys/time.h>
22 #include <sys/types.h> 24 #include <sys/types.h>
23 #include <unistd.h> 25 #include <unistd.h>
24 #include <stdbool.h>
25 26
27 #include "linux_util.h"
26 #include "suid_unsafe_environment_variables.h" 28 #include "suid_unsafe_environment_variables.h"
27 29
28 #if !defined(CLONE_NEWPID) 30 #if !defined(CLONE_NEWPID)
29 #define CLONE_NEWPID 0x20000000 31 #define CLONE_NEWPID 0x20000000
30 #endif 32 #endif
31 33
32 static const char kSandboxDescriptorEnvironmentVarName[] = "SBX_D"; 34 static const char kSandboxDescriptorEnvironmentVarName[] = "SBX_D";
33 35
34 // These are the magic byte values which the sandboxed process uses to request 36 // These are the magic byte values which the sandboxed process uses to request
35 // that it be chrooted. 37 // that it be chrooted.
36 static const char kMsgChrootMe = 'C'; 38 static const char kMsgChrootMe = 'C';
37 static const char kMsgChrootSuccessful = 'O'; 39 static const char kMsgChrootSuccessful = 'O';
38 40
39 static void FatalError(const char *msg, ...) 41 static void FatalError(const char *msg, ...)
40 __attribute__((noreturn, format(printf,1,2))); 42 __attribute__((noreturn, format(printf, 1, 2)));
41 43
42 static void FatalError(const char *msg, ...) { 44 static void FatalError(const char *msg, ...) {
43 va_list ap; 45 va_list ap;
44 va_start(ap, msg); 46 va_start(ap, msg);
45 47
46 vfprintf(stderr, msg, ap); 48 vfprintf(stderr, msg, ap);
47 fprintf(stderr, ": %s\n", strerror(errno)); 49 fprintf(stderr, ": %s\n", strerror(errno));
48 fflush(stderr); 50 fflush(stderr);
49 exit(1); 51 exit(1);
50 } 52 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 if (pid == -1) { 104 if (pid == -1) {
103 perror("clone"); 105 perror("clone");
104 close(sv[0]); 106 close(sv[0]);
105 close(sv[1]); 107 close(sv[1]);
106 return -1; 108 return -1;
107 } 109 }
108 110
109 if (pid == 0) { 111 if (pid == 0) {
110 // We share our files structure with an untrusted process. As a security in 112 // We share our files structure with an untrusted process. As a security in
111 // depth measure, we make sure that we can't open anything by mistake. 113 // depth measure, we make sure that we can't open anything by mistake.
112 // TODO: drop CAP_SYS_RESOURCE / use SECURE_NOROOT 114 // TODO(agl): drop CAP_SYS_RESOURCE / use SECURE_NOROOT
113 115
114 const struct rlimit nofile = {0, 0}; 116 const struct rlimit nofile = {0, 0};
115 if (setrlimit(RLIMIT_NOFILE, &nofile)) 117 if (setrlimit(RLIMIT_NOFILE, &nofile))
116 FatalError("Setting RLIMIT_NOFILE"); 118 FatalError("Setting RLIMIT_NOFILE");
117 119
118 if (close(sv[1])) 120 if (close(sv[1]))
119 FatalError("close"); 121 FatalError("close");
120 122
121 // wait for message 123 // wait for message
122 char msg; 124 char msg;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 253
252 if (setresuid(ruid, ruid, ruid)) { 254 if (setresuid(ruid, ruid, ruid)) {
253 perror("setresuid"); 255 perror("setresuid");
254 return false; 256 return false;
255 } 257 }
256 258
257 return true; 259 return true;
258 } 260 }
259 261
260 static bool SetupChildEnvironment() { 262 static bool SetupChildEnvironment() {
261
262 unsigned i; 263 unsigned i;
263 264
264 // ld.so may have cleared several environment variables because we are SUID. 265 // ld.so may have cleared several environment variables because we are SUID.
265 // However, the child process might need them so zygote_host_linux.cc saves a 266 // However, the child process might need them so zygote_host_linux.cc saves a
266 // copy in SANDBOX_$x. This is safe because we have dropped root by this 267 // copy in SANDBOX_$x. This is safe because we have dropped root by this
267 // point, so we can only exec a binary with the permissions of the user who 268 // point, so we can only exec a binary with the permissions of the user who
268 // ran us in the first place. 269 // ran us in the first place.
269 270
270 for (i = 0; kSUIDUnsafeEnvironmentVariables[i]; ++i) { 271 for (i = 0; kSUIDUnsafeEnvironmentVariables[i]; ++i) {
271 const char* const envvar = kSUIDUnsafeEnvironmentVariables[i]; 272 const char* const envvar = kSUIDUnsafeEnvironmentVariables[i];
(...skipping 12 matching lines...) Expand all
284 285
285 return true; 286 return true;
286 } 287 }
287 288
288 int main(int argc, char **argv) { 289 int main(int argc, char **argv) {
289 if (argc <= 1) { 290 if (argc <= 1) {
290 fprintf(stderr, "Usage: %s <renderer process> <args...>\n", argv[0]); 291 fprintf(stderr, "Usage: %s <renderer process> <args...>\n", argv[0]);
291 return 1; 292 return 1;
292 } 293 }
293 294
295 // In the SUID sandbox, if we succeed in calling MoveToNewPIDNamespace()
296 // below, then the zygote and all the renderers are in an alternate PID
297 // namespace and do not know their real PIDs. As such, they report the wrong
298 // PIDs to the task manager.
299 //
300 // To fix this, when the zygote spawns a new renderer, it gives the renderer
301 // a dummy socket, which has a unique inode number. Then it asks the sandbox
302 // host to find the PID of the process holding that fd by searching /proc.
303 //
304 // Since the zygote and renderers are all spawned by this setuid executable,
305 // their entries in /proc are owned by root and only readable by root. In
306 // order to search /proc for the fd we want, this setuid executable has to
307 // double as a helper and perform the search. The code block below does this
308 // when you call it with --find-inode INODE_NUMBER.
309 if (argc == 3 && (0 == strcmp(argv[1], kFindInodeSwitch))) {
310 pid_t pid;
311 char *endptr;
312 ino_t inode = strtoull(argv[2], &endptr, 10);
313 if (inode == ULLONG_MAX || *endptr)
314 return 1;
315 if (!FindProcessHoldingSocket(&pid, inode))
316 return 1;
317 printf("%d\n", pid);
318 return 0;
319 }
320
294 if (!MoveToNewPIDNamespace()) 321 if (!MoveToNewPIDNamespace())
295 return 1; 322 return 1;
296 if (!SpawnChrootHelper()) 323 if (!SpawnChrootHelper())
297 return 1; 324 return 1;
298 if (!DropRoot()) 325 if (!DropRoot())
299 return 1; 326 return 1;
300 if (!SetupChildEnvironment()) 327 if (!SetupChildEnvironment())
301 return 1; 328 return 1;
302 329
303 execv(argv[1], &argv[1]); 330 execv(argv[1], &argv[1]);
304 FatalError("execv failed"); 331 FatalError("execv failed");
305 332
306 return 1; 333 return 1;
307 } 334 }
OLDNEW
« no previous file with comments | « sandbox/linux/suid/linux_util.c ('k') | sandbox/sandbox.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698