kdbus: always pack message header as as single PAYLOAD_VEC item 89/71489/1 accepted/tizen/common/20160530.131628 accepted/tizen/ivi/20160602.021635 accepted/tizen/mobile/20160602.021631 accepted/tizen/tv/20160602.021607 accepted/tizen/wearable/20160602.021621 submit/tizen/20160527.082529
authorLukasz Skalski <l.skalski@samsung.com>
Wed, 25 May 2016 12:46:10 +0000 (14:46 +0200)
committerLukasz Skalski <l.skalski@samsung.com>
Wed, 25 May 2016 12:46:45 +0000 (14:46 +0200)
According to PORTING-DBUS1 document [1], the message header in its
entirety must be contained in a single PAYLOAD_VEC item. What's more,
in case of memfd transport, message footer (which contains body signature
and offsets size) has to be attached at the end of message as a yet another
PAYLOAD_VEC item.

[1] https://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/PORTING-DBUS1

Change-Id: I282589c0641c1eb97f874fcfd6e3bee6ecacc8ae

dbus/dbus-message.c
dbus/dbus-transport-kdbus.c
dbus/kdbus-common.c

index 0792e11..e058b7a 100644 (file)
@@ -4679,7 +4679,7 @@ _dbus_decode_kmsg (DBusString  *data,
           if (n_unix_fds > n_fds)
             {
               _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
-                            n_unix_fds, loader->n_unix_fds);
+                            n_unix_fds, message->n_unix_fds);
               dbus_message_unref (message);
               return NULL;
             }
index 80c5b3e..75cc180 100644 (file)
@@ -504,30 +504,22 @@ parse_name (const char *name)
 
 static int
 prepare_mfd (int memfd,
-             const char *header,
-             uint64_t header_size,
              const char *body,
              uint64_t body_size)
 {
-  const char *data[] = { header, body };
-  uint64_t count[] = { header_size, body_size };
   int64_t wr;
-  size_t p;
 
   _dbus_verbose ("sending data via memfd\n");
-  for (p = 0; p < sizeof (data) / sizeof (data[0]); ++p)
+  while (body_size)
     {
-      while (count[p])
+      wr = write (memfd, body, body_size);
+      if (wr < 0)
         {
-          wr = write (memfd, data[p], count[p]);
-          if (wr < 0)
-            {
-              _dbus_verbose ("writing to memfd failed: (%d) %m\n", errno);
-              return -1;
-            }
-          count[p] -= wr;
-          data[p] += wr;
+          _dbus_verbose ("writing to memfd failed: (%d) %m\n", errno);
+          return -1;
         }
+      body_size -= wr;
+      body += wr;
     }
 
   // seal data - kdbus module needs it
@@ -717,6 +709,7 @@ kdbus_write_msg_internal (DBusTransportKdbus  *transport,
   int memfd = -1;
   const int *unix_fds;
   unsigned fds_count;
+  const char* header_data;
   DBusError error;
 
   dbus_uint64_t items_size;
@@ -807,47 +800,79 @@ kdbus_write_msg_internal (DBusTransportKdbus  *transport,
   /* build message contents */
   item = msg->items;
 
-  if (memfd >= 0)
+  header_data = _dbus_string_get_const_data (header);
+
+  _dbus_verbose ("sending data by vec\n");
+  item = _kdbus_item_add_payload_vec (item,
+                                      header_size,
+                                      (uintptr_t)header_data);
+  if (body_size > 0)
     {
-      if (prepare_mfd (memfd,
-                       _dbus_string_get_const_data (header), header_size,
-                       _dbus_string_get_const_data (body), body_size) == -1)
+      const char* body_data = _dbus_string_get_const_data (body);
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+      if (-1 != debug)
         {
-          ret_size = -1;
-          goto out;
+          debug_str ("Header to send:", header);
+          debug_str ("Body to send:", body);
         }
+#endif
 
-      item = _kdbus_item_add_payload_memfd (item,
-                                            0,
-                                            ret_size,
-                                            memfd);
-    }
-  else
-    {
-      const char* header_data = _dbus_string_get_const_data (header);
-
-      _dbus_verbose ("sending data by vec\n");
-      item = _kdbus_item_add_payload_vec (item,
-                                          header_size,
-                                          (uintptr_t)header_data);
-      if (body_size > 0)
+      if (memfd >= 0)
         {
-          const char* body_data = _dbus_string_get_const_data (body);
 
-#ifdef DBUS_ENABLE_VERBOSE_MODE
-          if (-1 != debug)
+          size_t body_offsets_size;
+         const char *footer_ptr;
+
+          /* determine body offsets size */
+          if (ret_size <= 0xFF)
+            body_offsets_size = 1;
+          else if (ret_size <= 0xFFFF)
+            body_offsets_size = 2;
+          else if (ret_size <= 0xFFFFFFFF)
+            body_offsets_size = 4;
+          else
+            body_offsets_size = 8;
+
+          /* check footer size */
+          footer_ptr = body_data + body_size - body_offsets_size -1;
+          while (footer_ptr >= body_data && (*footer_ptr) != 0)
+            footer_ptr--;
+
+          if (footer_ptr < body_data)
             {
-              debug_str ("Header to send:", header);
-              debug_str ("Body to send:", body);
+              ret_size = -1;
+              goto out;
             }
-#endif
 
+          /* prepare memfd for body */
+          if (prepare_mfd (memfd,
+                           body_data,
+                           (footer_ptr - body_data) * sizeof(char)) == -1)
+            {
+              ret_size = -1;
+              goto out;
+            }
+
+         /* body */
+          item = _kdbus_item_add_payload_memfd (item,
+                                                0,
+                                                (footer_ptr - body_data) * sizeof(char),
+                                                memfd);
+
+         /* footer */
+          item = _kdbus_item_add_payload_vec (item,
+                                              (body_data + body_size - footer_ptr) * sizeof(char),
+                                              (uintptr_t)footer_ptr);
+        }
+      else
+        {
           while (body_size > 0)
             {
               dbus_uint64_t part_size = body_size;
 
               if (part_size > KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE)
-                part_size = KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
+                  part_size = KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
 
               _dbus_verbose ("attaching body part\n");
               item = _kdbus_item_add_payload_vec (item,
@@ -856,8 +881,8 @@ kdbus_write_msg_internal (DBusTransportKdbus  *transport,
               body_data += part_size;
               body_size -= part_size;
             }
-        }
-    }
+        } /* memfd */
+    } /* body_size */
 
   if (fds_count)
       item = _kdbus_item_add_fds (item, unix_fds, fds_count);
index e0af233..c2c2e0c 100644 (file)
@@ -698,16 +698,21 @@ _kdbus_compute_msg_items_size (kdbus_t       *kdbus,
 {
   __u64 items_size = 0;
 
+  /*  header */
+  items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_vec));
+
   if (use_memfd)
     {
+      /* body */
       items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_memfd));
+
+      /* footer */
+      items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_vec));
     }
   else
     {
       __u64 vectors = (body_size + KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE - 1)
                        / KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
-      /* 1st vector -> for header */
-      items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_vec));
       /* subsequent vectors -> parts of body */
       items_size += vectors * KDBUS_ITEM_SIZE (sizeof (struct kdbus_vec));
     }