summaryrefslogtreecommitdiff
path: root/src/libsystemd-bus/sd-bus.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-12-13 22:02:47 +0100
committerLennart Poettering <lennart@poettering.net>2013-12-14 05:10:25 +0100
commitbc9fd78c7bfc39881e19457e476393635f8b0442 (patch)
tree3c4dc6461460a2b4094516eb35424d36f52f455a /src/libsystemd-bus/sd-bus.c
parent3fa5dd6de798e17d93531bc900b8e2dc587c38f3 (diff)
bus: when connecting to a container's kdbus instance, enter namespace first
Previously we'd open the connection in the originating namespace, which meant most peers of the bus would not be able to make sense of the PID/UID/... identity of us since we didn't exist in the namespace they run in. However they require this identity for privilege decisions, hence disallowing access to anything from the host. Instead, when connecting to a container, create a temporary subprocess, make it join the container's namespace and then connect from there to the kdbus instance. This is similar to how we do it for socket conections already. THis also unifies the namespacing code used by machinectl and the bus APIs.
Diffstat (limited to 'src/libsystemd-bus/sd-bus.c')
-rw-r--r--src/libsystemd-bus/sd-bus.c69
1 files changed, 61 insertions, 8 deletions
diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c
index 932bf226c5..4eaceeff04 100644
--- a/src/libsystemd-bus/sd-bus.c
+++ b/src/libsystemd-bus/sd-bus.c
@@ -740,7 +740,7 @@ static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
return 0;
}
-static int parse_container_address(sd_bus *b, const char **p, char **guid) {
+static int parse_container_unix_address(sd_bus *b, const char **p, char **guid) {
_cleanup_free_ char *machine = NULL;
int r;
@@ -782,6 +782,49 @@ static int parse_container_address(sd_bus *b, const char **p, char **guid) {
return 0;
}
+static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid) {
+ _cleanup_free_ char *machine = NULL;
+ int r;
+
+ assert(b);
+ assert(p);
+ assert(*p);
+ assert(guid);
+
+ while (**p != 0 && **p != ';') {
+ r = parse_address_key(p, "guid", guid);
+ if (r < 0)
+ return r;
+ else if (r > 0)
+ continue;
+
+ r = parse_address_key(p, "machine", &machine);
+ if (r < 0)
+ return r;
+ else if (r > 0)
+ continue;
+
+ skip_address_key(p);
+ }
+
+ if (!machine)
+ return -EINVAL;
+
+ if (!filename_is_safe(machine))
+ return -EINVAL;
+
+ free(b->machine);
+ b->machine = machine;
+ machine = NULL;
+
+ free(b->kernel);
+ b->kernel = strdup("/dev/kdbus/0-system/bus");
+ if (!b->kernel)
+ return -ENOMEM;
+
+ return 0;
+}
+
static void bus_reset_parsed_address(sd_bus *b) {
assert(b);
@@ -855,10 +898,18 @@ static int bus_parse_next_address(sd_bus *b) {
return r;
break;
- } else if (startswith(a, "x-container:")) {
+ } else if (startswith(a, "x-container-unix:")) {
+
+ a += 17;
+ r = parse_container_unix_address(b, &a, &guid);
+ if (r < 0)
+ return r;
+
+ break;
+ } else if (startswith(a, "x-container-kernel:")) {
- a += 12;
- r = parse_container_address(b, &a, &guid);
+ a += 19;
+ r = parse_container_kernel_address(b, &a, &guid);
if (r < 0)
return r;
@@ -892,10 +943,12 @@ static int bus_start_address(sd_bus *b) {
if (b->exec_path)
r = bus_socket_exec(b);
+ else if (b->machine && b->kernel)
+ r = bus_container_connect_kernel(b);
+ else if (b->machine && b->sockaddr.sa.sa_family != AF_UNSPEC)
+ r = bus_container_connect_socket(b);
else if (b->kernel)
r = bus_kernel_connect(b);
- else if (b->machine)
- r = bus_container_connect(b);
else if (b->sockaddr.sa.sa_family != AF_UNSPEC)
r = bus_socket_connect(b);
else
@@ -1144,9 +1197,9 @@ _public_ int sd_bus_open_system_container(const char *machine, sd_bus **ret) {
return -ENOMEM;
#ifdef ENABLE_KDBUS
- p = strjoin("kernel:path=/dev/kdbus/ns/machine-", e, "/0-system/bus;x-container:machine=", e, NULL);
+ p = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL);
#else
- p = strjoin("x-container:machine=", e, NULL);
+ p = strjoin("x-container-unix:machine=", e, NULL);
#endif
if (!p)
return -ENOMEM;