Page MenuHomeFreeBSD

D60104.id187917.diff
No OneTemporary

D60104.id187917.diff

diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c
--- a/sys/netpfil/pf/pf_nl.c
+++ b/sys/netpfil/pf/pf_nl.c
@@ -847,7 +847,7 @@
error = nl_parse_nlmsg(hdr, &addrule_parser, npt, &attrs);
if (error != 0) {
- pf_free_rule(attrs.rule);
+ pf_krule_free(attrs.rule);
return (error);
}
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
@@ -60,6 +60,7 @@
tos \
unmapped_mbuf
+ATF_TESTS_PYTEST+= addrule.py
ATF_TESTS_PYTEST+= frag4.py
ATF_TESTS_PYTEST+= frag6.py
ATF_TESTS_PYTEST+= header.py
diff --git a/tests/sys/netpfil/pf/addrule.py b/tests/sys/netpfil/pf/addrule.py
new file mode 100644
--- /dev/null
+++ b/tests/sys/netpfil/pf/addrule.py
@@ -0,0 +1,100 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2026 Rubicon Communications, LLC (Netgate)
+#
+# 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.
+
+import errno
+
+import pytest
+from atf_python.sys.net.vnet import SingleVnetTestTemplate
+from atf_python.sys.netlink.attrs import NlAttrNested
+from atf_python.sys.netlink.attrs import NlAttrStr
+from atf_python.sys.netlink.attrs import NlAttrU32
+from atf_python.sys.netlink.attrs import NlAttrU8
+from atf_python.sys.netlink.base_headers import NlmBaseFlags
+from atf_python.sys.netlink.base_headers import NlMsgType
+from atf_python.sys.netlink.netlink import NetlinkTestTemplate
+from atf_python.sys.netlink.netlink_generic import NetlinkGenlMessage
+from atf_python.sys.netlink.utils import NlConst
+
+# sys/netpfil/pf/pf_nl.h
+PFNL_FAMILY_NAME = "pfctl"
+PFNL_CMD_ADDRULE = 5
+PF_ART_TICKET = 1
+PF_ART_RULE = 5
+PF_RT_SRC = 1
+PF_RT_IFNAME = 5
+PF_RAT_ADDR = 1
+PF_AT_TYPE = 5
+
+# sys/netpfil/pf/pf.h
+PF_ADDR_TABLE = 3
+
+
+class PfGenlMessage(NetlinkGenlMessage):
+ family_name = PFNL_FAMILY_NAME
+
+
+class TestAddrule(NetlinkTestTemplate, SingleVnetTestTemplate):
+ REQUIRED_MODULES = ["pf"]
+
+ def setup_method(self, method):
+ super().setup_method(method)
+ self.setup_netlink(NlConst.NETLINK_GENERIC)
+
+ @pytest.mark.parametrize(
+ "src_table",
+ [
+ pytest.param(False, id="ifname"),
+ pytest.param(True, id="table_ifname"),
+ ],
+ )
+ def test_parse_error(self, src_table):
+ """A rule that fails to parse is freed without harm"""
+ family_id = self.nlsock.get_genl_family_id(PFNL_FAMILY_NAME)
+
+ rule = []
+ if src_table:
+ # The rule is freed with this much filled in: a table
+ # address with no table attached.
+ rule.append(NlAttrNested(PF_RT_SRC, [
+ NlAttrNested(PF_RAT_ADDR, [
+ NlAttrU8(PF_AT_TYPE, PF_ADDR_TABLE),
+ ]),
+ ]))
+ # Longer than IFNAMSIZ, so the parse fails here.
+ rule.append(NlAttrStr(PF_RT_IFNAME, "x" * 63))
+
+ msg = PfGenlMessage(self.helper, family_id, PFNL_CMD_ADDRULE)
+ msg.nl_hdr.nlmsg_flags = (
+ NlmBaseFlags.NLM_F_ACK.value | NlmBaseFlags.NLM_F_REQUEST.value
+ )
+ msg.add_nla(NlAttrU32(PF_ART_TICKET, 0))
+ msg.add_nla(NlAttrNested(PF_ART_RULE, rule))
+
+ # This used to panic: the rule was freed with pf_free_rule(),
+ # which wants the rules lock and detaches the table.
+ rx_msg = self.get_reply(msg)
+ assert rx_msg.is_type(NlMsgType.NLMSG_ERROR)
+ assert rx_msg.error_code == errno.EINVAL

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 2, 4:41 AM (19 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40001334
Default Alt Text
D60104.id187917.diff (4 KB)

Event Timeline