netlink: Make nl_sock_transact() always return a reply on success.
authorBen Pfaff <blp@nicira.com>
Thu, 20 May 2010 22:57:36 +0000 (15:57 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 17 Jun 2010 17:30:18 +0000 (10:30 -0700)
Until now, if nl_sock_transact() received a reply that merely acknowledged
success, without providing any other payload, it would return success but
not provide the reply to its caller.  This is inconsistent and could easily
cause a segfault in a caller that expects to see the reply on success, if
kernel behavior changed, for whatever reason, so that a request that
previously returned data now just returns an acknowledgment.  In practice
this kind of change should never happen, but it is still better to handle
it properly.

lib/netlink.c

index de88a81..334e45a 100644 (file)
@@ -421,7 +421,14 @@ recv:
         ofpbuf_delete(reply);
         goto recv;
     }
-    if (nl_msg_nlmsgerr(reply, &retval)) {
+
+    /* If the reply is an error, discard the reply and return the error code.
+     *
+     * Except: if the reply is just an acknowledgement (error code of 0), and
+     * the caller is interested in the reply (replyp != NULL), pass the reply
+     * up to the caller.  Otherwise the caller will get a return value of 0
+     * and null '*replyp', which makes unwary callers likely to segfault. */
+    if (nl_msg_nlmsgerr(reply, &retval) && (retval || !replyp)) {
         ofpbuf_delete(reply);
         if (retval) {
             VLOG_DBG_RL(&rl, "received NAK error=%d (%s)",