Created attachment 270522 [details] tickle a bug in nl_get_attrs_bmask_raw() This code in netlink_message_parser.h will pass a negative len to nl_get_attrs_bmask_raw() if hdr->nlmsg_len is 31 and it is called from rtnl_handle_newlink() with ifmsg_parser, whose nl_hdr_off is 16. static inline void nl_get_attrs_bmask_nlmsg(struct nlmsghdr *hdr, const struct nlhdr_parser *parser, struct nlattr_bmask *bm) { nl_get_attrs_bmask_raw( (struct nlattr *)((char *)(hdr + 1) + parser->nl_hdr_off), hdr->nlmsg_len - sizeof(*hdr) - parser->nl_hdr_off, bm); } But nl_get_attrs_bmask_raw()'s len argument is declared unsigned, and will in this case be huge, so that this loop can run too many times: NLA_FOREACH(nla, nla_head, len) { I've attached a demo program. # uname -a FreeBSD xxx 16.0-CURRENT FreeBSD 16.0-CURRENT #35 main-n275527-1a9c5d7499c3: Fri May 8 13:21:19 AST 2026 root@xxx:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64 # cc netlink7b.c # ./a.out panic: vm_fault_lookup: fault on nofault entry, addr: 0xfffffe0123b05000 cpuid = 8 time = 1778265196 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00d7216700 vpanic() at vpanic+0x149/frame 0xfffffe00d7216830 panic() at panic+0x43/frame 0xfffffe00d7216890 vm_fault() at vm_fault+0x1c1a/frame 0xfffffe00d7216a10 vm_fault_trap() at vm_fault_trap+0x65/frame 0xfffffe00d7216a50 trap_pfault() at trap_pfault+0x275/frame 0xfffffe00d7216ac0 calltrap() at calltrap+0x8/frame 0xfffffe00d7216ac0 --- trap 0xc, rip = 0xffffffff80eab391, rsp = 0xfffffe00d7216b90, rbp = 0xfffffe00d7216bb0 --- nl_get_attrs_bmask_raw() at nl_get_attrs_bmask_raw+0x51/frame 0xfffffe00d7216bb0 rtnl_handle_newlink() at rtnl_handle_newlink+0xb3/frame 0xfffffe00d7216ca0 rtnl_handle_message() at rtnl_handle_message+0x195/frame 0xfffffe00d7216d00 nl_receive_message() at nl_receive_message+0x11c/frame 0xfffffe00d7216d40 nl_taskqueue_handler() at nl_taskqueue_handler+0x3f5/frame 0xfffffe00d7216e40 taskqueue_run_locked() at taskqueue_run_locked+0x1ce/frame 0xfffffe00d7216ec0 taskqueue_thread_loop() at taskqueue_thread_loop+0xd3/frame 0xfffffe00d7216ef0 fork_exit() at fork_exit+0x82/frame 0xfffffe00d7216f30 fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe00d7216f30 --- trap 0, rip = 0, rsp = 0, rbp = 0 --- KDB: enter: panic
Thanks for submission! Wasn't able to reproduce a crash, but indeed there is unsigned underflow here.
Created https://reviews.freebsd.org/D56916. The https://reviews.freebsd.org/D56915 was also inspired by this report.
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=e924a2c80b9e1ace68d8ca0ffdacec65feec90a3 commit e924a2c80b9e1ace68d8ca0ffdacec65feec90a3 Author: Gleb Smirnoff <glebius@FreeBSD.org> AuthorDate: 2026-05-20 14:27:52 +0000 Commit: Gleb Smirnoff <glebius@FreeBSD.org> CommitDate: 2026-05-20 14:27:52 +0000 netlink: fix unsigned overflow on a truncated message PR: 295106 Submitted by: Robert Morris <rtm@lcs.mit.edu> Reviewed by: pouria, melifaro Differential Revision: https://reviews.freebsd.org/D56916 sys/netlink/netlink_message_parser.h | 6 ++++++ 1 file changed, 6 insertions(+)