summaryrefslogtreecommitdiffstats
path: root/chromium/sandbox/linux/suid/sandbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/sandbox/linux/suid/sandbox.c')
-rw-r--r--chromium/sandbox/linux/suid/sandbox.c93
1 files changed, 55 insertions, 38 deletions
diff --git a/chromium/sandbox/linux/suid/sandbox.c b/chromium/sandbox/linux/suid/sandbox.c
index 238a647abe9..7410b71c315 100644
--- a/chromium/sandbox/linux/suid/sandbox.c
+++ b/chromium/sandbox/linux/suid/sandbox.c
@@ -4,7 +4,7 @@
// http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox
-#include "common/sandbox.h"
+#include "sandbox/linux/suid/common/sandbox.h"
#define _GNU_SOURCE
#include <asm/unistd.h>
@@ -29,9 +29,9 @@
#include <sys/wait.h>
#include <unistd.h>
-#include "linux_util.h"
-#include "process_util.h"
-#include "common/suid_unsafe_environment_variables.h"
+#include "sandbox/linux/suid/common/suid_unsafe_environment_variables.h"
+#include "sandbox/linux/suid/linux_util.h"
+#include "sandbox/linux/suid/process_util.h"
#if !defined(CLONE_NEWPID)
#define CLONE_NEWPID 0x20000000
@@ -44,10 +44,10 @@ static bool DropRoot();
#define HANDLE_EINTR(x) TEMP_FAILURE_RETRY(x)
-static void FatalError(const char *msg, ...)
+static void FatalError(const char* msg, ...)
__attribute__((noreturn, format(printf, 1, 2)));
-static void FatalError(const char *msg, ...) {
+static void FatalError(const char* msg, ...) {
va_list ap;
va_start(ap, msg);
@@ -85,20 +85,18 @@ static bool SpawnChrootHelper() {
return false;
}
- char *safedir = NULL;
+ char* safedir = NULL;
struct stat sdir_stat;
- if (!stat(SAFE_DIR, &sdir_stat) && S_ISDIR(sdir_stat.st_mode))
+ if (!stat(SAFE_DIR, &sdir_stat) && S_ISDIR(sdir_stat.st_mode)) {
safedir = SAFE_DIR;
- else
- if (!stat(SAFE_DIR2, &sdir_stat) && S_ISDIR(sdir_stat.st_mode))
- safedir = SAFE_DIR2;
- else {
- fprintf(stderr, "Could not find %s\n", SAFE_DIR2);
- return false;
- }
+ } else if (!stat(SAFE_DIR2, &sdir_stat) && S_ISDIR(sdir_stat.st_mode)) {
+ safedir = SAFE_DIR2;
+ } else {
+ fprintf(stderr, "Could not find %s\n", SAFE_DIR2);
+ return false;
+ }
- const pid_t pid = syscall(
- __NR_clone, CLONE_FS | SIGCHLD, 0, 0, 0);
+ const pid_t pid = syscall(__NR_clone, CLONE_FS | SIGCHLD, 0, 0, 0);
if (pid == -1) {
perror("clone");
@@ -214,7 +212,7 @@ static void WaitForChildAndExit(pid_t child_pid) {
}
int wait_ret =
- HANDLE_EINTR(waitid(P_PID, child_pid, &reaped_child_info, WEXITED));
+ HANDLE_EINTR(waitid(P_PID, child_pid, &reaped_child_info, WEXITED));
if (!wait_ret && reaped_child_info.si_pid == child_pid) {
if (reaped_child_info.si_code == CLD_EXITED) {
@@ -229,10 +227,7 @@ static void WaitForChildAndExit(pid_t child_pid) {
static bool MoveToNewNamespaces() {
// These are the sets of flags which we'll try, in order.
- const int kCloneExtraFlags[] = {
- CLONE_NEWPID | CLONE_NEWNET,
- CLONE_NEWPID,
- };
+ const int kCloneExtraFlags[] = {CLONE_NEWPID | CLONE_NEWNET, CLONE_NEWPID, };
// We need to close kZygoteIdFd before the child can continue. We use this
// socketpair to tell the child when to continue;
@@ -241,10 +236,10 @@ static bool MoveToNewNamespaces() {
FatalError("Failed to create a socketpair");
}
- for (size_t i = 0;
- i < sizeof(kCloneExtraFlags) / sizeof(kCloneExtraFlags[0]);
+ for (size_t i = 0; i < sizeof(kCloneExtraFlags) / sizeof(kCloneExtraFlags[0]);
i++) {
pid_t pid = syscall(__NR_clone, SIGCHLD | kCloneExtraFlags[i], 0, 0, 0);
+ const int clone_errno = errno;
if (pid > 0) {
if (!DropRoot()) {
@@ -296,8 +291,20 @@ static bool MoveToNewNamespaces() {
break;
}
+ // If EINVAL then the system doesn't support the requested flags, so
+ // continue to try a different set.
+ // On any other errno value the system *does* support these flags but
+ // something went wrong, hence we bail with an error message rather then
+ // provide less security.
if (errno != EINVAL) {
- perror("Failed to move to new PID namespace");
+ fprintf(stderr, "Failed to move to new namespace:");
+ if (kCloneExtraFlags[i] & CLONE_NEWPID) {
+ fprintf(stderr, " PID namespaces supported,");
+ }
+ if (kCloneExtraFlags[i] & CLONE_NEWNET) {
+ fprintf(stderr, " Network namespace supported,");
+ }
+ fprintf(stderr, " but failed: errno = %s\n", strerror(clone_errno));
return false;
}
}
@@ -373,7 +380,7 @@ bool CheckAndExportApiVersion() {
// Check the environment to see if a specific API version was requested.
// assume version 0 if none.
long api_number = -1;
- char *api_string = getenv(kSandboxEnvironmentApiRequest);
+ char* api_string = getenv(kSandboxEnvironmentApiRequest);
if (!api_string) {
api_number = 0;
} else {
@@ -386,20 +393,22 @@ bool CheckAndExportApiVersion() {
// Warn only for now.
if (api_number != kSUIDSandboxApiNumber) {
- fprintf(stderr, "The setuid sandbox provides API version %ld, "
- "but you need %ld\n"
- "Please read "
- "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment."
- "\n\n",
- kSUIDSandboxApiNumber,
- api_number);
+ fprintf(
+ stderr,
+ "The setuid sandbox provides API version %ld, "
+ "but you need %ld\n"
+ "Please read "
+ "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment."
+ "\n\n",
+ kSUIDSandboxApiNumber,
+ api_number);
}
// Export our version so that the sandboxed process can verify it did not
// use an old sandbox.
char version_string[64];
- snprintf(version_string, sizeof(version_string), "%ld",
- kSUIDSandboxApiNumber);
+ snprintf(
+ version_string, sizeof(version_string), "%ld", kSUIDSandboxApiNumber);
if (setenv(kSandboxEnvironmentApiProvides, version_string, 1)) {
perror("setenv");
return false;
@@ -408,7 +417,7 @@ bool CheckAndExportApiVersion() {
return true;
}
-int main(int argc, char **argv) {
+int main(int argc, char** argv) {
if (argc <= 1) {
if (argc <= 0) {
return 1;
@@ -463,9 +472,10 @@ int main(int argc, char **argv) {
endptr = NULL;
errno = 0;
score = strtol(argv[3], &endptr, 10);
- if (score == LONG_MAX || score == LONG_MIN ||
- !endptr || *endptr || errno != 0)
+ if (score == LONG_MAX || score == LONG_MIN || !endptr || *endptr ||
+ errno != 0) {
return 1;
+ }
return AdjustOOMScore(pid, score);
}
@@ -474,6 +484,13 @@ int main(int argc, char **argv) {
return 1;
}
+ if (geteuid() != 0) {
+ fprintf(stderr,
+ "The setuid sandbox is not running as root. Common causes:\n"
+ " * An unprivileged process using ptrace on it, like a debugger.\n"
+ " * A parent process set prctl(PR_SET_NO_NEW_PRIVS, ...)\n");
+ }
+
if (!MoveToNewNamespaces())
return 1;
if (!SpawnChrootHelper())