HomeFreeBSD

socket: Properly interlock when transitioning to a listening socket

Description

socket: Properly interlock when transitioning to a listening socket

Currently, most protocols implement pru_listen with something like the
following:

SOCK_LOCK(so);
error = solisten_proto_check(so);
if (error) {

		SOCK_UNLOCK(so);
		return (error);

}
solisten_proto(so);
SOCK_UNLOCK(so);

solisten_proto_check() fails if the socket is connected or connecting.
However, the socket lock is not used during I/O, so this pattern is
racy.

The change modifies solisten_proto_check() to additionally acquire
socket buffer locks, and the calling thread holds them until
solisten_proto() or solisten_proto_abort() is called. Now that the
socket buffer locks are preserved across a listen(2), this change allows
socket I/O paths to properly interlock with listen(2).

This fixes a large number of syzbot reports, only one is listed below
and the rest will be dup'ed to it.

Reported by: syzbot+9fece8a63c0e27273821@syzkaller.appspotmail.com
Reviewed by: tuexen, gallatin
MFC after: 1 month
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D31659

Details

Provenance
markjAuthored on Sep 7 2021, 6:49 PM
Reviewer
tuexen
Differential Revision
D31659: socket: Properly interlock when transitioning to a listening socket
Parents
rGc67f3b8b78e5: socket: Move sockbuf mutexes into the owning socket
Branches
Unknown
Tags
Unknown