panic #2: assertion "sb->sb_mb == m" failed in sbunlinkmbuf at /usr/src/sys/kern/uipc_sockbuf.c:552 cpuid = 0 Trace beginning at frame 0xfffff80118623708 sbunlinkmbuf() at sbunlinkmbuf+0x109 0xffffffff806c1e09 sbunlinkmbuf() at sbunlinkmbuf+0x109 0xffffffff806c1e09 soreceive() at soreceive+0xbd5 0xffffffff806c6335 kern_recvmsg() at kern_recvmsg+0xf7 0xffffffff806cba17 sys_recvfrom() at sys_recvfrom+0xc4 0xffffffff806cbc64 syscall2() at syscall2+0x11e 0xffffffff80bd6a0e Debugger("panic") CPU0 stopping CPUs: 0x0000003e stopped Stopped at Debugger+0x7c: movb $0,0xbdaf09(%rip) db> -------------------------------------------------------------- Captured from dfbsd-qemu serial console (vm.sh log) after the run: /tmp/poc_race 60 200 500 1 (mode 1 = AF_UNIX SOCK_STREAM socketpair, unprivileged user maxx). Same root cause as panic #1, different receive path: generic soreceive() (used by AF_UNIX / UDP) holds the receive token across its uiomove copy loop, but a DFly thread that blocks in tsleep() temporarily releases all its lwkt tokens (lwkt_switch -> lwkt_relalltokens). While the reader slept in a swap-in page fault, shutdown(fd, SHUT_RD) -> soshutdown() -> sorflush() (which never takes ssb_lock, uipc_socket.c:1953-1957) acquired the token, bzero()'d the sockbuf and freed every mbuf (ssb_release -> sbflush -> sbdrop -> m_freem). The reader woke, finished copying from a freed cluster, and then hit sbunlinkmbuf()'s KKASSERT(sb->sb_mb == m) (uipc_sockbuf.c:552) because sb->sb_mb had been zeroed underneath it. On a NON-INVARIANTS (production) kernel that KKASSERT is absent: sbunlinkmbuf() would then write sb->sb_mb = m->m_nextpkt (a stale pointer read from freed memory) and sbfree() accounting on a freed mbuf - i.e. sockbuf state corruption with attacker-influenced reuse, strictly worse than the panic. panic #1 (TCP path) is in panic.txt.