Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: conntrack: fix false CRC32c mismatch using paged skb

sctp_compute_cksum() implementation assumes that at least the SCTP header
is in the linear part of skb: modify conntrack error callback to avoid
false CRC32c mismatch, if the transport header is partially/entirely paged.

Fixes: cf6e007eef83 ("netfilter: conntrack: validate SCTP crc32c in PREROUTING")
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Davide Caratti and committed by
Pablo Neira Ayuso
f3c0eb05 6d18c732

+6 -3
+6 -3
net/netfilter/nf_conntrack_proto_sctp.c
··· 512 512 u8 pf, unsigned int hooknum) 513 513 { 514 514 const struct sctphdr *sh; 515 - struct sctphdr _sctph; 516 515 const char *logmsg; 517 516 518 - sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph); 519 - if (!sh) { 517 + if (skb->len < dataoff + sizeof(struct sctphdr)) { 520 518 logmsg = "nf_ct_sctp: short packet "; 521 519 goto out_invalid; 522 520 } 523 521 if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && 524 522 skb->ip_summed == CHECKSUM_NONE) { 523 + if (!skb_make_writable(skb, dataoff + sizeof(struct sctphdr))) { 524 + logmsg = "nf_ct_sctp: failed to read header "; 525 + goto out_invalid; 526 + } 527 + sh = (const struct sctphdr *)(skb->data + dataoff); 525 528 if (sh->checksum != sctp_compute_cksum(skb, dataoff)) { 526 529 logmsg = "nf_ct_sctp: bad CRC "; 527 530 goto out_invalid;