sd-bus: teach x-container-unix: bus protoocol to connect to the namespace of a PID...
authorLennart Poettering <lennart@poettering.net>
Tue, 23 Dec 2014 18:11:48 +0000 (19:11 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 23 Dec 2014 18:15:27 +0000 (19:15 +0100)
src/libsystemd/sd-bus/bus-container.c
src/libsystemd/sd-bus/bus-internal.h
src/libsystemd/sd-bus/sd-bus.c

index dd4bf15..d29b98a 100644 (file)
 
 int bus_container_connect_socket(sd_bus *b) {
         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
-        pid_t leader, child;
+        pid_t child;
         siginfo_t si;
         int r;
 
         assert(b);
         assert(b->input_fd < 0);
         assert(b->output_fd < 0);
+        assert(b->nspid > 0 || b->machine);
 
-        r = container_get_leader(b->machine, &leader);
-        if (r < 0)
-                return r;
+        if (b->nspid <= 0) {
+                r = container_get_leader(b->machine, &b->nspid);
+                if (r < 0)
+                        return r;
+        }
 
-        r = namespace_open(leader, &pidnsfd, &mntnsfd, NULL, &rootfd);
+        r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &rootfd);
         if (r < 0)
                 return r;
 
@@ -127,7 +130,7 @@ int bus_container_connect_kernel(sd_bus *b) {
                 .msg_controllen = sizeof(control),
         };
         struct cmsghdr *cmsg;
-        pid_t leader, child;
+        pid_t child;
         siginfo_t si;
         int r;
         _cleanup_close_ int fd = -1;
@@ -135,12 +138,15 @@ int bus_container_connect_kernel(sd_bus *b) {
         assert(b);
         assert(b->input_fd < 0);
         assert(b->output_fd < 0);
+        assert(b->nspid > 0 || b->machine);
 
-        r = container_get_leader(b->machine, &leader);
-        if (r < 0)
-                return r;
+        if (b->nspid <= 0) {
+                r = container_get_leader(b->machine, &b->nspid);
+                if (r < 0)
+                        return r;
+        }
 
-        r = namespace_open(leader, &pidnsfd, &mntnsfd, NULL, &rootfd);
+        r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &rootfd);
         if (r < 0)
                 return r;
 
index cb529d5..48c20c9 100644 (file)
@@ -245,6 +245,7 @@ struct sd_bus {
 
         char *kernel;
         char *machine;
+        pid_t nspid;
 
         sd_id128_t server_id;
 
index fd59bac..69ee239 100644 (file)
@@ -756,7 +756,7 @@ static int parse_kernel_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;
+        _cleanup_free_ char *machine = NULL, *pid = NULL;
         int r;
 
         assert(b);
@@ -777,18 +777,36 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid)
                 else if (r > 0)
                         continue;
 
+                r = parse_address_key(p, "pid", &pid);
+                if (r < 0)
+                        return r;
+                else if (r > 0)
+                        continue;
+
                 skip_address_key(p);
         }
 
-        if (!machine)
+        if (!machine == !pid)
                 return -EINVAL;
 
-        if (!machine_name_is_valid(machine))
-                return -EINVAL;
+        if (machine) {
+                if (!machine_name_is_valid(machine))
+                        return -EINVAL;
 
-        free(b->machine);
-        b->machine = machine;
-        machine = NULL;
+                free(b->machine);
+                b->machine = machine;
+                machine = NULL;
+        } else {
+                free(b->machine);
+                b->machine = NULL;
+        }
+
+        if (pid) {
+                r = parse_pid(pid, &b->nspid);
+                if (r < 0)
+                        return r;
+        } else
+                b->nspid = 0;
 
         b->sockaddr.un.sun_family = AF_UNIX;
         strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
@@ -798,7 +816,7 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid)
 }
 
 static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid) {
-        _cleanup_free_ char *machine = NULL;
+        _cleanup_free_ char *machine = NULL, *pid = NULL;
         int r;
 
         assert(b);
@@ -819,18 +837,36 @@ static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid
                 else if (r > 0)
                         continue;
 
+                r = parse_address_key(p, "pid", &pid);
+                if (r < 0)
+                        return r;
+                else if (r > 0)
+                        continue;
+
                 skip_address_key(p);
         }
 
-        if (!machine)
+        if (!machine == !pid)
                 return -EINVAL;
 
-        if (!machine_name_is_valid(machine))
-                return -EINVAL;
+        if (machine) {
+                if (!machine_name_is_valid(machine))
+                        return -EINVAL;
 
-        free(b->machine);
-        b->machine = machine;
-        machine = NULL;
+                free(b->machine);
+                b->machine = machine;
+                machine = NULL;
+        } else {
+                free(b->machine);
+                b->machine = NULL;
+        }
+
+        if (pid) {
+                r = parse_pid(pid, &b->nspid);
+                if (r < 0)
+                        return r;
+        } else
+                b->nspid = 0;
 
         free(b->kernel);
         b->kernel = strdup("/sys/fs/kdbus/0-system/bus");
@@ -854,6 +890,7 @@ static void bus_reset_parsed_address(sd_bus *b) {
         b->kernel = NULL;
         free(b->machine);
         b->machine = NULL;
+        b->nspid = 0;
 }
 
 static int bus_parse_next_address(sd_bus *b) {
@@ -958,9 +995,9 @@ static int bus_start_address(sd_bus *b) {
 
                 if (b->exec_path)
                         r = bus_socket_exec(b);
-                else if (b->machine && b->kernel)
+                else if ((b->nspid > 0 || b->machine) && b->kernel)
                         r = bus_container_connect_kernel(b);
-                else if (b->machine && b->sockaddr.sa.sa_family != AF_UNSPEC)
+                else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC)
                         r = bus_container_connect_socket(b);
                 else if (b->kernel)
                         r = bus_kernel_connect(b);