Index: sandbox/linux/suid/sandbox.c |
diff --git a/sandbox/linux/suid/sandbox.c b/sandbox/linux/suid/sandbox.c |
index 41a68c73119b4af53157bd07c4a7c30b8ee92de5..ef8049db34769a787d2f88bda4e4a4ab88ddc08b 100644 |
--- a/sandbox/linux/suid/sandbox.c |
+++ b/sandbox/linux/suid/sandbox.c |
@@ -1,4 +1,4 @@ |
-// Copyright (c) 2012 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. |
@@ -28,7 +28,6 @@ |
#include <sys/vfs.h> |
#include <unistd.h> |
-#include "init_process.h" |
#include "linux_util.h" |
#include "process_util.h" |
#include "suid_unsafe_environment_variables.h" |
@@ -72,47 +71,11 @@ static void FatalError(const char *msg, ...) { |
#define SAFE_DIR "/proc/self/fdinfo" |
#define SAFE_DIR2 "/proc/self/fd" |
-static bool DropRoot() { |
- if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0)) { |
- perror("prctl(PR_SET_DUMPABLE)"); |
- return false; |
- } |
- |
- if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) { |
- perror("Still dumpable after prctl(PR_SET_DUMPABLE)"); |
- return false; |
- } |
- |
- gid_t rgid, egid, sgid; |
- if (getresgid(&rgid, &egid, &sgid)) { |
- perror("getresgid"); |
- return false; |
- } |
- |
- if (setresgid(rgid, rgid, rgid)) { |
- perror("setresgid"); |
- return false; |
- } |
- |
- uid_t ruid, euid, suid; |
- if (getresuid(&ruid, &euid, &suid)) { |
- perror("getresuid"); |
- return false; |
- } |
- |
- if (setresuid(ruid, ruid, ruid)) { |
- perror("setresuid"); |
- return false; |
- } |
- |
- return true; |
-} |
- |
-static int SpawnChrootHelper() { |
+static bool SpawnChrootHelper() { |
int sv[2]; |
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) { |
perror("socketpair"); |
- return -1; |
+ return false; |
} |
char *safedir = NULL; |
@@ -124,7 +87,7 @@ static int SpawnChrootHelper() { |
safedir = SAFE_DIR2; |
else { |
fprintf(stderr, "Could not find %s\n", SAFE_DIR2); |
- return -1; |
+ return false; |
} |
const pid_t pid = syscall( |
@@ -134,7 +97,7 @@ static int SpawnChrootHelper() { |
perror("clone"); |
close(sv[0]); |
close(sv[1]); |
- return -1; |
+ return false; |
} |
if (pid == 0) { |
@@ -162,7 +125,6 @@ static int SpawnChrootHelper() { |
FatalError("read"); |
// do chrooting |
- errno = 0; |
if (msg != kMsgChrootMe) |
FatalError("Unknown message from sandboxed process"); |
@@ -195,7 +157,7 @@ static int SpawnChrootHelper() { |
if (close(sv[0])) { |
close(sv[1]); |
perror("close"); |
- return -1; |
+ return false; |
} |
// In the parent process, we install an environment variable containing the |
@@ -204,14 +166,13 @@ static int SpawnChrootHelper() { |
int printed = snprintf(desc_str, sizeof(desc_str), "%u", sv[1]); |
if (printed < 0 || printed >= (int)sizeof(desc_str)) { |
fprintf(stderr, "Failed to snprintf\n"); |
- close(sv[1]); |
- return -1; |
+ return false; |
} |
if (setenv(kSandboxDescriptorEnvironmentVarName, desc_str, 1)) { |
perror("setenv"); |
close(sv[1]); |
- return -1; |
+ return false; |
} |
// We also install an environment variable containing the pid of the child |
@@ -219,51 +180,15 @@ static int SpawnChrootHelper() { |
printed = snprintf(helper_pid_str, sizeof(helper_pid_str), "%u", pid); |
if (printed < 0 || printed >= (int)sizeof(helper_pid_str)) { |
fprintf(stderr, "Failed to snprintf\n"); |
- close(sv[1]); |
- return -1; |
+ return false; |
} |
if (setenv(kSandboxHelperPidEnvironmentVarName, helper_pid_str, 1)) { |
perror("setenv"); |
close(sv[1]); |
- return -1; |
- } |
- |
- return sv[1]; |
-} |
- |
-static bool JailMe() { |
- int fd = SpawnChrootHelper(); |
- if (fd < 0) { |
- return false; |
- } |
- if (!DropRoot()) { |
- close(fd); |
- return false; |
- } |
- ssize_t bytes; |
- char ch = kMsgChrootMe; |
- do { |
- errno = 0; |
- bytes = write(fd, &ch, 1); |
- } while (bytes == -1 && errno == EINTR); |
- if (bytes != 1) { |
- perror("write"); |
- close(fd); |
- return false; |
- } |
- do { |
- errno = 0; |
- bytes = read(fd, &ch, 1); |
- } while (bytes == -1 && errno == EINTR); |
- close(fd); |
- if (bytes != 1) { |
- perror("read"); |
- return false; |
- } |
- if (ch != kMsgChrootSuccessful) { |
return false; |
} |
+ |
return true; |
} |
@@ -283,51 +208,6 @@ static bool MoveToNewNamespaces() { |
_exit(0); |
if (pid == 0) { |
- if (syscall(__NR_getpid) == 1) { |
- int fds[2]; |
- char ch = 0; |
- if (pipe(fds)) { |
- perror("Failed to create pipe"); |
- _exit(1); |
- } |
- pid = fork(); |
- if (pid > 0) { |
- // The very first process in the new namespace takes on the |
- // role of the traditional "init" process. It must reap exit |
- // codes of daemon processes until the namespace is completely |
- // empty. |
- // We have to be careful that this "init" process doesn't |
- // provide a new attack surface. So, we also move it into |
- // a separate chroot and we drop all privileges. It does |
- // still need to access "/proc" and "/dev/null", though. So, |
- // we have to provide it with a file handles to these resources. |
- // These file handle are not accessible by any other processes in |
- // the sandbox and thus safe. |
- close(fds[0]); |
- int proc_fd = open("/proc", O_RDONLY | O_DIRECTORY); |
- int null_fd = open("/dev/null", O_RDWR); |
- if (!JailMe()) { |
- FatalError("Could not remove privileges from " |
- "new \"init\" process"); |
- } |
- SystemInitProcess(fds[1], pid, proc_fd, null_fd); |
- } else if (pid != 0) { |
- perror("Failed to fork"); |
- _exit(1); |
- } |
- // Wait for the "init" process to complete initialization. |
- close(fds[1]); |
- errno = 0; |
- while (read(fds[0], &ch, 1) < 0 && errno == EINTR) { |
- } |
- close(fds[0]); |
- if (ch != ' ') { |
- // We'll likely never get here. If the "init" process fails, it's |
- // death typically takes everyone of its children with it. |
- FatalError("Failed to set up new \"init\" process inside sandbox"); |
- } |
- } |
- |
if (kCloneExtraFlags[i] & CLONE_NEWPID) { |
setenv("SBX_PID_NS", "", 1 /* overwrite */); |
} else { |
@@ -353,6 +233,42 @@ static bool MoveToNewNamespaces() { |
return true; |
} |
+static bool DropRoot() { |
+ if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0)) { |
+ perror("prctl(PR_SET_DUMPABLE)"); |
+ return false; |
+ } |
+ |
+ if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) { |
+ perror("Still dumpable after prctl(PR_SET_DUMPABLE)"); |
+ return false; |
+ } |
+ |
+ gid_t rgid, egid, sgid; |
+ if (getresgid(&rgid, &egid, &sgid)) { |
+ perror("getresgid"); |
+ return false; |
+ } |
+ |
+ if (setresgid(rgid, rgid, rgid)) { |
+ perror("setresgid"); |
+ return false; |
+ } |
+ |
+ uid_t ruid, euid, suid; |
+ if (getresuid(&ruid, &euid, &suid)) { |
+ perror("getresuid"); |
+ return false; |
+ } |
+ |
+ if (setresuid(ruid, ruid, ruid)) { |
+ perror("setresuid"); |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
static bool SetupChildEnvironment() { |
unsigned i; |
@@ -447,7 +363,7 @@ int main(int argc, char **argv) { |
if (!MoveToNewNamespaces()) |
return 1; |
- if (SpawnChrootHelper() < 0) |
+ if (!SpawnChrootHelper()) |
return 1; |
if (!DropRoot()) |
return 1; |