]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
namespace: add support for custom kdbus endpoint
authorDaniel Mack <zonque@gmail.com>
Fri, 22 Aug 2014 16:55:21 +0000 (18:55 +0200)
committerDaniel Mack <daniel@zonque.org>
Mon, 8 Sep 2014 12:12:56 +0000 (14:12 +0200)
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
src/core/namespace.c
src/core/namespace.h
src/test/test-ns.c

index a88e1b19533cce2435e98253a6b557218e1ae37d..96cabe6d99c7bb8d5bf95910c18962550cb4fbcf 100644 (file)
@@ -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,
index fe9537787185c6755f9778593ae5aa393d760e7a..eaaebdd64403734c02be7a55974a50827b8a79bf 100644 (file)
@@ -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)
index 9343fe326420ee19e84fb2d5872551d03fddf5a8..9cd420e9589c074962c2a1d1d887fc4b1d35d1bd 100644 (file)
@@ -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,
index acad725899aa5686b5d842c83f4e6c293886bc7b..7714e49ad9f04b9450f13cb85198e94c163ce81a 100644 (file)
@@ -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,