connection: check whether a reply exists before freeing it
authorDaniel Mack <zonque@gmail.com>
Fri, 4 Apr 2014 18:35:32 +0000 (20:35 +0200)
committerDaniel Mack <zonque@gmail.com>
Fri, 4 Apr 2014 18:35:32 +0000 (20:35 +0200)
For KDBUS_RECV_DROP, Walk the list of pending replies and see if the
one attached to this queue item is stil there.  It might have been
removed by an incoming reply, and we currently don't track reply
entries in that direction in order to prevent potentially dangling
pointers.

At least atm, KDBUS_RECV_DROP is considered a rarely used operation, so
we can live with that.

connection.c

index f14cedce53d09bdef88c1e444d5b08bc5913b134..2d69f17d3925f09ed71cddd3e0fc4302813d5666 100644 (file)
@@ -1024,9 +1024,29 @@ int kdbus_cmd_msg_recv(struct kdbus_conn *conn,
 
        /* just drop the message */
        if (recv->flags & KDBUS_RECV_DROP) {
-               struct kdbus_conn_reply *reply = NULL;
+               struct kdbus_conn_reply *r, *reply = NULL;
+               bool reply_found = false;
 
                if (queue->reply) {
+                       struct kdbus_conn_reply *r;
+
+                       /*
+                        * Walk the list of pending replies and see if the
+                        * one attached to this queue item is stil there.
+                        * It might have been removed by an incoming reply,
+                        * and we currently don't track reply entries in that
+                        * direction in order to prevent potentially dangling
+                        * pointers.
+                        */
+                       list_for_each_entry(r, &conn->reply_list, entry) {
+                               if (r == queue->reply) {
+                                       reply_found = true;
+                                       break;
+                               }
+                       }
+               }
+
+               if (reply_found) {
                        if (queue->reply->sync) {
                                kdbus_conn_reply_sync(queue->reply, -EPIPE);
                        } else {