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