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