Page MenuHomeFreeBSD

D59333.id.diff
No OneTemporary

D59333.id.diff

diff --git a/tests/sys/netpfil/pf/Makefile b/tests/sys/netpfil/pf/Makefile
--- a/tests/sys/netpfil/pf/Makefile
+++ b/tests/sys/netpfil/pf/Makefile
@@ -5,6 +5,7 @@
ATF_TESTS_SH+= altq \
anchor \
+ bridge \
counters \
debug \
divert-to \
diff --git a/tests/sys/netpfil/pf/bridge.sh b/tests/sys/netpfil/pf/bridge.sh
new file mode 100644
--- /dev/null
+++ b/tests/sys/netpfil/pf/bridge.sh
@@ -0,0 +1,173 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2026 Alexander Leidinger <netchild@FreeBSD.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+. $(atf_get_srcdir)/utils.subr
+
+helper=$(atf_get_srcdir)/../../common/sendfile_helper
+
+# Build "sender -- bridge -- receiver", each in its own vnet, with pf
+# filtering the bridged path.
+#
+# Two preconditions decide whether this exercises anything at all:
+#
+# vnet_mkepair() clears IFCAP_MEXTPG. Without it sendfile(2) hands the
+# bridge only mapped mbufs, and every assertion below holds on a kernel
+# that cannot handle the unmapped ones.
+#
+# bridge_pfil() pulls up min(m_pkthdr.len, max_protohdr) bytes. The mapped
+# head of a sendfile(2) segment is ether + IPv4 + TCP, which reaches
+# max_protohdr (60) once TCP options are present; only without them is it
+# 54 and the pullup crosses into the payload.
+bridge_setup()
+{
+ epair_snd=$(vnet_mkepair)
+ epair_rcv=$(vnet_mkepair)
+ bridge=$(vnet_mkbridge)
+
+ for iface in ${epair_snd}a ${epair_snd}b ${epair_rcv}a ${epair_rcv}b; do
+ ifconfig ${iface} mextpg
+ ifconfig ${iface} | grep -q MEXTPG ||
+ atf_fail "MEXTPG unavailable on ${iface}"
+ done
+
+ vnet_mkjail br ${bridge} ${epair_snd}a ${epair_rcv}a
+ vnet_mkjail snd ${epair_snd}b
+ vnet_mkjail rcv ${epair_rcv}b
+
+ jexec br ifconfig ${epair_snd}a up
+ jexec br ifconfig ${epair_rcv}a up
+ jexec br ifconfig ${bridge} addm ${epair_snd}a addm ${epair_rcv}a up
+
+ # CTLFLAG_VNET, so this stays inside the jail.
+ atf_check -s exit:0 -o ignore \
+ jexec br sysctl net.link.bridge.pfil_member=1
+
+ jexec snd ifconfig ${epair_snd}b 192.0.2.1/24 up
+ jexec rcv ifconfig ${epair_rcv}b 192.0.2.2/24 up
+ jexec snd sysctl -q net.inet.tcp.rfc1323=0
+ jexec rcv sysctl -q net.inet.tcp.rfc1323=0
+
+ dd if=/dev/random of=payload bs=1m count=8 status=none
+ payload=$(pwd)/payload
+ size=$(stat -f %z ${payload})
+}
+
+# Send the payload and leave what arrived in $1.
+bridge_sendfile()
+{
+ out=$1
+
+ jexec rcv nc -l 5555 > ${out} &
+ receiver=$!
+ sleep 1
+ timeout 60 jexec snd ${helper} -c 192.0.2.2 -p 5555 ${payload} 0 ${size} 0
+ status=$?
+
+ i=0
+ while [ ${i} -lt 10 ] && kill -0 ${receiver} 2>/dev/null; do
+ sleep 1
+ i=$((i + 1))
+ done
+ kill ${receiver} 2>/dev/null
+ wait ${receiver} 2>/dev/null
+ return ${status}
+}
+
+# Guard against the test quietly doing nothing: if pf is not enabled, or if
+# it never saw the bridged frames, the transfer says nothing about the
+# filtered path.
+bridge_assert_filtered()
+{
+ jexec br pfctl -si | grep -q '^Status: Enabled' ||
+ atf_fail "pf is not enabled in the bridge jail"
+
+ pkts=$(jexec br pfctl -vsr |
+ awk '{ for (i = 1; i <= NF; i++)
+ if ($i == "Packets:") { print $(i + 1); exit } }')
+ [ "${pkts:-0}" -gt 0 ] ||
+ atf_fail "pf saw no packets on the bridged path"
+}
+
+atf_test_case "unmapped" "cleanup"
+unmapped_head()
+{
+ atf_set descr 'Bridged unmapped mbufs survive pf filtering'
+ atf_set require.user root
+}
+
+unmapped_body()
+{
+ pft_init
+ vnet_init_bridge
+ bridge_setup
+
+ pft_set_rules br "pass all"
+ jexec br pfctl -e
+
+ bridge_sendfile received ||
+ atf_fail "sendfile across the filtered bridge failed"
+ atf_check -s exit:0 cmp ${payload} received
+ bridge_assert_filtered
+}
+
+unmapped_cleanup()
+{
+ pft_cleanup
+}
+
+atf_test_case "unmapped_block" "cleanup"
+unmapped_block_head()
+{
+ atf_set descr 'pf blocks a bridged unmapped transfer when told to'
+ atf_set require.user root
+}
+
+unmapped_block_body()
+{
+ pft_init
+ vnet_init_bridge
+ bridge_setup
+
+ pft_set_rules br "block drop quick proto tcp to port 5555" "pass all"
+ jexec br pfctl -e
+
+ if bridge_sendfile blocked; then
+ atf_fail "transfer succeeded although pf blocks the port"
+ fi
+ [ ! -s blocked ] || atf_fail "payload arrived although pf blocks the port"
+ bridge_assert_filtered
+}
+
+unmapped_block_cleanup()
+{
+ pft_cleanup
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case "unmapped"
+ atf_add_test_case "unmapped_block"
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Sep 4, 1:41 PM (19 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38216336
Default Alt Text
D59333.id.diff (5 KB)

Event Timeline