DF-2694 / panic.txt
panic: assertion "m" failed in sorecvtcp at /usr/src/sys/kern/uipc_socket.c:1852
cpuid = 4
Trace beginning at frame 0xfffff80118677738
sorecvtcp() at sorecvtcp+0x988 0xffffffff806c6e78
sorecvtcp() at sorecvtcp+0x988 0xffffffff806c6e78
kern_recvmsg() at kern_recvmsg+0xf7 0xffffffff806cba17
sys_recvfrom() at sys_recvfrom+0xc4 0xffffffff806cbc64
syscall2() at syscall2() +0x11e 0xffffffff80bd6a0e
Debugger("panic")
CPU4 stopping CPUs: 0x0000002f
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 40 3000 3000 (as unprivileged user maxx,
uid 1001). DragonFly 6.5-DEVELOPMENT #0 stock INVARIANTS kernel.
The panic is KKASSERT(m) in the post-copy "sync" block of
sorecvtcp(): after sorecvtcp() released the receive token
(uipc_socket.c:1756/1758) and copied from the M_SOLOCKED mbuf
chain, a concurrent shutdown(fd, SHUT_RD) -> soshutdown() ->
sorflush() (which never takes ssb_lock) acquired the token while
the reader was blocked in a swap-in page fault (blocked DFly
threads release their lwkt tokens: lwkt_switch ->
lwkt_relalltokens), snapshotted the sockbuf, zeroed it and freed
every mbuf via ssb_release() -> sbflush() -> sbdrop() ->
m_freem() (no M_SOLOCKED check anywhere on that path). When the
reader woke it kept reading the freed mbufs; the copy loop exited
on m == NULL and the sync block then found so_rcv.ssb_mb == NULL
with offset != 0 -> KKASSERT(m) -> panic.
Reproducer: findings/poc/DF-2694/poc_race.c (see README.md)