chiark / gitweb /
bus: return ECHILD as soon as people try to reuse a bus connection across a fork()
[elogind.git] / src / libsystemd-bus / bus-control.c
index 7c139cfd32cab7cb579e837056d58204ce7a9466..177bd882ada36c569bfc68d31f65459bc775c61e 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+#include <valgrind/memcheck.h>
+#endif
+
 #include <stddef.h>
 #include <errno.h>
 
@@ -36,6 +40,8 @@ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
                 return -EINVAL;
         if (!unique)
                 return -EINVAL;
+        if (bus_pid_changed(bus))
+                return -ECHILD;
 
         r = bus_ensure_running(bus);
         if (r < 0)
@@ -56,23 +62,30 @@ int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
                 return -EINVAL;
         if (!bus->bus_client)
                 return -EINVAL;
+        if (!BUS_IS_OPEN(bus->state))
+                return -ENOTCONN;
+        if (bus_pid_changed(bus))
+                return -ECHILD;
 
         if (bus->is_kernel) {
                 struct kdbus_cmd_name *n;
                 size_t l;
 
                 l = strlen(name);
-                n = alloca(offsetof(struct kdbus_cmd_name, name) + l + 1);
+                n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
-                n->flags = flags;
-                n->id = 0;
+                n->name_flags = flags;
                 memcpy(n->name, name, l+1);
 
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+                VALGRIND_MAKE_MEM_DEFINED(n, n->size);
+#endif
+
                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
                 if (r < 0)
                         return -errno;
 
-                return n->flags;
+                return n->name_flags;
         } else {
                 r = sd_bus_call_method(
                                 bus,
@@ -107,23 +120,28 @@ int sd_bus_release_name(sd_bus *bus, const char *name) {
                 return -EINVAL;
         if (!bus->bus_client)
                 return -EINVAL;
+        if (!BUS_IS_OPEN(bus->state))
+                return -ENOTCONN;
+        if (bus_pid_changed(bus))
+                return -ECHILD;
 
         if (bus->is_kernel) {
                 struct kdbus_cmd_name *n;
                 size_t l;
 
                 l = strlen(name);
-                n = alloca(offsetof(struct kdbus_cmd_name, name) + l + 1);
+                n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
-                n->flags = 0;
-                n->id = 0;
                 memcpy(n->name, name, l+1);
 
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+                VALGRIND_MAKE_MEM_DEFINED(n, n->size);
+#endif
                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
                 if (r < 0)
                         return -errno;
 
-                return n->flags;
+                return n->name_flags;
         } else {
                 r = sd_bus_call_method(
                                 bus,
@@ -155,6 +173,10 @@ int sd_bus_list_names(sd_bus *bus, char ***l) {
                 return -EINVAL;
         if (!l)
                 return -EINVAL;
+        if (!BUS_IS_OPEN(bus->state))
+                return -ENOTCONN;
+        if (bus_pid_changed(bus))
+                return -ECHILD;
 
         r = sd_bus_call_method(
                         bus,
@@ -205,6 +227,10 @@ int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner) {
                 return -EINVAL;
         if (!name)
                 return -EINVAL;
+        if (!BUS_IS_OPEN(bus->state))
+                return -ENOTCONN;
+        if (bus_pid_changed(bus))
+                return -ECHILD;
 
         r = sd_bus_call_method(
                         bus,
@@ -247,6 +273,10 @@ int sd_bus_get_owner_uid(sd_bus *bus, const char *name, uid_t *uid) {
                 return -EINVAL;
         if (!uid)
                 return -EINVAL;
+        if (!BUS_IS_OPEN(bus->state))
+                return -ENOTCONN;
+        if (bus_pid_changed(bus))
+                return -ECHILD;
 
         r = sd_bus_call_method(
                         bus,
@@ -280,6 +310,10 @@ int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) {
                 return -EINVAL;
         if (!pid)
                 return -EINVAL;
+        if (!BUS_IS_OPEN(bus->state))
+                return -ENOTCONN;
+        if (bus_pid_changed(bus))
+                return -ECHILD;
 
         r = sd_bus_call_method(
                         bus,
@@ -336,3 +370,39 @@ int bus_remove_match_internal(sd_bus *bus, const char *match) {
                         "s",
                         match);
 }
+
+int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        const char *mid;
+        int r;
+
+        if (!bus)
+                return -EINVAL;
+        if (!name)
+                return -EINVAL;
+        if (!BUS_IS_OPEN(bus->state))
+                return -ENOTCONN;
+        if (bus_pid_changed(bus))
+                return -ECHILD;
+
+        if (streq_ptr(name, bus->unique_name))
+                return sd_id128_get_machine(machine);
+
+        r = sd_bus_call_method(bus,
+                               name,
+                               "/",
+                               "org.freedesktop.DBus.Peer",
+                               "GetMachineId",
+                               NULL,
+                               &reply,
+                               NULL);
+
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_read(reply, "s", &mid);
+        if (r < 0)
+                return r;
+
+        return sd_id128_from_string(mid, machine);
+}