net/smc: add fallback check to connect()
commit86434744fe
upstream. FASTOPEN setsockopt() or sendmsg() may switch the SMC socket to fallback mode. Once fallback mode is active, the native TCP socket functions are called. Nevertheless there is a small race window, when FASTOPEN setsockopt/sendmsg runs in parallel to a connect(), and switch the socket into fallback mode before connect() takes the sock lock. Make sure the SMC-specific connect setup is omitted in this case. This way a syzbot-reported refcount problem is fixed, triggered by different threads running non-blocking connect() and FASTOPEN_KEY setsockopt. Reported-by: syzbot+96d3f9ff6a86d37e44c8@syzkaller.appspotmail.com Fixes:6d6dd528d5
("net/smc: fix refcount non-blocking connect() -part 2") Signed-off-by: Ursula Braun <ubraun@linux.ibm.com> Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
e83c40f7bb
commit
90e0e78bfa
|
@ -854,6 +854,8 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
|
|||
goto out;
|
||||
|
||||
sock_hold(&smc->sk); /* sock put in passive closing */
|
||||
if (smc->use_fallback)
|
||||
goto out;
|
||||
if (flags & O_NONBLOCK) {
|
||||
if (schedule_work(&smc->connect_work))
|
||||
smc->connect_nonblock = 1;
|
||||
|
@ -1716,8 +1718,6 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
|
|||
sk->sk_err = smc->clcsock->sk->sk_err;
|
||||
sk->sk_error_report(sk);
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (optlen < sizeof(int))
|
||||
return -EINVAL;
|
||||
|
@ -1725,6 +1725,8 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
|
|||
return -EFAULT;
|
||||
|
||||
lock_sock(sk);
|
||||
if (rc || smc->use_fallback)
|
||||
goto out;
|
||||
switch (optname) {
|
||||
case TCP_ULP:
|
||||
case TCP_FASTOPEN:
|
||||
|
@ -1736,15 +1738,14 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
|
|||
smc_switch_to_fallback(smc);
|
||||
smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP;
|
||||
} else {
|
||||
if (!smc->use_fallback)
|
||||
rc = -EINVAL;
|
||||
rc = -EINVAL;
|
||||
}
|
||||
break;
|
||||
case TCP_NODELAY:
|
||||
if (sk->sk_state != SMC_INIT &&
|
||||
sk->sk_state != SMC_LISTEN &&
|
||||
sk->sk_state != SMC_CLOSED) {
|
||||
if (val && !smc->use_fallback)
|
||||
if (val)
|
||||
mod_delayed_work(system_wq, &smc->conn.tx_work,
|
||||
0);
|
||||
}
|
||||
|
@ -1753,7 +1754,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
|
|||
if (sk->sk_state != SMC_INIT &&
|
||||
sk->sk_state != SMC_LISTEN &&
|
||||
sk->sk_state != SMC_CLOSED) {
|
||||
if (!val && !smc->use_fallback)
|
||||
if (!val)
|
||||
mod_delayed_work(system_wq, &smc->conn.tx_work,
|
||||
0);
|
||||
}
|
||||
|
@ -1764,6 +1765,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
out:
|
||||
release_sock(sk);
|
||||
|
||||
return rc;
|
||||
|
|
Loading…
Reference in New Issue