]> git.proxmox.com Git - ovs.git/commitdiff
Do not free uninitialized packets.
authorJarno Rajahalme <jrajahalme@nicira.com>
Tue, 17 Dec 2013 23:54:30 +0000 (15:54 -0800)
committerJarno Rajahalme <jrajahalme@nicira.com>
Tue, 17 Dec 2013 23:54:30 +0000 (15:54 -0800)
Commit da546e0 (dpif: Allow execute to modify the packet.) uninitializes
the "dpif_upcall.packet" of "struct upcall" when dpif_recv() returns error.
The packet ofpbuf is likely uninitialized in this case, hence calling
ofpbuf_uninit() on it will likely cause a SEGFAULT.

This commit fixes this bug by only uninitializing packet's ofpbuf on
successfully received upcalls.

A note warning about this is added on the comment of dpif_recv() in
dpif.c and dpif-provider.h.

Reported-by: Alex Wang <alexw@nicira.com>
Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
lib/dpif-provider.h
lib/dpif.c
ofproto/ofproto-dpif-upcall.c

index f279934b613f8e33eaef28ba490855220e682818..90a02b43600f9797fb11305d4d54a26aa401c0e5 100644 (file)
@@ -349,7 +349,9 @@ struct dpif_class {
      * The caller owns the data of 'upcall->packet' and may modify it.  If
      * packet's headroom is exhausted as it is manipulated, 'upcall->packet'
      * will be reallocated.  This requires the data of 'upcall->packet' to be
-     * released with ofpbuf_uninit() before 'upcall' is destroyed.
+     * released with ofpbuf_uninit() before 'upcall' is destroyed.  However,
+     * when an error is returned, the 'upcall->packet' may be uninitialized
+     * and should not be released.
      *
      * This function must not block.  If no upcall is pending when it is
      * called, it should return EAGAIN without blocking. */
index 7220b380cf2efe48fb5ba99f64608897dd6ccc7e..6b519b8bdeec413a3aa7565446e574f5f4ad408a 100644 (file)
@@ -1315,6 +1315,13 @@ dpif_recv_set(struct dpif *dpif, bool enable)
  * 'upcall->key' and 'upcall->userdata' point into data in the caller-provided
  * 'buf', so their memory cannot be freed separately from 'buf'.
  *
+ * The caller owns the data of 'upcall->packet' and may modify it.  If
+ * packet's headroom is exhausted as it is manipulated, 'upcall->packet'
+ * will be reallocated.  This requires the data of 'upcall->packet' to be
+ * released with ofpbuf_uninit() before 'upcall' is destroyed.  However,
+ * when an error is returned, the 'upcall->packet' may be uninitialized
+ * and should not be released.
+ *
  * Returns 0 if successful, otherwise a positive errno value.  Returns EAGAIN
  * if no upcall is immediately available. */
 int
index 12214d29819f98c2515468e73368272b5921b5bb..f0088f0ea429e3b809463757199f1b38cc795724 100644 (file)
@@ -533,7 +533,10 @@ recv_upcalls(struct udpif *udpif)
         error = dpif_recv(udpif->dpif, &upcall->dpif_upcall,
                           &upcall->upcall_buf);
         if (error) {
-            upcall_destroy(upcall);
+            /* upcall_destroy() can only be called on successfully received
+             * upcalls. */
+            ofpbuf_uninit(&upcall->upcall_buf);
+            free(upcall);
             break;
         }