mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
socket: Avoid clearing SS_ISCONNECTING if soconnect() fails
This behaviour appears to date from the 4.4 BSD import. It has two
problems:
1. The update to so_state is not protected by the socket lock, so
concurrent updates to so_state may be lost.
2. Suppose two threads race to call connect(2) on a socket, and one
succeeds while the other fails. Then the failing thread may
incorrectly clear SS_ISCONNECTING, confusing the state machine.
Simply remove the update. It does not appear to be necessary:
pru_connect implementations which call soisconnecting() only do so after
all failure modes have been handled. For instance, tcp_connect() and
tcp6_connect() will never return an error after calling soisconnected().
However, we cannot correctly assert that SS_ISCONNECTED is not set after
an error from soconnect() since the socket lock is not held across the
pru_connect call, so a concurrent connect(2) may have set the flag.
Sponsored by: The FreeBSD Foundation
(cherry picked from commit a8aa6f1f78)
This commit is contained in:
parent
f983298883
commit
160ed20e62
1 changed files with 2 additions and 7 deletions
|
|
@ -484,7 +484,7 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
|
|||
{
|
||||
struct socket *so;
|
||||
struct file *fp;
|
||||
int error, interrupted = 0;
|
||||
int error;
|
||||
|
||||
#ifdef CAPABILITY_MODE
|
||||
if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD))
|
||||
|
|
@ -522,11 +522,8 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
|
|||
while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
|
||||
error = msleep(&so->so_timeo, &so->so_lock, PSOCK | PCATCH,
|
||||
"connec", 0);
|
||||
if (error != 0) {
|
||||
if (error == EINTR || error == ERESTART)
|
||||
interrupted = 1;
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (error == 0) {
|
||||
error = so->so_error;
|
||||
|
|
@ -534,8 +531,6 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
|
|||
}
|
||||
SOCK_UNLOCK(so);
|
||||
bad:
|
||||
if (!interrupted)
|
||||
so->so_state &= ~SS_ISCONNECTING;
|
||||
if (error == ERESTART)
|
||||
error = EINTR;
|
||||
done1:
|
||||
|
|
|
|||
Loading…
Reference in a new issue