OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "common/sandbox.h" | 7 #include "common/sandbox.h" |
8 | 8 |
9 #define _GNU_SOURCE | 9 #define _GNU_SOURCE |
10 #include <asm/unistd.h> | 10 #include <asm/unistd.h> |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 va_list ap; | 51 va_list ap; |
52 va_start(ap, msg); | 52 va_start(ap, msg); |
53 | 53 |
54 vfprintf(stderr, msg, ap); | 54 vfprintf(stderr, msg, ap); |
55 fprintf(stderr, ": %s\n", strerror(errno)); | 55 fprintf(stderr, ": %s\n", strerror(errno)); |
56 fflush(stderr); | 56 fflush(stderr); |
57 va_end(ap); | 57 va_end(ap); |
58 _exit(1); | 58 _exit(1); |
59 } | 59 } |
60 | 60 |
| 61 static void ExitWithErrorSignalHandler(int signal) { |
| 62 const char msg[] = "\nThe setuid sandbox got signaled, exiting.\n"; |
| 63 if (-1 == write(2, msg, sizeof(msg) - 1)) { |
| 64 // Do nothing. |
| 65 } |
| 66 |
| 67 _exit(1); |
| 68 } |
| 69 |
61 // We will chroot() to the helper's /proc/self directory. Anything there will | 70 // We will chroot() to the helper's /proc/self directory. Anything there will |
62 // not exist anymore if we make sure to wait() for the helper. | 71 // not exist anymore if we make sure to wait() for the helper. |
63 // | 72 // |
64 // /proc/self/fdinfo or /proc/self/fd are especially safe and will be empty | 73 // /proc/self/fdinfo or /proc/self/fd are especially safe and will be empty |
65 // even if the helper survives as a zombie. | 74 // even if the helper survives as a zombie. |
66 // | 75 // |
67 // There is very little reason to use fdinfo/ instead of fd/ but we are | 76 // There is very little reason to use fdinfo/ instead of fd/ but we are |
68 // paranoid. fdinfo/ only exists since 2.6.22 so we allow fallback to fd/ | 77 // paranoid. fdinfo/ only exists since 2.6.22 so we allow fallback to fd/ |
69 #define SAFE_DIR "/proc/self/fdinfo" | 78 #define SAFE_DIR "/proc/self/fdinfo" |
70 #define SAFE_DIR2 "/proc/self/fd" | 79 #define SAFE_DIR2 "/proc/self/fd" |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 } | 197 } |
189 | 198 |
190 return true; | 199 return true; |
191 } | 200 } |
192 | 201 |
193 // Block until child_pid exits, then exit. Try to preserve the exit code. | 202 // Block until child_pid exits, then exit. Try to preserve the exit code. |
194 static void WaitForChildAndExit(pid_t child_pid) { | 203 static void WaitForChildAndExit(pid_t child_pid) { |
195 int exit_code = -1; | 204 int exit_code = -1; |
196 siginfo_t reaped_child_info; | 205 siginfo_t reaped_child_info; |
197 | 206 |
| 207 // Don't "Core" on SIGABRT. SIGABRT is sent by the Chrome OS session manager |
| 208 // when things are hanging. |
| 209 // Here, the current process is going to waitid() and _exit(), so there is no |
| 210 // point in generating a crash report. The child process is the one |
| 211 // blocking us. |
| 212 if (signal(SIGABRT, ExitWithErrorSignalHandler) == SIG_ERR) { |
| 213 FatalError("Failed to change signal handler"); |
| 214 } |
| 215 |
198 int wait_ret = | 216 int wait_ret = |
199 HANDLE_EINTR(waitid(P_PID, child_pid, &reaped_child_info, WEXITED)); | 217 HANDLE_EINTR(waitid(P_PID, child_pid, &reaped_child_info, WEXITED)); |
200 | 218 |
201 if (!wait_ret && reaped_child_info.si_pid == child_pid) { | 219 if (!wait_ret && reaped_child_info.si_pid == child_pid) { |
202 if (reaped_child_info.si_code == CLD_EXITED) { | 220 if (reaped_child_info.si_code == CLD_EXITED) { |
203 exit_code = reaped_child_info.si_status; | 221 exit_code = reaped_child_info.si_status; |
204 } else { | 222 } else { |
205 // Exit with code 0 if the child got signaled. | 223 // Exit with code 0 if the child got signaled. |
206 exit_code = 0; | 224 exit_code = 0; |
207 } | 225 } |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 if (!DropRoot()) | 493 if (!DropRoot()) |
476 return 1; | 494 return 1; |
477 if (!SetupChildEnvironment()) | 495 if (!SetupChildEnvironment()) |
478 return 1; | 496 return 1; |
479 | 497 |
480 execv(argv[1], &argv[1]); | 498 execv(argv[1], &argv[1]); |
481 FatalError("execv failed"); | 499 FatalError("execv failed"); |
482 | 500 |
483 return 1; | 501 return 1; |
484 } | 502 } |
OLD | NEW |