Date: Wed, 29 Apr 2026 14:47:50 +0000 From: Mark Johnston <markj@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Cc: Kristof Provost <kp@FreeBSD.org> Subject: git: e1c9f92130e8 - stable/15 - pf: improve SCTP validation Message-ID: <69f21a16.3b8c8.445c6a60@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch stable/15 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=e1c9f92130e8327c52cc1953c6a9d53dfb4bb177 commit e1c9f92130e8327c52cc1953c6a9d53dfb4bb177 Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2026-04-26 09:34:55 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-04-29 14:40:57 +0000 pf: improve SCTP validation As per RFC5061 "4.2. New Parameter Types" the add/delete IP address parameters (0xc001, 0xc002) may not be present in an INIT or INIT-ACK chunk. They are only allowed to be present in an ASCONF chunk. This also prevents unbounded recursion while parsing an SCTP packet. Approved by: so Security: FreeBSD-SA-26:14.pf Security: CVE-2026-7164 PR: 294799 Reported by: Igor Gabriel Sousa e Souza Sponsored by: Orange Business Services --- sys/netpfil/pf/pf.c | 16 +++++++++++----- tests/sys/netpfil/pf/sctp.py | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 6349e922387b..7aee28e7b917 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -7682,7 +7682,7 @@ again: } static int -pf_multihome_scan(int start, int len, struct pf_pdesc *pd, int op) +pf_multihome_scan(int start, int len, struct pf_pdesc *pd, int op, bool asconf) { int off = 0; struct pf_sctp_multihome_job *job; @@ -7787,13 +7787,16 @@ pf_multihome_scan(int start, int len, struct pf_pdesc *pd, int op) int ret; struct sctp_asconf_paramhdr ah; + if (asconf) + return (PF_DROP); + if (!pf_pull_hdr(pd->m, start + off, &ah, sizeof(ah), NULL, NULL, pd->af)) return (PF_DROP); ret = pf_multihome_scan(start + off + sizeof(ah), ntohs(ah.ph.param_length) - sizeof(ah), pd, - SCTP_ADD_IP_ADDRESS); + SCTP_ADD_IP_ADDRESS, true); if (ret != PF_PASS) return (ret); break; @@ -7802,12 +7805,15 @@ pf_multihome_scan(int start, int len, struct pf_pdesc *pd, int op) int ret; struct sctp_asconf_paramhdr ah; + if (asconf) + return (PF_DROP); + if (!pf_pull_hdr(pd->m, start + off, &ah, sizeof(ah), NULL, NULL, pd->af)) return (PF_DROP); ret = pf_multihome_scan(start + off + sizeof(ah), ntohs(ah.ph.param_length) - sizeof(ah), pd, - SCTP_DEL_IP_ADDRESS); + SCTP_DEL_IP_ADDRESS, true); if (ret != PF_PASS) return (ret); break; @@ -7828,7 +7834,7 @@ pf_multihome_scan_init(int start, int len, struct pf_pdesc *pd) start += sizeof(struct sctp_init_chunk); len -= sizeof(struct sctp_init_chunk); - return (pf_multihome_scan(start, len, pd, SCTP_ADD_IP_ADDRESS)); + return (pf_multihome_scan(start, len, pd, SCTP_ADD_IP_ADDRESS, false)); } int @@ -7837,7 +7843,7 @@ pf_multihome_scan_asconf(int start, int len, struct pf_pdesc *pd) start += sizeof(struct sctp_asconf_chunk); len -= sizeof(struct sctp_asconf_chunk); - return (pf_multihome_scan(start, len, pd, SCTP_ADD_IP_ADDRESS)); + return (pf_multihome_scan(start, len, pd, SCTP_ADD_IP_ADDRESS, false)); } int diff --git a/tests/sys/netpfil/pf/sctp.py b/tests/sys/netpfil/pf/sctp.py index 9f1d7dea4ef6..722f7777a305 100644 --- a/tests/sys/netpfil/pf/sctp.py +++ b/tests/sys/netpfil/pf/sctp.py @@ -618,6 +618,29 @@ class TestSCTP_SRV(VnetTestTemplate): assert r.getlayer(sp.SCTPChunkInitAck) assert r.getlayer(sp.SCTP).tag == 42 + @pytest.mark.require_user("root") + @pytest.mark.require_progs(["scapy"]) + def test_too_many_add_ip(self): + import scapy.all as sp + DEPTH=90 + params=[] + for i in range(0, DEPTH): + ch = sp.SCTPChunkParamAddIPAddr(len=(DEPTH - i) * 8) + params.append(ch) + packet = sp.IP(src="192.0.2.1", dst="192.0.2.2") \ + / sp.SCTP(sport=4321, dport=1234) \ + / sp.SCTPChunkInit(init_tag=1, n_in_streams=1, n_out_streams=1, a_rwnd=1500, + params=params) + packet.show() + sp.hexdump(packet) + print("len %d" % len(packet)) + + r = sp.sr1(packet, timeout=3) + # We should not get a reply to this + if r: + r.show() + assert not r + class TestSCTPv6(VnetTestTemplate): REQUIRED_MODULES = ["sctp", "pf"] TOPOLOGY = {home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69f21a16.3b8c8.445c6a60>
