@@ -147,7 +147,8 @@ static int smc_release(struct socket *sock)
smc->clcsock = NULL;
}
if (smc->use_fallback) {
- sock_put(sk); /* passive closing */
+ if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT)
+ sock_put(sk); /* passive closing */
sk->sk_state = SMC_CLOSED;
sk->sk_state_change(sk);
}
@@ -417,12 +418,18 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code)
{
int rc;
- if (reason_code < 0) /* error, fallback is not possible */
+ if (reason_code < 0) { /* error, fallback is not possible */
+ if (smc->sk.sk_state == SMC_INIT)
+ sock_put(&smc->sk); /* passive closing */
return reason_code;
+ }
if (reason_code != SMC_CLC_DECL_REPLY) {
rc = smc_clc_send_decline(smc, reason_code);
- if (rc < 0)
+ if (rc < 0) {
+ if (smc->sk.sk_state == SMC_INIT)
+ sock_put(&smc->sk); /* passive closing */
return rc;
+ }
}
return smc_connect_fallback(smc);
}
@@ -435,8 +442,6 @@ static int smc_connect_abort(struct smc_sock *smc, int reason_code,
smc_lgr_forget(smc->conn.lgr);
mutex_unlock(&smc_create_lgr_pending);
smc_conn_free(&smc->conn);
- if (reason_code < 0 && smc->sk.sk_state == SMC_INIT)
- sock_put(&smc->sk); /* passive closing */
return reason_code;
}
@@ -107,6 +107,8 @@ static void smc_close_active_abort(struct smc_sock *smc)
}
switch (sk->sk_state) {
case SMC_INIT:
+ sk->sk_state = SMC_PEERABORTWAIT;
+ break;
case SMC_ACTIVE:
sk->sk_state = SMC_PEERABORTWAIT;
release_sock(sk);
smc_release() calls a sock_put() for smc fallback sockets to cover the passive closing sock_hold() in __smc_connect() and smc_tcp_listen_work(). This does not make sense for sockets in state SMC_LISTEN and SMC_INIT. An SMC socket stays in state SMC_INIT if connect fails. The sock_put in smc_connect_abort() does not cover all failures. Move it into smc_connect_decline_fallback(). Fixes: ee9dfbef02d18 ("net/smc: handle sockopts forcing fallback") Reported-by: syzbot+3a0748c8f2f210c0ef9b@syzkaller.appspotmail.com Reported-by: syzbot+9e60d2428a42049a592a@syzkaller.appspotmail.com Signed-off-by: Ursula Braun <ubraun@linux.ibm.com> --- net/smc/af_smc.c | 15 ++++++++++----- net/smc/smc_close.c | 2 ++ 2 files changed, 12 insertions(+), 5 deletions(-)