On 17 Mar 2026, at 19:55, Mike Pattrick via dev wrote:
> 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);
Hi Mike,
Thanks for the patch. However, I don't believe this change is necessary.
Just one line above the proposed change, the code checks if the batch is
full via dp_packet_batch_is_full(curr_batch). If it is, it moves to the
next (empty) batch in the array.
This appears to be a false positive from the static analyzer (I have also
marked this as a false positive in Coverity previously). Furthermore, if
we were to adopt this check, it is missing from the other invocations of
dp_packet_batch_add() later in the same function.
Cheers,
Eelco
> + 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
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev