chiark / gitweb /
libsystemd-bus: catch up with latest kdbus changes
authorDaniel Mack <zonque@gmail.com>
Sat, 30 Nov 2013 12:31:04 +0000 (13:31 +0100)
committerDaniel Mack <zonque@gmail.com>
Sat, 30 Nov 2013 12:31:04 +0000 (13:31 +0100)
The name list and query functions now work differently in kdbus, as the
result is stored in the connection's pool, rather than being copied back
through the ioctl buffer. That also safes us some logic, as we don't
have to resize the communication buffer in a loop with growing buffer
sizes.

Due to this, KDBUS_CMD_MSG_RELEASE was renamed to KDBUS_CMD_FREE, as it
is now used outside the message logic as well.

src/libsystemd-bus/bus-control.c
src/libsystemd-bus/bus-kernel.c
src/libsystemd-bus/bus-message.c
src/libsystemd-bus/kdbus.h
src/libsystemd-bus/sd-bus.c

index a0eeb305da7d6d57c5f32ccbc73f1367f6014f1b..1d1f6d0f394c8b3330e0f4863f52b47bd9570d71 100644 (file)
@@ -174,36 +174,23 @@ _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
         if (bus->is_kernel) {
-                _cleanup_free_ struct kdbus_cmd_names *names = NULL;
+                _cleanup_free_ struct kdbus_cmd_name_list *cmd = NULL;
+                struct kdbus_name_list *name_list;
                 struct kdbus_cmd_name *name;
-                size_t size;
 
-                /* assume 8k size first. If that doesn't suffice, kdbus will tell us
-                 * how big the buffer needs to be.  */
-                size = 8192;
-
-                for(;;) {
-                        names = realloc(names, size);
-                        if (!names)
-                                return -ENOMEM;
-
-                        names->size = size;
-                        names->flags = KDBUS_NAME_LIST_UNIQUE_NAMES;
+                cmd = malloc0(sizeof(struct kdbus_cmd_name_list *));
+                if (!cmd)
+                        return -ENOMEM;
 
-                        r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, names);
-                        if (r < 0) {
-                                if (errno == ENOBUFS && size != names->size) {
-                                        size = names->size;
-                                        continue;
-                                }
+                cmd->flags = KDBUS_NAME_LIST_UNIQUE_NAMES;
 
-                                return -errno;
-                        }
+                r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, cmd);
+                if (r < 0)
+                        return -errno;
 
-                        break;
-                }
+                name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
 
