Commit f1533cce authored by Marcelo Ricardo Leitner's avatar Marcelo Ricardo Leitner Committed by David S. Miller

sctp: fix panic when sending auth chunks

When we introduced GSO support, if using auth the auth chunk was being
left queued on the packet even after the final segment was generated.
Later on sctp_transmit_packet it calls sctp_packet_reset, which zeroed
the packet len while not accounting for this left-over. This caused more
space to be used the next packet due to the chunk still being queued,
but space which wasn't allocated as its size wasn't accounted.

The fix is to only queue it back when we know that we are going to
generate another segment.

Fixes: 90017acc ("sctp: Add GSO support")
Signed-off-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 09a7636a
...@@ -582,9 +582,7 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp) ...@@ -582,9 +582,7 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
*/ */
pkt_size -= WORD_ROUND(chunk->skb->len); pkt_size -= WORD_ROUND(chunk->skb->len);
if (chunk == packet->auth && !list_empty(&packet->chunk_list)) if (!sctp_chunk_is_data(chunk) && chunk != packet->auth)
list_add(&chunk->list, &packet->chunk_list);
else if (!sctp_chunk_is_data(chunk))
sctp_chunk_free(chunk); sctp_chunk_free(chunk);
if (!pkt_size) if (!pkt_size)
...@@ -605,6 +603,18 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp) ...@@ -605,6 +603,18 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
(struct sctp_auth_chunk *)auth, (struct sctp_auth_chunk *)auth,
gfp); gfp);
if (packet->auth) {
if (!list_empty(&packet->chunk_list)) {
/* We will generate more packets, so re-queue
* auth chunk.
*/
list_add(&chunk->list, &packet->chunk_list);
} else {
sctp_chunk_free(packet->auth);
packet->auth = NULL;
}
}
if (!gso) if (!gso)
break; break;
...@@ -735,6 +745,8 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp) ...@@ -735,6 +745,8 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
} }
goto out; goto out;
nomem: nomem:
if (packet->auth && list_empty(&packet->auth->list))
sctp_chunk_free(packet->auth);
err = -ENOMEM; err = -ENOMEM;
goto err; goto err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment