summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-10 18:17:32 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-10 18:17:32 +0000
commit0e161112cc06b7d77d8c9b73b334b209d79e12d1 (patch)
tree9db1d84127c29b65e2ffc0c20d856bb8d343aeaa
parent1e00c3c588f2721eda5702df1468f92f3ae4c210 (diff)
downloadchromium_src-0e161112cc06b7d77d8c9b73b334b209d79e12d1.zip
chromium_src-0e161112cc06b7d77d8c9b73b334b209d79e12d1.tar.gz
chromium_src-0e161112cc06b7d77d8c9b73b334b209d79e12d1.tar.bz2
Linux: use a temp directory for the chroot.
Ubuntu systems (at least) wipe /var/run at boot time, which is deleting our sandbox directory. Instead, we have the SUID helper create a temp directory in /tmp, unlink it and use that for the chroot directory. A file descriptor is passed to the zygote process for it to fchdir into. (Thanks to fta for discussions on this.) BUG=16363 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20388 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/zygote_host_linux.cc11
-rw-r--r--chrome/browser/zygote_main_linux.cc31
-rw-r--r--sandbox/linux/suid/sandbox.cc47
3 files changed, 69 insertions, 20 deletions
diff --git a/chrome/browser/zygote_host_linux.cc b/chrome/browser/zygote_host_linux.cc
index bfb9d7b..bc6eba1 100644
--- a/chrome/browser/zygote_host_linux.cc
+++ b/chrome/browser/zygote_host_linux.cc
@@ -47,24 +47,17 @@ ZygoteHost::ZygoteHost() {
cmd_line.PrependWrapper(prefix);
}
- const std::string kSandboxPath =
- WideToASCII(std::wstring(L"/var/run/") +
- chrome::kBrowserProcessExecutableName +
- L"-sandbox");
-
struct stat st;
if (stat(kSandboxBinary, &st) == 0) {
if (access(kSandboxBinary, X_OK) == 0 &&
(st.st_mode & S_ISUID) &&
- (st.st_mode & S_IXOTH) &&
- access(kSandboxPath.c_str(), F_OK) == 0) {
+ (st.st_mode & S_IXOTH)) {
cmd_line.PrependWrapper(ASCIIToWide(kSandboxBinary));
} else {
LOG(FATAL) << "The SUID sandbox helper binary was found, but is not "
"configured correctly. Rather than run without sandboxing "
"I'm aborting now. You need to make sure that "
- << kSandboxBinary << " is mode 4755 and that "
- << kSandboxPath << " exists";
+ << kSandboxBinary << " is mode 4755.";
}
}
diff --git a/chrome/browser/zygote_main_linux.cc b/chrome/browser/zygote_main_linux.cc
index c6854e9..9b8ef98 100644
--- a/chrome/browser/zygote_main_linux.cc
+++ b/chrome/browser/zygote_main_linux.cc
@@ -215,16 +215,35 @@ static bool MaybeEnterChroot() {
static const char kChrootMe = 'C';
static const char kChrootMeSuccess = 'O';
- if (HANDLE_EINTR(write(fd, &kChrootMe, 1)) != 1)
+ if (HANDLE_EINTR(write(fd, &kChrootMe, 1)) != 1) {
+ LOG(ERROR) << "Failed to write to chroot pipe: " << errno;
return false;
+ }
char reply;
- if (HANDLE_EINTR(read(fd, &reply, 1)) != 1)
+ std::vector<int> fds;
+ if (!base::RecvMsg(fd, &reply, 1, &fds)) {
+ LOG(ERROR) << "Failed to read from chroot pipe: " << errno;
+ return false;
+ }
+ if (reply != kChrootMeSuccess) {
+ LOG(ERROR) << "Error code reply from chroot helper";
+ for (size_t i = 0; i < fds.size(); ++i)
+ HANDLE_EINTR(close(fds[i]));
return false;
- if (reply != kChrootMeSuccess)
+ }
+ if (fds.size() != 1) {
+ LOG(ERROR) << "Bad number of file descriptors from chroot helper";
+ for (size_t i = 0; i < fds.size(); ++i)
+ HANDLE_EINTR(close(fds[i]));
return false;
- if (chdir("/") == -1)
+ }
+ if (fchdir(fds[0]) == -1) {
+ LOG(ERROR) << "Failed to chdir to root directory: " << errno;
+ HANDLE_EINTR(close(fds[0]));
return false;
+ }
+ HANDLE_EINTR(close(fds[0]));
static const int kMagicSandboxIPCDescriptor = 5;
SkiaFontConfigUseIPCImplementation(kMagicSandboxIPCDescriptor);
@@ -243,8 +262,10 @@ static bool MaybeEnterChroot() {
// exists at this point and we can set the non-dumpable flag which is
// inherited by all our renderer children.
prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
- if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
+ if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
+ LOG(ERROR) << "Failed to set non-dumpable flag";
return false;
+ }
} else {
SkiaFontConfigUseDirectImplementation();
}
diff --git a/sandbox/linux/suid/sandbox.cc b/sandbox/linux/suid/sandbox.cc
index 1ea2af3..abd066c 100644
--- a/sandbox/linux/suid/sandbox.cc
+++ b/sandbox/linux/suid/sandbox.cc
@@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox
+
#include <asm/unistd.h>
#include <errno.h>
+#include <fcntl.h>
#include <sched.h>
#include <signal.h>
#include <stdarg.h>
@@ -22,7 +25,6 @@
#define CLONE_NEWPID 0x20000000
#endif
-static const char kSandboxPath[] = "/var/run/chrome-sandbox";
static const char kChromeBinary[] = "/opt/google/chrome/chrome";
static const char kSandboxDescriptorEnvironmentVarName[] = "SBX_D";
@@ -62,6 +64,23 @@ static int CloneChrootHelperProcess() {
}
if (pid == 0) {
+ // We create a temp directory for our chroot. Nobody should ever write into
+ // it, so it's root:root 0555.
+ char kTempDirectoryTemplate[] = "/tmp/chrome-sandbox-chroot-XXXXXX";
+ const char* temp_dir = mkdtemp(kTempDirectoryTemplate);
+ if (!temp_dir)
+ FatalError("Failed to create temp directory for chroot");
+
+ const int chroot_dir_fd = open(temp_dir, O_DIRECTORY | O_RDONLY);
+ if (chroot_dir_fd < 0) {
+ rmdir(temp_dir);
+ FatalError("Failed to open chroot temp directory");
+ }
+
+ rmdir(temp_dir);
+ fchown(chroot_dir_fd, 0, 0);
+ fchmod(chroot_dir_fd, 0555);
+
// We share our files structure with an untrusted process. As a security in
// depth measure, we make sure that we can't open anything by mistake.
// TODO: drop CAP_SYS_RESOURCE
@@ -87,25 +106,41 @@ static int CloneChrootHelperProcess() {
if (msg != kMsgChrootMe)
FatalError("Unknown message from sandboxed process");
- if (chdir(kSandboxPath))
- FatalError("Cannot chdir into %s", kSandboxPath);
+ if (fchdir(chroot_dir_fd))
+ FatalError("Cannot chdir into chroot temp directory");
struct stat st;
if (stat(".", &st))
FatalError("stat");
if (st.st_uid || st.st_gid || st.st_mode & S_IWOTH)
- FatalError("Bad permissions on chroot directory (%s)", kSandboxPath);
+ FatalError("Bad permissions on chroot temp directory");
if (chroot("."))
- FatalError("Cannot chroot into %s", kSandboxPath);
+ FatalError("Cannot chroot into temp directory");
if (chdir("/"))
FatalError("Cannot chdir to / after chroot");
const char reply = kMsgChrootSuccessful;
do {
- bytes = write(sv[0], &reply, 1);
+ struct msghdr msg = {0};
+ struct iovec iov = {(char *) &reply, 1};
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ char control_buffer[CMSG_SPACE(sizeof(int))];
+ msg.msg_control = control_buffer;
+ msg.msg_controllen = sizeof(control_buffer);
+ struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ memcpy(CMSG_DATA(cmsg), &chroot_dir_fd, sizeof(int));
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ bytes = sendmsg(sv[0], &msg, 0);
} while (bytes == -1 && errno == EINTR);
if (bytes != 1)