-                KDBUS_PART_FOREACH(name, names, names) {
+                KDBUS_PART_FOREACH(name, name_list, names) {
                         char *n;
 
                         if (name->size > sizeof(*name))
@@ -216,6 +203,10 @@ _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
                                 return -ENOMEM;
                 }
 
+                r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset);
+                if (r < 0)
+                        return -errno;
+
                 *l = x;
         } else {
                 r = sd_bus_call_method(
@@ -587,7 +578,7 @@ static int add_name_change_match(sd_bus *bus,
         return 0;
 }
 
-static int kdbus_name_query(
+static int kdbus_name_info(
                 sd_bus *bus,
                 const char *name,
                 uint64_t mask,
@@ -596,52 +587,32 @@ static int kdbus_name_query(
 
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+        _cleanup_free_ struct kdbus_cmd_name_info *cmd = NULL;
         _cleanup_free_ char *unique = NULL;
-        struct kdbus_cmd_name_info *name_info = NULL;
+        struct kdbus_name_info *name_info;
         struct kdbus_item *item;
         uint64_t attach_flags, m;
-        size_t slen, size;
+        size_t size;
         int r;
 
         r = kdbus_translate_attach_flags(mask, &attach_flags);
         if (r < 0)
                 return r;
 
-        slen = strlen(name) + 1;
-
-        /*
-         * The structure is used for both directions. Start with 8k buffer size and
-         * expand to the size kdbus reports in case we fail.
-         */
-        size = slen + 8192;
-
-        for(;;) {
-                name_info = realloc(name_info, size);
-                if (!name_info)
-                        return -ENOMEM;
-
-                memset(name_info, 0, size);
-
-                name_info->size = size;
-                name_info->attach_flags = attach_flags;
-
-                item = name_info->items;
-                item->type = KDBUS_NAME_INFO_ITEM_NAME;
-                item->size = KDBUS_ITEM_SIZE(slen);
-                strcpy(item->str, name);
+        size = sizeof(struct kdbus_cmd_name_info) + strlen(name) + 1;
+        cmd = malloc0(size);
+        if (!cmd)
+                return -ENOMEM;
 
-                r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_QUERY, name_info);
-                if (r < 0) {
-                        if (errno == ENOBUFS && size != name_info->size) {
-                                size = name_info->size;
-                                continue;
-                        }
+        cmd ->size = size;
+        cmd->attach_flags = attach_flags;
+        strcpy(cmd->name, name);
 
-                        return -errno;
-                }
+        r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_INFO, cmd);
+        if (r < 0)
+                return -errno;
 
-                break;
-        }
+        name_info = (struct kdbus_name_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
 
         asprintf(&unique, ":1.%llu", (unsigned long long) name_info->id);
 
@@ -756,6 +727,10 @@ static int kdbus_name_query(
                 }
         }
 
+        r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset);
+        if (r < 0)
+                return -errno;
+
         if (creds) {
                 *creds = c;
                 c = NULL;
@@ -784,7 +759,7 @@ _public_ int sd_bus_get_owner(
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
         if (bus->is_kernel)
-                return kdbus_name_query(bus, name, mask, owner, creds);
+                return kdbus_name_info(bus, name, mask, owner, creds);
 
         return sd_bus_get_owner_dbus(bus, name, mask, owner, creds);
 }
index 1cab2544ecc14c79434e7dbc6d839c520919b097..b63fe56c41a2a80fbdec17138ec2812846bf84ad 100644 (file)
@@ -459,7 +459,7 @@ static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
         assert(k);
 
         off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
-        ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
+        ioctl(bus->input_fd, KDBUS_CMD_FREE, &off);
 
         KDBUS_PART_FOREACH(d, k, items) {
 
index 920488dae7a17acc03b13e22bba5348cf7504bb8..56bf88c39412b4e92296f6208488889ed1060419 100644 (file)
@@ -129,7 +129,7 @@ static void message_free(sd_bus_message *m) {
                 uint64_t off;
 
                 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
-                ioctl(m->bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
+                ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &off);
         }
 
         if (m->bus)
index bfd299bd266e70cc9e5d6bbde74294cb08ec3b44..3dafeceec2ba4539af860d678f9ff1fbfce2d884 100644 (file)
@@ -297,6 +297,11 @@ enum {
 enum {
        _KDBUS_MAKE_NULL,
        KDBUS_MAKE_NAME,
+       KDBUS_MAKE_CRED,        /* allow translator services which connect
+                                * to the bus on behalf of somebody else,
+                                * allow specifying the credentials of the
+                                * client to connect on behalf on. Needs
+                                * privileges */
 };
 
 struct kdbus_cmd_bus_make {
@@ -345,7 +350,7 @@ enum {
        KDBUS_NAME_IN_QUEUE                     = 1 << 16,
 };
 
-/* We allow (de)regestration of names of other peers */
+/* We allow (de)registration of names of other peers */
 struct kdbus_cmd_name {
        __u64 size;
        __u64 flags;
@@ -354,32 +359,39 @@ struct kdbus_cmd_name {
        char name[0];
 };
 
+/* KDBUS_CMD_NAME_LIST */
 enum {
        KDBUS_NAME_LIST_UNIQUE_NAMES            = 1 <<  0,
 };
 
-struct kdbus_cmd_names {
-       __u64 size;
+struct kdbus_cmd_name_list {
        __u64 flags;
-       struct kdbus_cmd_name names[0];
+       __u64 offset;                   /* returned offset in the caller's buffer */
 };
 
-enum {
-       _KDBUS_NAME_INFO_ITEM_NULL,
-       KDBUS_NAME_INFO_ITEM_NAME,      /* userspace → kernel */
-       KDBUS_NAME_INFO_ITEM_SECLABEL,  /* kernel → userspace */
-       KDBUS_NAME_INFO_ITEM_AUDIT,     /* kernel → userspace */
+struct kdbus_name_list {
+       __u64 size;
+       struct kdbus_cmd_name names[0];
 };
 
+/* KDBUS_CMD_NAME_INFO */
 struct kdbus_cmd_name_info {
-       __u64 size;                     /* overall size of info */
+       __u64 size;
        __u64 flags;                    /* query flags */
        __u64 attach_flags;             /* which meta data payload to attach */
-       __u64 id;                       /* either ID, or 0 and _ITEM_NAME follows */
-       struct kdbus_creds creds;
+       __u64 id;                       /* either ID, or 0 and name follows */
+       __u64 offset;                   /* returned offset in the caller's buffer */
+       char name[0];
+};
+
+struct kdbus_name_info {
+       __u64 size;
+       __u64 id;
+       __u64 flags;                    /* connection flags */
        struct kdbus_item items[0];     /* list of item records */
 };
 
+/* KDBUS_CMD_MATCH_ADD/REMOVE */
 enum {
        _KDBUS_MATCH_NULL,
        KDBUS_MATCH_BLOOM,              /* Matches a mask blob against KDBUS_MSG_BLOOM */
@@ -399,22 +411,13 @@ struct kdbus_cmd_match {
        struct kdbus_item items[0];
 };
 
+/* KDBUS_CMD_MONITOR */
 struct kdbus_cmd_monitor {
        __u64 id;               /* We allow setting the monitor flag of other peers */
        unsigned int enable;    /* A boolean to enable/disable monitoring */
        __u32 __pad;
 };
 
-/* FD states:
- * control nodes: unset
- *   bus owner  (via KDBUS_CMD_BUS_MAKE)
- *   ns owner   (via KDBUS_CMD_NS_MAKE)
- *
- * ep nodes: unset
- *   connected  (via KDBUS_CMD_HELLO)
- *   starter    (via KDBUS_CMD_HELLO with KDBUS_CMD_HELLO_STARTER)
- *   ep owner   (via KDBUS_CMD_EP_MAKE)
- */
 enum {
        /* kdbus control node commands: require unset state */
        KDBUS_CMD_BUS_MAKE =            _IOW(KDBUS_IOC_MAGIC, 0x00, struct kdbus_cmd_bus_make),
@@ -427,12 +430,12 @@ enum {
        /* kdbus ep node commands: require connected state */
        KDBUS_CMD_MSG_SEND =            _IOW(KDBUS_IOC_MAGIC, 0x40, struct kdbus_msg),
        KDBUS_CMD_MSG_RECV =            _IOR(KDBUS_IOC_MAGIC, 0x41, __u64 *),
-       KDBUS_CMD_MSG_RELEASE =         _IOW(KDBUS_IOC_MAGIC, 0x42, __u64 *),
+       KDBUS_CMD_FREE =                _IOW(KDBUS_IOC_MAGIC, 0x42, __u64 *),
 
        KDBUS_CMD_NAME_ACQUIRE =        _IOWR(KDBUS_IOC_MAGIC, 0x50, struct kdbus_cmd_name),
        KDBUS_CMD_NAME_RELEASE =        _IOW(KDBUS_IOC_MAGIC, 0x51, struct kdbus_cmd_name),
-       KDBUS_CMD_NAME_LIST =           _IOWR(KDBUS_IOC_MAGIC, 0x52, struct kdbus_cmd_names),
-       KDBUS_CMD_NAME_QUERY =          _IOWR(KDBUS_IOC_MAGIC, 0x53, struct kdbus_cmd_name_info),
+       KDBUS_CMD_NAME_LIST =           _IOWR(KDBUS_IOC_MAGIC, 0x52, struct kdbus_cmd_name_list),
+       KDBUS_CMD_NAME_INFO =           _IOWR(KDBUS_IOC_MAGIC, 0x53, struct kdbus_cmd_name_info),
 
        KDBUS_CMD_MATCH_ADD =           _IOW(KDBUS_IOC_MAGIC, 0x60, struct kdbus_cmd_match),
        KDBUS_CMD_MATCH_REMOVE =        _IOW(KDBUS_IOC_MAGIC, 0x61, struct kdbus_cmd_match),
index 0d5deb6c6deb1f88855a9e00c014c1e4f2d9c373..37b6fedf031159de374d84ab54734f0e299192cc 100644 (file)
@@ -1153,9 +1153,8 @@ _public_ void sd_bus_close(sd_bus *bus) {
 
         /* We'll leave the fd open in case this is a kernel bus, since
          * there might still be memblocks around that reference this
-         * bus, and they might need to invoke the
-         * KDBUS_CMD_MSG_RELEASE ioctl on the fd when they are
-         * freed. */
+         * bus, and they might need to invoke the * KDBUS_CMD_FREE
+         * ioctl on the fd when they are freed. */
 }
 
 static void bus_enter_closing(sd_bus *bus) {