193 lines
6.3 KiB
Diff
193 lines
6.3 KiB
Diff
|
From a610cc4f18c24a007e5a2cac21b2ecbd81e5f3c3 Mon Sep 17 00:00:00 2001
|
||
|
From: Daniel Mack <zonque@gmail.com>
|
||
|
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 a88e1b1953..96cabe6d99 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 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)
|
||
|
diff --git a/src/core/namespace.h b/src/core/namespace.h
|
||
|
index 9343fe3264..9cd420e958 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 acad725899..7714e49ad9 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,
|