aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/tools
diff options
context:
space:
mode:
authorGravatar Philipp Wollermann <philwo@google.com>2017-03-24 10:50:21 +0000
committerGravatar Yue Gan <yueg@google.com>2017-03-24 12:20:28 +0000
commit7429648a3bf241becf38711f876201dd5c6c5cb5 (patch)
treef879b2e10115b931360928c836a68a9a3d0e9660 /src/main/tools
parent3e2329a73ffd5d60e5e2babe60ebe5bf322c07da (diff)
sandbox: No longer require a temporary "sandbox" directory.
By removing the --sandbox_block_path feature in an earlier change and taking advantage of the fact that in a mount namespace we can actually "remount" mount points to be read-only without bind mounting them to some other place beforehand, this is no longer necessary. The code becomes much simpler due to this, for example we no longer need to chroot. -- PiperOrigin-RevId: 151111360 MOS_MIGRATED_REVID=151111360
Diffstat (limited to 'src/main/tools')
-rw-r--r--src/main/tools/linux-sandbox-options.cc13
-rw-r--r--src/main/tools/linux-sandbox-options.h2
-rw-r--r--src/main/tools/linux-sandbox-pid1.cc116
-rw-r--r--src/main/tools/linux-sandbox.cc19
4 files changed, 13 insertions, 137 deletions
diff --git a/src/main/tools/linux-sandbox-options.cc b/src/main/tools/linux-sandbox-options.cc
index 3bd9a7e243..96354ec8ec 100644
--- a/src/main/tools/linux-sandbox-options.cc
+++ b/src/main/tools/linux-sandbox-options.cc
@@ -123,23 +123,14 @@ static void ParseCommandLine(unique_ptr<vector<char *>> args) {
int c;
bool source_specified;
- while ((c = getopt(args->size(), args->data(),
- ":CS:W:T:t:l:L:w:e:M:m:HNRD")) != -1) {
+ while ((c = getopt(args->size(), args->data(), ":CW:T:t:l:L:w:e:M:m:HNRD")) !=
+ -1) {
if (c != 'M' && c != 'm') source_specified = false;
switch (c) {
case 'C':
// Shortcut for the "does this system support sandboxing" check.
exit(CheckNamespacesSupported());
break;
- case 'S':
- if (opt.sandbox_root_dir == NULL) {
- ValidateIsAbsolutePath(optarg, args->front(), static_cast<char>(c));
- opt.sandbox_root_dir = strdup(optarg);
- } else {
- Usage(args->front(),
- "Multiple root directories (-S) specified, expected one.");
- }
- break;
case 'W':
if (opt.working_dir == NULL) {
ValidateIsAbsolutePath(optarg, args->front(), static_cast<char>(c));
diff --git a/src/main/tools/linux-sandbox-options.h b/src/main/tools/linux-sandbox-options.h
index 6f57eba3a4..5c78e46d31 100644
--- a/src/main/tools/linux-sandbox-options.h
+++ b/src/main/tools/linux-sandbox-options.h
@@ -22,8 +22,6 @@
// Options parsing result.
struct Options {
- // Temporary root directory (-S)
- const char *sandbox_root_dir;
// Working directory (-W)
const char *working_dir;
// How long to wait before killing the child (-T)
diff --git a/src/main/tools/linux-sandbox-pid1.cc b/src/main/tools/linux-sandbox-pid1.cc
index 0be62d9e5f..76dccbad24 100644
--- a/src/main/tools/linux-sandbox-pid1.cc
+++ b/src/main/tools/linux-sandbox-pid1.cc
@@ -145,102 +145,37 @@ static void SetupUtsNamespace() {
}
}
-// Recursively creates the file or directory specified in "path" and its parent
-// directories.
-static int CreateTarget(const char *path, bool is_directory) {
- PRINT_DEBUG("CreateTarget(%s, %s)", path, is_directory ? "true" : "false");
- if (path == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- struct stat sb;
- // If the path already exists...
- if (stat(path, &sb) == 0) {
- if (is_directory && S_ISDIR(sb.st_mode)) {
- // and it's a directory and supposed to be a directory, we're done here.
- return 0;
- } else if (!is_directory && S_ISREG(sb.st_mode)) {
- // and it's a regular file and supposed to be one, we're done here.
- return 0;
- } else {
- // otherwise something is really wrong.
- errno = is_directory ? ENOTDIR : EEXIST;
- return -1;
- }
- } else {
- // If stat failed because of any error other than "the path does not exist",
- // this is an error.
- if (errno != ENOENT) {
- return -1;
- }
- }
-
- // Create the parent directory.
- if (CreateTarget(dirname(strdupa(path)), true) < 0) {
- DIE("CreateTarget(%s, true)", dirname(strdupa(path)));
- }
-
- if (is_directory) {
- if (mkdir(path, 0755) < 0) {
- DIE("mkdir(%s, 0755)", path);
- }
- } else {
- int handle;
- if ((handle = open(path, O_CREAT | O_WRONLY | O_EXCL, 0666)) < 0) {
- DIE("open(%s, O_CREAT | O_WRONLY | O_EXCL, 0666)", path);
- }
- if (close(handle) < 0) {
- DIE("close(%d)", handle);
- }
- }
-
- return 0;
-}
-
static void MountFilesystems() {
- if (mount("/", opt.sandbox_root_dir, NULL, MS_BIND | MS_REC, NULL) < 0) {
- DIE("mount(/, %s, NULL, MS_BIND | MS_REC, NULL)", opt.sandbox_root_dir);
- }
-
- if (chdir(opt.sandbox_root_dir) < 0) {
- DIE("chdir(%s)", opt.sandbox_root_dir);
- }
-
for (const char *tmpfs_dir : opt.tmpfs_dirs) {
PRINT_DEBUG("tmpfs: %s", tmpfs_dir);
- if (mount("tmpfs", tmpfs_dir + 1, "tmpfs",
- MS_NOSUID | MS_NODEV | MS_NOATIME, NULL) < 0) {
+ if (mount("tmpfs", tmpfs_dir, "tmpfs", MS_NOSUID | MS_NODEV | MS_NOATIME,
+ NULL) < 0) {
DIE("mount(tmpfs, %s, tmpfs, MS_NOSUID | MS_NODEV | MS_NOATIME, NULL)",
- tmpfs_dir + 1);
+ tmpfs_dir);
}
}
// Make sure that our working directory is a mount point. The easiest way to
// do this is by bind-mounting it upon itself.
PRINT_DEBUG("working dir: %s", opt.working_dir);
- PRINT_DEBUG("sandbox root: %s", opt.sandbox_root_dir);
- CreateTarget(opt.working_dir + 1, true);
- if (mount(opt.working_dir, opt.working_dir + 1, NULL, MS_BIND, NULL) < 0) {
- DIE("mount(%s, %s, NULL, MS_BIND, NULL)", opt.working_dir,
- opt.working_dir + 1);
+ if (mount(opt.working_dir, opt.working_dir, NULL, MS_BIND, NULL) < 0) {
+ DIE("mount(%s, %s, NULL, MS_BIND, NULL)", opt.working_dir, opt.working_dir);
}
for (size_t i = 0; i < opt.bind_mount_sources.size(); i++) {
const char *source = opt.bind_mount_sources.at(i);
const char *target = opt.bind_mount_targets.at(i);
PRINT_DEBUG("bind mount: %s -> %s", source, target);
- if (mount(source, target + 1, NULL, MS_BIND, NULL) < 0) {
- DIE("mount(%s, %s, NULL, MS_BIND, NULL)", source, target + 1);
+ if (mount(source, target, NULL, MS_BIND, NULL) < 0) {
+ DIE("mount(%s, %s, NULL, MS_BIND, NULL)", source, target);
}
}
for (const char *writable_file : opt.writable_files) {
PRINT_DEBUG("writable: %s", writable_file);
- if (mount(writable_file, writable_file + 1, NULL, MS_BIND, NULL) < 0) {
- DIE("mount(%s, %s, NULL, MS_BIND, NULL)", writable_file,
- writable_file + 1);
+ if (mount(writable_file, writable_file, NULL, MS_BIND, NULL) < 0) {
+ DIE("mount(%s, %s, NULL, MS_BIND, NULL)", writable_file, writable_file);
}
}
}
@@ -248,8 +183,6 @@ static void MountFilesystems() {
// We later remount everything read-only, except the paths for which this method
// returns true.
static bool ShouldBeWritable(char *mnt_dir) {
- mnt_dir += strlen(opt.sandbox_root_dir);
-
if (strcmp(mnt_dir, opt.working_dir) == 0) {
return true;
}
@@ -288,14 +221,10 @@ static void MakeFilesystemMostlyReadOnly() {
struct mntent *ent;
while ((ent = getmntent(mounts)) != NULL) {
- // Skip mounts that do not belong to our sandbox.
- if (strstr(ent->mnt_dir, opt.sandbox_root_dir) != ent->mnt_dir) {
- continue;
- }
// Skip mounts that are under tmpfs directories because we've already
// replaced such directories with new tmpfs instances.
// mount() would fail with ENOENT if we tried to remount such mount points.
- if (IsUnderTmpDir(ent->mnt_dir + strlen(opt.sandbox_root_dir))) {
+ if (IsUnderTmpDir(ent->mnt_dir)) {
continue;
}
@@ -355,7 +284,7 @@ static void MakeFilesystemMostlyReadOnly() {
static void MountProc() {
// Mount a new proc on top of the old one, because the old one still refers to
// our parent PID namespace.
- if (mount("proc", "proc", "proc", MS_NODEV | MS_NOEXEC | MS_NOSUID, NULL) <
+ if (mount("/proc", "/proc", "proc", MS_NODEV | MS_NOEXEC | MS_NOSUID, NULL) <
0) {
DIE("mount");
}
@@ -393,29 +322,6 @@ static void SetupNetworking() {
}
static void EnterSandbox() {
- // Move the real root to old_root, then detach it.
- char old_root[] = "tmp/old-root-XXXXXX";
- if (mkdtemp(old_root) == NULL) {
- DIE("mkdtemp(%s)", old_root);
- }
-
- // pivot_root has no wrapper in libc, so we need syscall()
- if (syscall(SYS_pivot_root, ".", old_root) < 0) {
- DIE("pivot_root(., %s)", old_root);
- }
-
- if (chroot(".") < 0) {
- DIE("chroot(.)");
- }
-
- if (umount2(old_root, MNT_DETACH) < 0) {
- DIE("umount2(%s, MNT_DETACH)", old_root);
- }
-
- if (rmdir(old_root) < 0) {
- DIE("rmdir(%s)", old_root);
- }
-
if (chdir(opt.working_dir) < 0) {
DIE("chdir(%s)", opt.working_dir);
}
diff --git a/src/main/tools/linux-sandbox.cc b/src/main/tools/linux-sandbox.cc
index 799ece4ebb..0d73174727 100644
--- a/src/main/tools/linux-sandbox.cc
+++ b/src/main/tools/linux-sandbox.cc
@@ -71,7 +71,6 @@
int global_outer_uid;
int global_outer_gid;
-static char global_sandbox_root[] = "/tmp/sandbox.XXXXXX";
static int global_child_pid;
// The signal that will be sent to the child when a timeout occurs.
@@ -117,22 +116,6 @@ static void CloseFds() {
}
}
-static void RemoveSandboxRoot() {
- if (rmdir(global_sandbox_root) < 0) {
- DIE("rmdir(%s)", global_sandbox_root);
- }
-}
-
-static void SetupSandboxRoot() {
- if (opt.sandbox_root_dir == NULL) {
- if (mkdtemp(global_sandbox_root) == NULL) {
- DIE("mkdtemp(%s)", global_sandbox_root);
- }
- atexit(RemoveSandboxRoot);
- opt.sandbox_root_dir = global_sandbox_root;
- }
-}
-
static void HandleSignal(int signum, void (*handler)(int)) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
@@ -283,8 +266,6 @@ int main(int argc, char *argv[]) {
// file handles from our parent.
CloseFds();
- SetupSandboxRoot();
-
HandleSignal(SIGALRM, OnTimeout);
if (opt.timeout_secs > 0) {
alarm(opt.timeout_secs);