When a batch is full, dp_packet_batch_add() frees the packet instead of
adding it to the batch.  In dp_packet_gso__(), the code calls
dp_packet_batch_add() to add the original packet 'p' back into the
batch, but does not check if the packet was freed.  If the packet was
freed, subsequent operations on 'p' (such as dp_packet_tunnel(),
dp_packet_get_inner_tcp_payload(), and dp_packet_set_size()) cause
undefined behavior.

Fix by checking the return value and exiting early if the packet was
freed.

Found with clang analyze.

Fixes: ef762327f6d3 ("dp-packet-gso: Refactor software segmentation code.")
Signed-off-by: Mike Pattrick <[email protected]>
---
 lib/dp-packet-gso.c |  4 +++-
 lib/dp-packet.h     | 12 +++++++-----
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/lib/dp-packet-gso.c b/lib/dp-packet-gso.c
index bceb851fb..0d4d52daf 100644
--- a/lib/dp-packet-gso.c
+++ b/lib/dp-packet-gso.c
@@ -199,7 +199,9 @@ dp_packet_gso__(struct dp_packet *p, struct dp_packet_batch 
**batches,
     if (dp_packet_batch_is_full(curr_batch)) {
         curr_batch++;
     }
-    dp_packet_batch_add(curr_batch, p);
+    if (!dp_packet_batch_add(curr_batch, p)) {
+        goto out;
+    }
 
     if (n_segs <= 1) {
         goto out;
diff --git a/lib/dp-packet.h b/lib/dp-packet.h
index d92b9d473..fb15a8546 100644
--- a/lib/dp-packet.h
+++ b/lib/dp-packet.h
@@ -872,22 +872,24 @@ dp_packet_batch_init(struct dp_packet_batch *batch)
     batch->trunc = false;
 }
 
-static inline void
+static inline bool
 dp_packet_batch_add__(struct dp_packet_batch *batch,
                       struct dp_packet *packet, size_t limit)
 {
     if (batch->count < limit) {
         batch->packets[batch->count++] = packet;
+        return true;
     } else {
         dp_packet_delete(packet);
+        return false;
     }
 }
 
 /* When the batch is full, 'packet' will be dropped and freed. */
-static inline void
+static inline bool
 dp_packet_batch_add(struct dp_packet_batch *batch, struct dp_packet *packet)
 {
-    dp_packet_batch_add__(batch, packet, NETDEV_MAX_BURST);
+    return dp_packet_batch_add__(batch, packet, NETDEV_MAX_BURST);
 }
 
 static inline size_t
@@ -904,11 +906,11 @@ dp_packet_batch_refill_init(struct dp_packet_batch *batch)
     batch->count = 0;
 };
 
-static inline void
+static inline bool
 dp_packet_batch_refill(struct dp_packet_batch *batch,
                        struct dp_packet *packet, size_t idx)
 {
-    dp_packet_batch_add__(batch, packet, MIN(NETDEV_MAX_BURST, idx + 1));
+    return dp_packet_batch_add__(batch, packet, MIN(NETDEV_MAX_BURST, idx + 
1));
 }
 
 static inline void
-- 
2.53.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to