diff options
Diffstat (limited to 'src/core/namespace.c')
-rw-r--r-- | src/core/namespace.c | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/src/core/namespace.c b/src/core/namespace.c index fe95377871..eaaebdd644 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) |