Skip to content

Commit

Permalink
net/smc: add fallback check to connect()
Browse files Browse the repository at this point in the history
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: 6d6dd52 ("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>
  • Loading branch information
Ursula Braun authored and Jakub Kicinski committed Dec 15, 2019
1 parent 9b2079c commit 8643474
Showing 1 changed file with 8 additions and 6 deletions.
14 changes: 8 additions & 6 deletions net/smc/af_smc.c
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,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;
Expand Down Expand Up @@ -1721,15 +1723,15 @@ 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;
if (get_user(val, (int __user *)optval))
return -EFAULT;

lock_sock(sk);
if (rc || smc->use_fallback)
goto out;
switch (optname) {
case TCP_ULP:
case TCP_FASTOPEN:
Expand All @@ -1741,15 +1743,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);
}
Expand All @@ -1758,7 +1759,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);
}
Expand All @@ -1769,6 +1770,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
default:
break;
}
out:
release_sock(sk);

return rc;
Expand Down

0 comments on commit 8643474

Please sign in to comment.