From nobody Tue Feb 18 17:43:16 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Yy6Lt1fSdz5nwfB; Tue, 18 Feb 2025 17:43:18 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Yy6Ls0Yqvz3WNT; Tue, 18 Feb 2025 17:43:17 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1739900597; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Ww286Yo2Ryn5Qk7gkfyVQiBG1UgeK5tLiMBOjR+tM8I=; b=TM1xjO8ag0wDJuBp3MoGUi+YSZ2qDeg7eJBDPHo+KintfB9FtItkcVlTcA7fa/hgr9/WcG HIfcYFlJXqEds3wZNs2g9J+zphAcXnIWyzUDIHNa1f67JIdDsJQkclnvmE9dnJlb3orzcQ n4SGpZbrswkFg0Ekpbjqragd4A0JEFFCENkuBEH7adN4idsL2Vqmasufu3uEDHIO75jzB6 OqZerDUKV+FQslXkptHxC5hG7nj3YpxKqCPuBsgh6JO15M585rc0Aloj6lNdnWeWeX2p/g fq4iL+8tZH9khGayR227ig4HRxka7H3jeC7MjdisMmT3aPdnQg2umjnZNt9+uA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1739900597; a=rsa-sha256; cv=none; b=ftkn74pG0SIfSvNwpsIZdJFqHBxlqWZhSLPsp4LJa33e8XsgKYtBIZQLn0KjWCyQcIXshQ aCb8i+3Rcr5Q05uCo8vt9Oe7PF+STcsjJAs89056Bq5VZsdDAr+rjBa7sDzzM4VCDP+/id F3fAIfiNdC0bvmzdW0BDR6Tv6JSN2FdPEvQRZYDO/avLyT/zXI+AEuTYZMYaG2V9C0wdPZ 5Ci9j484CY+G2oMqPvltlgHYgC7cq1KbHkCqhzzu1E/cK/h4aEIhxoJJfunrOEKJ5RnI1q 7RWJnO5pUwS+9Yi3XEM7lE6dyuVLpbU2M3wpYlJgugqRLnx7kfGHuY8JuHKOIg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1739900597; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Ww286Yo2Ryn5Qk7gkfyVQiBG1UgeK5tLiMBOjR+tM8I=; b=bVMBNQzskqncPGpO3kjup3WYUOvPF875KM3ptxllteRXT5kQUGnhD4p6jMYEQ2842xSYon tpIVuUe4lPk3sri8T+y/EmT1A6ILSpXl6oORruFLkQebTTjMnSULxRdiDK1sYd185rra12 Q147V8N+bdiowr069dgcXYyA/cjhMPC4r+sVEiGH7QPnSbBI9sNCDnpLnkKsq93VgDKOIn TUhHx0XDHtJXcWmOZoweOSG/WkMyh4/uZRQNplXEz7n1lBzRyRbFWCc1a4gzyRCkE0dokq I62W9AGNHr6Gy5VjF4UTsLS1GySQrnUTVnHMTdWTRm6YP3lAa0JOGRoz5WdXkA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Yy6Lr72w6zDWL; Tue, 18 Feb 2025 17:43:16 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 51IHhGk7021424; Tue, 18 Feb 2025 17:43:16 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 51IHhGNS021418; Tue, 18 Feb 2025 17:43:16 GMT (envelope-from git) Date: Tue, 18 Feb 2025 17:43:16 GMT Message-Id: <202502181743.51IHhGNS021418@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kristof Provost Subject: git: 5ff91b71bb67 - stable/14 - pf tests: add more fragmentation test cases List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 5ff91b71bb67f4408a2541a13cd270b7370c6766 Auto-Submitted: auto-generated The branch stable/14 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=5ff91b71bb67f4408a2541a13cd270b7370c6766 commit 5ff91b71bb67f4408a2541a13cd270b7370c6766 Author: Kristof Provost AuthorDate: 2025-02-04 13:06:33 +0000 Commit: Kristof Provost CommitDate: 2025-02-18 17:40:26 +0000 pf tests: add more fragmentation test cases Add more test cases for pf fragment hole counter. Also look into final fragment of echo reply and check total length of IP packet. MFC after: 1 week Obtained from: OpenBSD, bluhm , 640736615b Sponsored by: Rubicon Communications, LLC ("Netgate") (cherry picked from commit db100bd93036855c7688dc088b811dc7b660f51d) --- tests/sys/netpfil/pf/Makefile | 4 ++ tests/sys/netpfil/pf/frag-adjhole.py | 58 +++++++++++++++++++++ tests/sys/netpfil/pf/frag-overhole.py | 83 ++++++++++++++++++++++++++++++ tests/sys/netpfil/pf/fragmentation_pass.sh | 38 ++++++++++++++ 4 files changed, 183 insertions(+) diff --git a/tests/sys/netpfil/pf/Makefile b/tests/sys/netpfil/pf/Makefile index dc77fd67b2c6..f2ccd5aa6ec2 100644 --- a/tests/sys/netpfil/pf/Makefile +++ b/tests/sys/netpfil/pf/Makefile @@ -62,6 +62,8 @@ ${PACKAGE}FILES+= CVE-2019-5597.py \ frag-overindex.py \ frag-overlimit.py \ frag-overreplace.py \ + frag-overhole.py \ + frag-adjhole.py \ pfsync_defer.py \ pft_ether.py \ rdr-srcport.py \ @@ -73,6 +75,8 @@ ${PACKAGE}FILESMODE_fragcommon.py= 0555 ${PACKAGE}FILESMODE_frag-overindex.py= 0555 ${PACKAGE}FILESMODE_frag-overlimit.py= 0555 ${PACKAGE}FILESMODE_frag-overreplace.py= 0555 +${PACKAGE}FILESMODE_frag-overhole.py= 0555 +${PACKAGE}FILESMODE_frag-adjhole.py= 0555 ${PACKAGE}FILESMODE_pfsync_defer.py= 0555 ${PACKAGE}FILESMODE_pft_ether.py= 0555 diff --git a/tests/sys/netpfil/pf/frag-adjhole.py b/tests/sys/netpfil/pf/frag-adjhole.py new file mode 100644 index 000000000000..99caf66617dd --- /dev/null +++ b/tests/sys/netpfil/pf/frag-adjhole.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Alexander Bluhm + +from fragcommon import * + +# |--------| +# |--------| +# |-------| +# |----| + +def send(src, dst, send_if, recv_if): + pid = os.getpid() + eid = pid & 0xffff + payload = b"ABCDEFGHIJKLMNOP" * 2 + packet = sp.IP(src=src, dst=dst)/ \ + sp.ICMP(type='echo-request', id=eid) / payload + frag = [] + fid = pid & 0xffff + frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, + flags='MF') / bytes(packet)[20:36]) + frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, + frag=2, flags='MF') / bytes(packet)[36:52]) + frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, + frag=1, flags='MF') / bytes(packet)[28:44]) + frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, + frag=4) / bytes(packet)[52:60]) + eth=[] + for f in frag: + eth.append(sp.Ether()/f) + if os.fork() == 0: + time.sleep(1) + sp.sendp(eth, iface=send_if) + os._exit(0) + + ans = sp.sniff(iface=recv_if, timeout=3, filter= + "ip and src " + dst + " and dst " + src + " and icmp") + for a in ans: + if a and a.type == sp.ETH_P_IP and \ + a.payload.proto == 1 and \ + a.payload.frag == 0 and a.payload.flags == 0 and \ + sp.icmptypes[a.payload.payload.type] == 'echo-reply': + id = a.payload.payload.id + print("id=%#x" % (id)) + if id != eid: + print("WRONG ECHO REPLY ID") + exit(2) + data = a.payload.payload.payload.load + print("payload=%s" % (data)) + if data == payload: + exit(0) + print("PAYLOAD!=%s" % (payload)) + exit(1) + print("NO ECHO REPLY") + exit(2) + +if __name__ == '__main__': + main(send) diff --git a/tests/sys/netpfil/pf/frag-overhole.py b/tests/sys/netpfil/pf/frag-overhole.py new file mode 100644 index 000000000000..91697b6b83c6 --- /dev/null +++ b/tests/sys/netpfil/pf/frag-overhole.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Alexander Bluhm + +from fragcommon import * + +# index boundary 4096 | +# |--------------| +# .... +# |--------------| +# |----------| +# |XXXX----------| +# |XXXX----| +# |---| + +# this should trigger "frag tail overlap %d" and "frag head overlap %d" +def send(src, dst, send_if, recv_if): + pid = os.getpid() + eid = pid & 0xffff + payload = b"ABCDEFGHIJKLMNOP" + dummy = b"01234567" + fragsize = 1024 + boundary = 4096 + fragnum = int(boundary / fragsize) + packet = sp.IP(src=src, dst=dst)/ \ + sp.ICMP(type='echo-request', id=eid)/ \ + ((int((boundary + fragsize) / len(payload)) + 1) * payload) + packet_length = len(packet) + frag = [] + fid = pid & 0xffff + for i in range(fragnum-1): + frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, + frag=(i * fragsize)>>3, flags='MF')/ + bytes(packet)[20 + i * fragsize:20 + (i + 1) * fragsize]) + frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, + frag=(boundary - fragsize) >> 3, flags='MF')/ + bytes(packet)[20 + boundary - fragsize:20 + boundary - len(dummy)]) + frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, + frag=(boundary - len(dummy)) >> 3, flags='MF')/ + (dummy+bytes(packet)[20 + boundary:20 + boundary + fragsize])) + frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, + frag=(boundary - 8 - len(dummy)) >> 3, flags='MF')/ + (dummy+bytes(packet)[20 + boundary - 8:20 + boundary])) + frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, + frag=(boundary + fragsize) >> 3)/bytes(packet)[20 + boundary + fragsize:]) + eth=[] + for f in frag: + eth.append(sp.Ether() / f) + + if os.fork() == 0: + time.sleep(1) + for e in eth: + sp.sendp(e, iface=send_if) + time.sleep(0.001) + os._exit(0) + + ans = sp.sniff(iface=recv_if, timeout=3, filter= + "ip and src " + dst + " and dst " + src + " and icmp") + for a in ans: + if a and a.type == sp.ETH_P_IP and \ + a.payload.proto == 1 and \ + a.payload.frag == 0 and \ + sp.icmptypes[a.payload.payload.type] == 'echo-reply': + id = a.payload.payload.id + print("id=%#x" % (id)) + if id != eid: + print("WRONG ECHO REPLY ID") + exit(2) + if a and a.type == sp.ETH_P_IP and \ + a.payload.proto == 1 and \ + a.payload.frag > 0 and \ + a.payload.flags == '': + length = (a.payload.frag << 3) + a.payload.len + print("len=%d" % (length)) + if length != packet_length: + print("WRONG ECHO REPLY LENGTH") + exit(1) + exit(0) + print("NO ECHO REPLY") + exit(1) + +if __name__ == '__main__': + main(send) diff --git a/tests/sys/netpfil/pf/fragmentation_pass.sh b/tests/sys/netpfil/pf/fragmentation_pass.sh index 5e92bb2d9a97..66fe336dff34 100644 --- a/tests/sys/netpfil/pf/fragmentation_pass.sh +++ b/tests/sys/netpfil/pf/fragmentation_pass.sh @@ -285,6 +285,42 @@ overlimit_cleanup() pft_cleanup } +atf_test_case "overhole" "cleanup" +overhole_head() +{ + atf_set descr 'ping fragment at index boundary which modifies pf hole counter' + atf_set require.user root + atf_set require.progs scapy +} + +overhole_body() +{ + frag_common overhole +} + +overhole_cleanup() +{ + pft_cleanup +} + +atf_test_case "adjhole" "cleanup" +adjhole_head() +{ + atf_set descr 'overlapping ping fragments which modifies pf hole counter' + atf_set require.user root + atf_set require.progs scapy +} + +adjhole_body() +{ + frag_common adjhole +} + +adjhole_cleanup() +{ + pft_cleanup +} + atf_test_case "reassemble" "cleanup" reassemble_head() { @@ -476,6 +512,8 @@ atf_init_test_cases() atf_add_test_case "overreplace" atf_add_test_case "overindex" atf_add_test_case "overlimit" + atf_add_test_case "overhole" + atf_add_test_case "adjhole" atf_add_test_case "reassemble" atf_add_test_case "no_df" atf_add_test_case "reassemble_slowpath"