netfilter: nfnetlink_queue: unbreak SCTP traffic

when packet is enqueued with nfqueue and GSO is enabled, checksum
calculation has to take into account the protocol, as SCTP uses a
32 bits CRC checksum.

Enter skb_gso_segment() path in case of SCTP GSO packets because
skb_zerocopy() does not support for GSO_BY_FRAGS.

Joint work with Pablo.

Signed-off-by: Antonio Ojea <aojea@google.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Antonio Ojea 2024-06-27 13:27:10 +02:00 committed by Pablo Neira Ayuso
parent 1bf8e07c38
commit 26a77d0289
2 changed files with 11 additions and 2 deletions

View File

@ -3386,6 +3386,7 @@ int skb_crc32c_csum_help(struct sk_buff *skb)
out:
return ret;
}
EXPORT_SYMBOL(skb_crc32c_csum_help);
__be16 skb_network_protocol(struct sk_buff *skb, int *depth)
{

View File

@ -540,6 +540,14 @@ nla_put_failure:
return -1;
}
static int nf_queue_checksum_help(struct sk_buff *entskb)
{
if (skb_csum_is_sctp(entskb))
return skb_crc32c_csum_help(entskb);
return skb_checksum_help(entskb);
}
static struct sk_buff *
nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
struct nf_queue_entry *entry,
@ -602,7 +610,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
case NFQNL_COPY_PACKET:
if (!(queue->flags & NFQA_CFG_F_GSO) &&
entskb->ip_summed == CHECKSUM_PARTIAL &&
skb_checksum_help(entskb))
nf_queue_checksum_help(entskb))
return NULL;
data_len = READ_ONCE(queue->copy_range);
@ -1014,7 +1022,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
break;
}
if ((queue->flags & NFQA_CFG_F_GSO) || !skb_is_gso(skb))
if (!skb_is_gso(skb) || ((queue->flags & NFQA_CFG_F_GSO) && !skb_is_gso_sctp(skb)))
return __nfqnl_enqueue_packet(net, queue, entry);
nf_bridge_adjust_skb_data(skb);