In the Linux kernel, the following vulnerability has been resolved:
net/smc: fix TOCTOU race between smclistenout() and listener close
smclistenout() reads lsmc->sk.skstate without the listener lock, then acquires locksocknested() only after the check passes. This opens a window where smccloseactive() can transition the listener to SMCCLOSED, call smcclosecleanup_listen() to drain the accept queue, and release the lock, all between the lockless read and the delayed lock acquisition:
smclistenwork (smchswq) smccloseactive() ------------------------------- ------------------------- releasesock(child) if (skstate == SMCLISTEN) TRUE locksock(listener) skstate = SMCCLOSED smcclosecleanuplisten() releasesock(listener) flushwork(tcplistenwork) locksocknested(listener) smcaccept_enqueue(listener, child) /* child enqueued on dead listener */
smccloseactive() flushes only tcplistenwork. Work items already dispatched onto smchswq for the CLC handshake continue running unguarded. smcacceptenqueue() takes a sockhold() on the child that is never released, so the child smcsock, its clcsock, and the reference all leak. A remote peer that opens TCP connections while the server calls close() can exhaust kernel memory.
Move locksocknested() to before the sk_state check so that the test and the enqueue are atomic under the listener lock.