update cookie and cookie_reply logic
authorKay Sievers <kay@vrfy.org>
Wed, 25 Dec 2013 03:14:05 +0000 (04:14 +0100)
committerKay Sievers <kay@vrfy.org>
Wed, 25 Dec 2013 04:00:36 +0000 (05:00 +0100)
connection.c
kdbus.h
message.c

index f2490109f425e20dc055473d902d004069188c58..8e6866b92711e5bd8a02f3b14276d8a61f569032 100644 (file)
@@ -80,7 +80,7 @@ struct kdbus_conn_queue {
  * @entry:             The list_head entry of the connection's reply_from_list
  * @conn:              The counterpart connection that is expected to answer
  * @deadline_ns:       The deadline of the reply, in nanoseconds
- * @cookie:            The expected reply cookie
+ * @cookie:            The cookie of the requesting message
  */
 struct kdbus_conn_reply_entry {
        struct list_head entry;
@@ -724,25 +724,28 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep,
 
        if (conn_src) {
                bool allowed = false;
-               struct kdbus_conn_reply_entry *reply;
+               struct kdbus_conn_reply_entry *r;
 
                /*
                 * Walk the list of connection we expect a reply from.
                 * If there's any matching entry, allow the message to
                 * be sent, and remove the entry.
                 */
-               mutex_lock(&conn_dst->lock);
-               list_for_each_entry(reply, &conn_dst->reply_list, entry) {
-                       if (reply->conn != conn_src)
-                               continue;
-                       if (reply->cookie != msg->cookie)
-                               continue;
+               if (msg->cookie_reply > 0) {
+                       mutex_lock(&conn_dst->lock);
+                       list_for_each_entry(r, &conn_dst->reply_list, entry) {
+                               if (r->conn != conn_src)
+                                       continue;
 
-                       kdbus_conn_reply_entry_free(reply);
-                       allowed = true;
-                       break;
+                               if (r->cookie != msg->cookie_reply)
+                                       continue;
+
+                               kdbus_conn_reply_entry_free(r);
+                               allowed = true;
+                               break;
+                       }
+                       mutex_unlock(&conn_dst->lock);
                }
-               mutex_unlock(&conn_dst->lock);
 
                /* ... otherwise, ask the policy DB for permission */
                if (!allowed && ep->policy_db) {
diff --git a/kdbus.h b/kdbus.h
index 6991b7fb8b84772d66fad2a97bc293eac6e73752..71bf86d063547ec5260ced38047473688c84fcb9 100644 (file)
--- a/kdbus.h
+++ b/kdbus.h
@@ -313,9 +313,11 @@ struct kdbus_item {
 
 /**
  * enum kdbus_msg_flags - type of message
- * @KDBUS_MSG_FLAGS_EXPECT_REPLY:      Expect a reply message, used for method
- *                                     calls. The cookie identifies the
- *                                     message and the respective reply
+ * @KDBUS_MSG_FLAGS_EXPECT_REPLY:      Expect a reply message, used for
+ *                                     method calls. The userspace-supplied
+ *                                     cookie identifies the message and the
+ *                                     respective reply carries the cookie
+ *                                     in cookie_reply
  * @KDBUS_MSG_FLAGS_NO_AUTO_START:     Do not start a service, if the addressed
  *                                     name is not currently active
  */
@@ -327,7 +329,7 @@ enum kdbus_msg_flags {
 /**
  * enum kdbus_payload_type - type of payload carried by message
  * @KDBUS_PAYLOAD_KERNEL:      Kernel-generated simple message
- * @KDBUS_PAYLOAD_DBUS:                D-Bus marshalling
+ * @KDBUS_PAYLOAD_DBUS:                D-Bus marshalling
  */
 enum kdbus_payload_type {
        KDBUS_PAYLOAD_KERNEL,
@@ -341,9 +343,11 @@ enum kdbus_payload_type {
  * @dst_id:            64-bit ID of the destination connection
  * @src_id:            64-bit ID of the source connection
  * @payload_type:      Payload type (KDBUS_PAYLOAD_*)
- * @cookie:            Userspace-supplied cookie
- * @cookie_reply:      For kernel-generated messages, this is the cookie
- *                     the message is a reply to
+ * @cookie:            Userspace-supplied cookie, for the connection
+ *                     to identify its messages
+ * @cookie_reply:      A reply to the message with the same cookie. The
+ *                     reply itself has its own cookie, @cookie_reply
+ *                     corresponds to the cookie of the request message
  * @timeout_ns:                For non-kernel-generated messages, this denotes the
  *                     message timeout in nanoseconds. A message has to be
  *                     received with KDBUS_CMD_MSG_RECV by the destination
@@ -365,10 +369,8 @@ struct kdbus_msg {
        __u64 src_id;
        __u64 payload_type;
        __u64 cookie;
-       union {
-               __u64 cookie_reply;
-               __u64 timeout_ns;
-       };
+       __u64 cookie_reply;
+       __u64 timeout_ns;
        struct kdbus_item items[0];
 } __attribute__((aligned(8)));
 
index 2a17d286c4ff07feed674eb2191d8e4e9ac25a02..f6d3bc6444ef009903909c1d6ca2db3daba3ab15 100644 (file)
--- a/message.c
+++ b/message.c
@@ -269,13 +269,20 @@ int kdbus_kmsg_new_from_user(struct kdbus_conn *conn,
                goto exit_free;
        }
 
-       /* check validity and gather some values for processing */
+       /* requests for replies need a timeout */
        if (m->msg.flags & KDBUS_MSG_FLAGS_EXPECT_REPLY &&
            m->msg.timeout_ns == 0) {
                ret = -EINVAL;
                goto exit_free;
        }
 
+       /* replies cannot request a reply themselves */
+       if (m->msg.flags & KDBUS_MSG_FLAGS_EXPECT_REPLY &&
+           m->msg.cookie_reply > 0) {
+               ret = -EINVAL;
+               goto exit_free;
+       }
+
        ret = kdbus_msg_scan_items(conn, m);
        if (ret < 0)
                goto exit_free;