sctp_check_len() walks the chunks while the offset of the next chunk
is below the L4 size, and reads the chunk length there. When fewer
than 4 bytes are left after the last complete chunk, the length is
read past the end of the packet.
Only enter the loop when a whole chunk header fits in the packet. A
packet with a truncated chunk header now fails the check, since the
walk does not end exactly at the L4 size.
Fixes: 501f665a5a4b ("conntrack: Extract l4 information for SCTP.")
Assisted-by: claude-opus-5-5, Claude Code
Signed-off-by: Alejandro Pacheco <[email protected]>
---
lib/conntrack.c | 2 +-
tests/ofproto-dpif.at | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/lib/conntrack.c b/lib/conntrack.c
index f84cdd216..d40870c63 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -1870,7 +1870,7 @@ sctp_check_len(const struct sctp_header *sh, size_t size)
*/
for (next = sizeof(struct sctp_header),
sch = SCTP_NEXT_CHUNK(sh, next);
- next < size;
+ next + sizeof *sch <= size;
next += ROUND_UP(ntohs(sch->length), 4),
sch = SCTP_NEXT_CHUNK(sh, next)) {
/* rfc4960: This value represents the size of the chunk in bytes,
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index cd8991814..8598ffa39 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -12639,6 +12639,41 @@
icmp6,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([ofproto-dpif - conntrack - sctp truncated chunk header])
+OVS_VSWITCHD_START
+
+add_of_ports br0 1 2
+
+AT_DATA([flows.txt], [dnl
+table=0,priority=10,ip,ct_state=-trk,action=ct(table=1)
+table=1,priority=10,ct_state=+trk+inv,action=drop
+table=1,priority=10,ct_state=+trk+new,action=output:2
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+m4_define([SCTP_PKT], m4_join([],
+dnl eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a,type=0x0800)
+[50540000000a5054000000090800],
+dnl ipv4(src=10.0.0.1,dst=10.0.0.2,proto=132,tot_len=33)
+[4500002100000000408466570a0000010a000002],
+dnl sctp(src=1,dst=2,vtag=0,csum=0)
+[000100020000000000000000],
+dnl One byte of a chunk header.
+[01]))
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 SCTP_PKT])
+
+AT_CHECK([ovs-appctl revalidator/purge])
+AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl
+ table=1, n_packets=1, n_bytes=47, priority=10,ct_state=+inv+trk actions=drop
+ table=1, priority=10,ct_state=+new+trk actions=output:2
+NXST_FLOW reply:
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([ofproto-dpif - conntrack - zones])
OVS_VSWITCHD_START
--
2.53.0
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev