From a610cc4f18c24a007e5a2cac21b2ecbd81e5f3c3 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 22 Aug 2014 18:55:21 +0200 Subject: [PATCH] namespace: add support for custom kdbus endpoint If a path to a previously created custom kdbus endpoint is passed in, bind-mount a new devtmpfs that contains a 'bus' node, which in turn in bind-mounted with the custom endpoint. This tmpfs then mounted over the kdbus subtree that refers to the current bus. This way, we can fake the bus node in order to lock down services with a kdbus custom endpoint policy. --- src/core/execute.c | 1 + src/core/namespace.c | 91 +++++++++++++++++++++++++++++++++++++++++++- src/core/namespace.h | 1 + src/test/test-ns.c | 1 + 4 files changed, 93 insertions(+), 1 deletion(-) diff --git a/src/core/execute.c b/src/core/execute.c index a88e1b195..96cabe6d9 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1523,6 +1523,7 @@ static int exec_child(ExecCommand *command, context->inaccessible_dirs, tmp, var, + NULL, context->private_devices, context->protect_home, context->protect_system, diff --git a/src/core/namespace.c b/src/core/namespace.c index fe9537787..eaaebdd64 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -51,6 +51,7 @@ typedef enum MountMode { PRIVATE_TMP, PRIVATE_VAR_TMP, PRIVATE_DEV, + PRIVATE_BUS_ENDPOINT, READWRITE } MountMode; @@ -272,6 +273,84 @@ fail: return r; } +static int mount_kdbus(BindMount *m) { + + char temporary_mount[] = "/tmp/kdbus-dev-XXXXXX"; + _cleanup_free_ char *basepath = NULL; + _cleanup_umask_ mode_t u; + char *busnode, *root; + struct stat st; + int r; + + assert(m); + + u = umask(0000); + + if (!mkdtemp(temporary_mount)) { + log_error("Failed create temp dir: %m"); + return -errno; + } + + root = strappenda(temporary_mount, "/kdbus"); + mkdir(root, 0755); + if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_STRICTATIME, "mode=777") < 0) { + r = -errno; + goto fail; + } + + /* create a new /dev/null dev node copy so we have some fodder to + * bind-mount the custom endpoint over. */ + if (stat("/dev/null", &st) < 0) { + log_error("Failed to stat /dev/null: %m"); + r = -errno; + goto fail; + } + + busnode = strappenda(root, "/bus"); + if (mknod(busnode, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0) { + log_error("mknod() for %s failed: %m", busnode); + r = -errno; + goto fail; + } + + r = mount(m->path, busnode, "bind", MS_BIND, NULL); + if (r < 0) { + log_error("bind mount of %s failed: %m", m->path); + r = -errno; + goto fail; + } + + basepath = dirname_malloc(m->path); + if (!basepath) { + r = -ENOMEM; + goto fail; + } + + if (mount(root, basepath, NULL, MS_MOVE, NULL) < 0) { + log_error("bind mount of %s failed: %m", basepath); + r = -errno; + goto fail; + } + + rmdir(temporary_mount); + return 0; + +fail: + if (busnode) { + umount(busnode); + unlink(busnode); + } + + if (root) { + umount(root); + rmdir(root); + } + + rmdir(temporary_mount); + + return r; +} + static int apply_mount( BindMount *m, const char *tmp_dir, @@ -311,6 +390,9 @@ static int apply_mount( case PRIVATE_DEV: return mount_dev(m); + case PRIVATE_BUS_ENDPOINT: + return mount_kdbus(m); + default: assert_not_reached("Unknown mode"); } @@ -350,6 +432,7 @@ int setup_namespace( char** inaccessible_dirs, char* tmp_dir, char* var_tmp_dir, + char* bus_endpoint_path, bool private_dev, ProtectHome protect_home, ProtectSystem protect_system, @@ -365,7 +448,7 @@ int setup_namespace( if (unshare(CLONE_NEWNS) < 0) return -errno; - n = !!tmp_dir + !!var_tmp_dir + + n = !!tmp_dir + !!var_tmp_dir + !!bus_endpoint_path + strv_length(read_write_dirs) + strv_length(read_only_dirs) + strv_length(inaccessible_dirs) + @@ -406,6 +489,12 @@ int setup_namespace( m++; } + if (bus_endpoint_path) { + m->path = bus_endpoint_path; + m->mode = PRIVATE_BUS_ENDPOINT; + m++; + } + if (protect_home != PROTECT_HOME_NO) { r = append_mounts(&m, STRV_MAKE("-/home", "-/run/user", "-/root"), protect_home == PROTECT_HOME_READ_ONLY ? READONLY : INACCESSIBLE); if (r < 0) diff --git a/src/core/namespace.h b/src/core/namespace.h index 9343fe326..9cd420e95 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -46,6 +46,7 @@ int setup_namespace(char **read_write_dirs, char **inaccessible_dirs, char *tmp_dir, char *var_tmp_dir, + char *endpoint_path, bool private_dev, ProtectHome protect_home, ProtectSystem protect_system, diff --git a/src/test/test-ns.c b/src/test/test-ns.c index acad72589..7714e49ad 100644 --- a/src/test/test-ns.c +++ b/src/test/test-ns.c @@ -59,6 +59,7 @@ int main(int argc, char *argv[]) { (char **) inaccessible, tmp_dir, var_tmp_dir, + NULL, true, PROTECT_HOME_NO, PROTECT_SYSTEM_NO, -- 2.30.2