aboutgitcodebugslistschat
path: root/isolation.c
diff options
context:
space:
mode:
Diffstat (limited to 'isolation.c')
-rw-r--r--isolation.c75
1 files changed, 41 insertions, 34 deletions
diff --git a/isolation.c b/isolation.c
index ca2c68b..c944fb3 100644
--- a/isolation.c
+++ b/isolation.c
@@ -29,7 +29,8 @@
*
* Executed immediately after startup, drops capabilities we don't
* need at any point during execution (or which we gain back when we
- * need by joining other namespaces).
+ * need by joining other namespaces), and closes any leaked file we
+ * might have inherited from the parent process.
*
* 2. isolate_user()
* =================
@@ -105,7 +106,7 @@ static void drop_caps_ep_except(uint64_t keep)
int i;
if (syscall(SYS_capget, &hdr, data))
- die("Couldn't get current capabilities: %s", strerror(errno));
+ die_perror("Couldn't get current capabilities");
for (i = 0; i < CAP_WORDS; i++) {
uint32_t mask = keep >> (32 * i);
@@ -115,7 +116,7 @@ static void drop_caps_ep_except(uint64_t keep)
}
if (syscall(SYS_capset, &hdr, data))
- die("Couldn't drop capabilities: %s", strerror(errno));
+ die_perror("Couldn't drop capabilities");
}
/**
@@ -152,30 +153,31 @@ static void clamp_caps(void)
*/
if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0) &&
errno != EINVAL && errno != EPERM)
- die("Couldn't drop cap %i from bounding set: %s",
- i, strerror(errno));
+ die_perror("Couldn't drop cap %i from bounding set", i);
}
if (syscall(SYS_capget, &hdr, data))
- die("Couldn't get current capabilities: %s", strerror(errno));
+ die_perror("Couldn't get current capabilities");
for (i = 0; i < CAP_WORDS; i++)
data[i].inheritable = 0;
if (syscall(SYS_capset, &hdr, data))
- die("Couldn't drop inheritable capabilities: %s",
- strerror(errno));
+ die_perror("Couldn't drop inheritable capabilities");
}
/**
- * isolate_initial() - Early, config independent self isolation
+ * isolate_initial() - Early, mostly config independent self isolation
+ * @argc: Argument count
+ * @argv: Command line options: only --fd (if present) is relevant here
*
* Should:
* - drop unneeded capabilities
+ * - close all open files except for standard streams and the one from --fd
* Musn't:
* - remove filesytem access (we need to access files during setup)
*/
-void isolate_initial(void)
+void isolate_initial(int argc, char **argv)
{
uint64_t keep;
@@ -209,6 +211,8 @@ void isolate_initial(void)
keep |= BIT(CAP_SETFCAP) | BIT(CAP_SYS_PTRACE);
drop_caps_ep_except(keep);
+
+ close_open_files(argc, argv);
}
/**
@@ -234,34 +238,30 @@ void isolate_user(uid_t uid, gid_t gid, bool use_userns, const char *userns,
if (setgroups(0, NULL)) {
/* If we don't have CAP_SETGID, this will EPERM */
if (errno != EPERM)
- die("Can't drop supplementary groups: %s",
- strerror(errno));
+ die_perror("Can't drop supplementary groups");
}
if (setgid(gid) != 0)
- die("Can't set GID to %u: %s", gid, strerror(errno));
+ die_perror("Can't set GID to %u", gid);
if (setuid(uid) != 0)
- die("Can't set UID to %u: %s", uid, strerror(errno));
+ die_perror("Can't set UID to %u", uid);
if (*userns) { /* If given a userns, join it */
int ufd;
ufd = open(userns, O_RDONLY | O_CLOEXEC);
if (ufd < 0)
- die("Couldn't open user namespace %s: %s",
- userns, strerror(errno));
+ die_perror("Couldn't open user namespace %s", userns);
if (setns(ufd, CLONE_NEWUSER) != 0)
- die("Couldn't enter user namespace %s: %s",
- userns, strerror(errno));
+ die_perror("Couldn't enter user namespace %s", userns);
close(ufd);
} else if (use_userns) { /* Create and join a new userns */
if (unshare(CLONE_NEWUSER) != 0)
- die("Couldn't create user namespace: %s",
- strerror(errno));
+ die_perror("Couldn't create user namespace");
}
/* Joining a new userns gives us full capabilities; drop the
@@ -316,34 +316,34 @@ int isolate_prefork(const struct ctx *c)
flags |= CLONE_NEWPID;
if (unshare(flags)) {
- perror("unshare");
+ err_perror("Failed to detach isolating namespaces");
return -errno;
}
if (mount("", "/", "", MS_UNBINDABLE | MS_REC, NULL)) {
- perror("mount /");
+ err_perror("Failed to remount /");
return -errno;
}
if (mount("", TMPDIR, "tmpfs",
MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_RDONLY,
"nr_inodes=2,nr_blocks=0")) {
- perror("mount tmpfs");
+ err_perror("Failed to mount empty tmpfs for pivot_root()");
return -errno;
}
if (chdir(TMPDIR)) {
- perror("chdir");
+ err_perror("Failed to change directory into empty tmpfs");
return -errno;
}
if (syscall(SYS_pivot_root, ".", ".")) {
- perror("pivot_root");
+ err_perror("Failed to pivot_root() into empty tmpfs");
return -errno;
}
if (umount2(".", MNT_DETACH | UMOUNT_NOFOLLOW)) {
- perror("umount2");
+ err_perror("Failed to unmount original root filesystem");
return -errno;
}
@@ -379,17 +379,24 @@ void isolate_postfork(const struct ctx *c)
prctl(PR_SET_DUMPABLE, 0);
- if (c->mode == MODE_PASTA) {
- prog.len = (unsigned short)ARRAY_SIZE(filter_pasta);
- prog.filter = filter_pasta;
- } else {
+ switch (c->mode) {
+ case MODE_PASST:
prog.len = (unsigned short)ARRAY_SIZE(filter_passt);
prog.filter = filter_passt;
+ break;
+ case MODE_PASTA:
+ prog.len = (unsigned short)ARRAY_SIZE(filter_pasta);
+ prog.filter = filter_pasta;
+ break;
+ case MODE_VU:
+ prog.len = (unsigned short)ARRAY_SIZE(filter_vu);
+ prog.filter = filter_vu;
+ break;
+ default:
+ ASSERT(0);
}
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
- prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
- perror("prctl");
- exit(EXIT_FAILURE);
- }
+ prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog))
+ die_perror("Failed to apply seccomp filter");
}