From nobody Mon Nov 20 13:04:27 2023 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 4SYnlc0p49z51G5n; Mon, 20 Nov 2023 13:04:28 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4SYnlc0CJZz3cX2; Mon, 20 Nov 2023 13:04:28 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1700485468; 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=TGZSevQ2ea9wN0t7XbZaldk8SBczi8RLGRzmgZHwnwY=; b=VN3HvVfhdAw9dxqSuCa5I9pj6V9GNUmYW2zbHTFogw5aFq8VtDiIY1byT7kWQ75vtCEuWm 9uqduzJyC7YcUyb1X4TACzKUl+WF6dQK7Q4n9Sd2/zcBUkzAU4cTRvtPd038K631quS5pX EAs/zxZVia1n9RFlkHc70wUnm0uzHAXYVO4Rv9fTaKR9QD8jmHlMIXWewAMRb2vNcSQMOV 59kDI5n8p1BKPYm+YGoVGFD1YfFmHCAWL8XRnL/bSCvBMay9uZtDan3Jy+7RefgOtKzjqZ htf8X+0vaGQizdCN2bsxrrXN4xo4ep03DSAmRixHOeajkWXR8Dp9seIl9LW3kQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1700485468; 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=TGZSevQ2ea9wN0t7XbZaldk8SBczi8RLGRzmgZHwnwY=; b=p54a5Z5gfZXSsSIvoVqzqej4Eje1r3Fcf7HKjGLraL5GQcCDEFVgdYBjc1SNfi9WlrEr/X 5nH6j/3Q/vDxXz7f5z/MikdMwf1bRb0RKKdcormyhTsTjMPNOdZsajE80aEJHmqGrn5zC3 B2+aKlH2he/3HdruNHUarK4gE3+9hSx1sF9V6/JW8ixXOAXliksB90MfLLKR8cvSl4yCm7 UO11f/wqQEbV5yhPH5bZoM2yAgp5XmtWCWjB/qWbYZjJLcd0su4UzGIhzJlapACXYzXc2p ioGovuLbxUvv+fh/Gp1Xeb2y59hb2j9SAht8vkiCsCbzhgA5jrvO3oFLguR2yg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1700485468; a=rsa-sha256; cv=none; b=gAnmHxrp3veXRLETafPUf1WW5azlrb5Q74R0+y1zlpEZQCpPPWVisBkEUW1TDy9FWERxzV v5JrUITpOncV1lyF1xS0cxChmwQ2L6W7oZp9yV0e/Roh9VV3Ii56nnYu/274vlAcx0w1Sz bz2IjrxUN1T5WpG+lU5EwJdUtaeO7uXElaUAoEY4y+8T8rqwMig2WdudMNoJFVVh8CRmkV qnvddD6KvbfX23OyYRIXuWkBg2VjRotd65J/DMXlsuZ+ZQYZLj7VzZeVHaWFnfzBwZb1nJ FfSivfQ2SriHV5H9UXI+Pq4rc1Z3TZIyENbKwFxrp4m6Ves6DAREgLnotEBkkQ== 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 4SYnlb6L39ztBx; Mon, 20 Nov 2023 13:04:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 3AKD4RZM089639; Mon, 20 Nov 2023 13:04:27 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 3AKD4RjV089636; Mon, 20 Nov 2023 13:04:27 GMT (envelope-from git) Date: Mon, 20 Nov 2023 13:04:27 GMT Message-Id: <202311201304.3AKD4RjV089636@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: f831517d862d - stable/14 - pf: fix dummynet + ipdivert use case 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: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: 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: f831517d862dac2df3110c569b44e8417c3f0afa Auto-Submitted: auto-generated The branch stable/14 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=f831517d862dac2df3110c569b44e8417c3f0afa commit f831517d862dac2df3110c569b44e8417c3f0afa Author: Igor Ostapenko AuthorDate: 2023-11-17 16:04:01 +0000 Commit: Kristof Provost CommitDate: 2023-11-20 10:30:19 +0000 pf: fix dummynet + ipdivert use case Dummynet re-injects an mbuf with MTAG_IPFW_RULE added, and the same mtag is used by divert(4) as parameters for packet diversion. If according to pf rule set a packet should go through dummynet first and through ipdivert after then mentioned mtag must be removed after dummynet not to make ipdivert think that this is its input parameters. At the very beginning ipfw consumes this mtag what means the same behavior with tag clearing after dummynet. And after fabf705f4b5a pf passes parameters to ipdivert using its personal MTAG_PF_DIVERT mtag. PR: 274850 Reviewed by: kp Differential Revision: https://reviews.freebsd.org/D42609 (cherry picked from commit fe3bb40b9e807d4010617de1ef040ba3aa623487) --- sys/netpfil/pf/pf.c | 27 +++++++-- tests/sys/netpfil/pf/divert-to.sh | 118 +++++++++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 6 deletions(-) diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 6e6b0b20130d..9cb5fe03b5c2 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -303,6 +303,8 @@ static int pf_state_key_attach(struct pf_state_key *, static void pf_state_key_detach(struct pf_kstate *, int); static int pf_state_key_ctor(void *, int, void *, int); static u_int32_t pf_tcp_iss(struct pf_pdesc *); +static __inline void pf_dummynet_flag_remove(struct mbuf *m, + struct pf_mtag *pf_mtag); static int pf_dummynet(struct pf_pdesc *, struct pf_kstate *, struct pf_krule *, struct mbuf **); static int pf_dummynet_route(struct pf_pdesc *, @@ -4140,7 +4142,7 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) /* But only once. We may see the packet multiple times (e.g. * PFIL_IN/PFIL_OUT). */ - mtag->flags &= ~PF_MTAG_FLAG_DUMMYNET; + pf_dummynet_flag_remove(m, mtag); return (PF_PASS); } @@ -4361,7 +4363,7 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) mtag->flags |= PF_MTAG_FLAG_DUMMYNET; ip_dn_io_ptr(m0, &dnflow); if (*m0 != NULL) - mtag->flags &= ~PF_MTAG_FLAG_DUMMYNET; + pf_dummynet_flag_remove(m, mtag); } else { PF_RULES_RUNLOCK(); } @@ -7794,6 +7796,21 @@ pf_test_eth(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, return (pf_test_eth_rule(dir, kif, m0)); } +static __inline void +pf_dummynet_flag_remove(struct mbuf *m, struct pf_mtag *pf_mtag) +{ + struct m_tag *mtag; + + pf_mtag->flags &= ~PF_MTAG_FLAG_DUMMYNET; + + /* dummynet adds this tag, but pf does not need it, + * and keeping it creates unexpected behavior, + * e.g. in case of divert(4) usage right after dummynet. */ + mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL); + if (mtag != NULL) + m_tag_delete(m, mtag); +} + static int pf_dummynet(struct pf_pdesc *pd, struct pf_kstate *s, struct pf_krule *r, struct mbuf **m0) @@ -7844,7 +7861,7 @@ pf_dummynet_route(struct pf_pdesc *pd, struct pf_kstate *s, ip_dn_io_ptr(m0, &dnflow); if (*m0 != NULL) { pd->pf_mtag->flags &= ~PF_MTAG_FLAG_ROUTE_TO; - pd->pf_mtag->flags &= ~PF_MTAG_FLAG_DUMMYNET; + pf_dummynet_flag_remove(*m0, pd->pf_mtag); } } } @@ -7933,7 +7950,7 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, /* But only once. We may see the packet multiple times (e.g. * PFIL_IN/PFIL_OUT). */ - pd.pf_mtag->flags &= ~PF_MTAG_FLAG_DUMMYNET; + pf_dummynet_flag_remove(m, pd.pf_mtag); PF_RULES_RUNLOCK(); return (PF_PASS); @@ -8494,7 +8511,7 @@ pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb if (ip_dn_io_ptr != NULL && pd.pf_mtag != NULL && pd.pf_mtag->flags & PF_MTAG_FLAG_DUMMYNET) { - pd.pf_mtag->flags &= ~PF_MTAG_FLAG_DUMMYNET; + pf_dummynet_flag_remove(m, pd.pf_mtag); /* Dummynet re-injects packets after they've * completed their delay. We've already * processed them, so pass unconditionally. */ diff --git a/tests/sys/netpfil/pf/divert-to.sh b/tests/sys/netpfil/pf/divert-to.sh index 0a37cea78ad3..965464b35810 100644 --- a/tests/sys/netpfil/pf/divert-to.sh +++ b/tests/sys/netpfil/pf/divert-to.sh @@ -51,11 +51,13 @@ # > outbound > diverted > outbound | network terminated # # Test case naming legend: +# ipfwon - with ipfw enabled +# ipfwoff - with ipfw disabled # in - inbound # div - diverted # out - outbound # fwd - forwarded -# ipfwon - with ipfw enabled, which allows all +# dn - delayed by dummynet # . $(atf_get_srcdir)/utils.subr @@ -67,6 +69,13 @@ divert_init() fi } +dummynet_init() +{ + if ! kldstat -q -m dummynet; then + atf_skip "This test requires dummynet" + fi +} + ipfw_init() { if ! kldstat -q -m ipfw; then @@ -396,6 +405,110 @@ ipfwon_in_div_in_fwd_out_div_out_cleanup() pft_cleanup } +atf_test_case "ipfwoff_in_dn_in_div_in_out_dn_out_div_out" "cleanup" +ipfwoff_in_dn_in_div_in_out_dn_out_div_out_head() +{ + atf_set descr 'Test inbound > delayed+diverted > outbound > delayed+diverted > outbound | network terminated' + atf_set require.user root +} +ipfwoff_in_dn_in_div_in_out_dn_out_div_out_body() +{ + local ipfwon + + pft_init + divert_init + dummynet_init + test "$1" == "ipfwon" && ipfwon="yes" + test $ipfwon && ipfw_init || assert_ipfw_is_off + + epair=$(vnet_mkepair) + vnet_mkjail alcatraz ${epair}b + ifconfig ${epair}a 192.0.2.1/24 up + ifconfig ${epair}a ether 02:00:00:00:00:01 + jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up + test $ipfwon && jexec alcatraz ipfw add 65534 allow all from any to any + + # Sanity check + atf_check -s exit:0 -o ignore ping -c3 192.0.2.2 + + # a) ping should time out due to very narrow dummynet pipes { + + jexec alcatraz dnctl pipe 1001 config bw 1Byte/s + jexec alcatraz dnctl pipe 1002 config bw 1Byte/s + + jexec alcatraz pfctl -e + pft_set_rules alcatraz \ + "ether pass in from 02:00:00:00:00:01 l3 all dnpipe 1001" \ + "ether pass out to 02:00:00:00:00:01 l3 all dnpipe 1002 " \ + "pass all" \ + "pass in inet proto icmp icmp-type echoreq divert-to 127.0.0.1 port 1001 no state" \ + "pass out inet proto icmp icmp-type echorep divert-to 127.0.0.1 port 1002 no state" + + jexec alcatraz $(atf_get_srcdir)/divapp 1001 divert-back & + indivapp_pid=$! + jexec alcatraz $(atf_get_srcdir)/divapp 1002 divert-back & + outdivapp_pid=$! + # Wait for the divappS to be ready + sleep 1 + + atf_check -s not-exit:0 -o ignore ping -c1 -s56 -t1 192.0.2.2 + + wait $indivapp_pid + atf_check_not_equal 0 $? + wait $outdivapp_pid + atf_check_not_equal 0 $? + + # } + + # b) ping should NOT time out due to wide enough dummynet pipes { + + jexec alcatraz dnctl pipe 2001 config bw 100KByte/s + jexec alcatraz dnctl pipe 2002 config bw 100KByte/s + + jexec alcatraz pfctl -e + pft_set_rules alcatraz \ + "ether pass in from 02:00:00:00:00:01 l3 all dnpipe 2001" \ + "ether pass out to 02:00:00:00:00:01 l3 all dnpipe 2002 " \ + "pass all" \ + "pass in inet proto icmp icmp-type echoreq divert-to 127.0.0.1 port 2001 no state" \ + "pass out inet proto icmp icmp-type echorep divert-to 127.0.0.1 port 2002 no state" + + jexec alcatraz $(atf_get_srcdir)/divapp 2001 divert-back & + indivapp_pid=$! + jexec alcatraz $(atf_get_srcdir)/divapp 2002 divert-back & + outdivapp_pid=$! + # Wait for the divappS to be ready + sleep 1 + + atf_check -s exit:0 -o ignore ping -c1 -s56 -t1 192.0.2.2 + + wait $indivapp_pid + atf_check_equal 0 $? + wait $outdivapp_pid + atf_check_equal 0 $? + + # } +} +ipfwoff_in_dn_in_div_in_out_dn_out_div_out_cleanup() +{ + pft_cleanup +} + +atf_test_case "ipfwon_in_dn_in_div_in_out_dn_out_div_out" "cleanup" +ipfwon_in_dn_in_div_in_out_dn_out_div_out_head() +{ + atf_set descr 'Test inbound > delayed+diverted > outbound > delayed+diverted > outbound | network terminated, with ipfw enabled' + atf_set require.user root +} +ipfwon_in_dn_in_div_in_out_dn_out_div_out_body() +{ + ipfwoff_in_dn_in_div_in_out_dn_out_div_out_body "ipfwon" +} +ipfwon_in_dn_in_div_in_out_dn_out_div_out_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "ipfwoff_in_div" @@ -410,4 +523,7 @@ atf_init_test_cases() atf_add_test_case "ipfwoff_in_div_in_fwd_out_div_out" atf_add_test_case "ipfwon_in_div_in_fwd_out_div_out" + + atf_add_test_case "ipfwoff_in_dn_in_div_in_out_dn_out_div_out" + atf_add_test_case "ipfwon_in_dn_in_div_in_out_dn_out_div_out" }