summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2014-08-22 18:55:21 +0200
committerDaniel Mack <daniel@zonque.org>2014-09-08 14:12:56 +0200
commita610cc4f18c24a007e5a2cac21b2ecbd81e5f3c3 (patch)
tree7e1dd169235a078a63a367fadbf2f54aa31ac6ca
parent501996231293506a85bf4d610938a655ddc8cb92 (diff)
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.
-rw-r--r--src/core/execute.c1
-rw-r--r--src/core/namespace.c91
-rw-r--r--src/core/namespace.h1
-rw-r--r--src/test/test-ns.c1
4 files changed, 93 insertions, 1 deletions
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,