User code can cause the kernel pf netlink code to write beyond the bounds of stack-allocated objects due to the way that pf_nl.c's nested_table_parser is used. nested_table_parser is willing to let user-supplied netlink commands cause writes to pfioc_table.pfrio_flags: #define _OUT(_field) offsetof(struct pfioc_table, _field) static const struct nlattr_parser nla_p_table[] = { ..., { .type = PF_T_FLAGS, .off = _OUT(pfrio_flags), .cb = nlattr_get_uint32 }, }; ... NL_DECLARE_ATTR_PARSER(nested_table_parser, nla_p_table); But then nested_table_parser is used in contexts where the target is not a pfioc_table, for example in table_astats_parser: #define _OUT(_field) offsetof(struct nl_parsed_table_astats, _field) static const struct nlattr_parser nla_p_table_astats[] = { { .type = PF_TAS_TABLE, .off = _OUT(table), .arg = &nested_table_parser, .cb = nlattr_get_nested }, }; NL_DECLARE_PARSER(table_astats_parser, struct genlmsghdr, nlf_p_empty, nla_p_table_astats); In this example, pf_handle_table_get_astats() parses into a struct nl_parsed_table_astats. This struct has size 1068, but the nested_table_parser is willing to write "pfrio_flags" at offset 1096. This writes somewhere bad on the stack. One possible fix is that nla_p_table should be used only in table_parser, and not also in nested_table_parser; instead, a separate nlattr_parser should be declared for nested_table_parser, omitting the PF_T_FLAGS.
Thanks for the report. Iām currently on vacation but will investigate this sometime next week.
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=64327f769cee0c26e1b81e6195a5092498b10403 commit 64327f769cee0c26e1b81e6195a5092498b10403 Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2026-05-21 08:13:24 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2026-05-21 21:19:49 +0000 pf: fix incorrect table decoding in netlink We used nla_p_table for pfr_table structures, but this netlink decoder was intended for pfioc_table and decoded an extra field, outside of pfr_table. This allowed userspace to write (slightly) outside of pfr_table. Use a separate nlattr_parser for pfr_table. PR: 295218 Reported by: Robert Morris <rtm@lcs.mit.edu> MFC after: 1 week Sponsored by: Rubicon Communications, LLC ("Netgate") sys/netpfil/pf/pf_nl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
A commit in branch stable/15 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=45aaba521c3b7abd39dc9e8f5ed0e9521fee57c3 commit 45aaba521c3b7abd39dc9e8f5ed0e9521fee57c3 Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2026-05-21 08:13:24 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2026-05-28 11:36:43 +0000 pf: fix incorrect table decoding in netlink We used nla_p_table for pfr_table structures, but this netlink decoder was intended for pfioc_table and decoded an extra field, outside of pfr_table. This allowed userspace to write (slightly) outside of pfr_table. Use a separate nlattr_parser for pfr_table. PR: 295218 Reported by: Robert Morris <rtm@lcs.mit.edu> MFC after: 1 week Sponsored by: Rubicon Communications, LLC ("Netgate") (cherry picked from commit 64327f769cee0c26e1b81e6195a5092498b10403) sys/netpfil/pf/pf_nl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)