[Bug 283797] netlink's npt_clear() should set npt->cookie = 0

From: <bugzilla-noreply_at_freebsd.org>
Date: Thu, 02 Jan 2025 16:31:37 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=283797

            Bug ID: 283797
           Summary: netlink's npt_clear() should set npt->cookie = 0
           Product: Base System
           Version: Unspecified
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: rtm@lcs.mit.edu
 Attachment #256345 text/plain
         mime type:

Created attachment 256345
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=256345&action=edit
demonstrate a bug in netlink's npt_clear()

npt_clear() in sys/netlink/netlink_io.c zeroes npt->lb, but leaves
npt->cookie unchanged. Since npt->cookie (if non-NULL) points into
npt->lb, this means that npt_clear() can leave a non-NULL npt->cookie
pointing to zeroed contents.

As a result, if nl_process_nbuf() takes more than one trip through its
for loop, on the second &c trip npt->cookie can be non-NULL even
though npt->cookie->nla_len is zero. This can cause nlmsg_ack()'s call
to nlattr_add_raw(nw, npt->cookie) to execute

        return (nlattr_add(nw, nla_src->nla_type,
            nla_src->nla_len - sizeof(struct nlattr),
            (const void *)(nla_src + 1)));

which (since nla_src->nla_len is zero) will pass attr_len=65532 to
nlattr_add.

With an INVARIANTS kernel, this will cause an MPASS() or KASSERT()
failure. On an ordinary kernel, it will cause nlattr_add() to memcpy
off the end of the allocated nw->buf.

I've attached a demo.

# uname -a
FreeBSD  15.0-CURRENT FreeBSD 15.0-CURRENT #335
main-n250995-3750873316a1-dirty: Thu Jan  2 11:25:30 EST 2025    
rtm@xxx:/usr/obj/usr/rtm/symbsd/src/riscv.riscv64/sys/RTM riscv
# cc netlink4c.c
# ./a.out
tap0: Ethernet address: da:2e:d7:ce:2d:57
tap0: promiscuous mode enabled
REDZONE: Buffer overflow detected. 16 bytes corrupted after 0xffffffc09e011020
(65568 bytes allocated).
Allocation backtrace:
#0 0xffffffc000617370 at redzone_setup+0xa0
#1 0xffffffc0002d4da8 at malloc_large+0x90
#2 0xffffffc0002d4bc4 at malloc+0x120
#3 0xffffffc00052bad4 at nl_buf_alloc+0x2a
#4 0xffffffc00052ca02 at _nlmsg_refill_buffer+0xb2
#5 0xffffffc00052d11e at nlmsg_ack+0x3a6
#6 0xffffffc00052bfca at nl_taskqueue_handler+0x32a
#7 0xffffffc000357070 at taskqueue_run_locked+0x158
#8 0xffffffc000357d74 at taskqueue_thread_loop+0xd4
#9 0xffffffc0002ba19c at fork_exit+0x68
#10 0xffffffc0006785ea at fork_trampoline+0xa
Free backtrace:
#0 0xffffffc00061773a at redzone_check+0x344
#1 0xffffffc0002d5bac at free_dbg+0x5c
#2 0xffffffc0002d4976 at free+0x1c
#3 0xffffffc00052bb1c at nl_buf_free+0x14
#4 0xffffffc00052a85c at nl_close+0x1ca
#5 0xffffffc00038e438 at soclose+0xba
#6 0xffffffc00036cd88 at soo_close+0x20
#7 0xffffffc0002a1f8e at _fdrop+0x16
#8 0xffffffc0002a55d8 at closef+0x1b0
#9 0xffffffc0002a4ca4 at fdescfree+0x4ea
#10 0xffffffc0002b55bc at exit1+0x40a
#11 0xffffffc0002b51ae at sys_exit+0x10
#12 0xffffffc00067913a at do_trap_user+0x1e0
#13 0xffffffc000666b12 at cpu_exception_handler_user+0x72
panic: Stopping here.

-- 
You are receiving this mail because:
You are the assignee for the bug.