Commit e1bbdd57 authored by Ursula Braun's avatar Ursula Braun Committed by David S. Miller
Browse files

net/smc: reduce sock_put() for fallback sockets

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: ee9dfbef

 ("net/smc: handle sockopts forcing fallback")
Reported-by: syzbot+3a0748c8f2f210c0ef9b@syzkaller.appspotmail.com
Reported-by: syzbot+9e60d2428a42049a592a@syzkaller.appspotmail.com
Signed-off-by: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 000244d3
...@@ -147,6 +147,7 @@ static int smc_release(struct socket *sock) ...@@ -147,6 +147,7 @@ static int smc_release(struct socket *sock)
smc->clcsock = NULL; smc->clcsock = NULL;
} }
if (smc->use_fallback) { if (smc->use_fallback) {
if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT)
sock_put(sk); /* passive closing */ sock_put(sk); /* passive closing */
sk->sk_state = SMC_CLOSED; sk->sk_state = SMC_CLOSED;
sk->sk_state_change(sk); sk->sk_state_change(sk);
...@@ -417,13 +418,19 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code) ...@@ -417,13 +418,19 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code)
{ {
int rc; 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; return reason_code;
}
if (reason_code != SMC_CLC_DECL_REPLY) { if (reason_code != SMC_CLC_DECL_REPLY) {
rc = smc_clc_send_decline(smc, reason_code); 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 rc;
} }
}
return smc_connect_fallback(smc); return smc_connect_fallback(smc);
} }
...@@ -435,8 +442,6 @@ static int smc_connect_abort(struct smc_sock *smc, int reason_code, ...@@ -435,8 +442,6 @@ static int smc_connect_abort(struct smc_sock *smc, int reason_code,
smc_lgr_forget(smc->conn.lgr); smc_lgr_forget(smc->conn.lgr);
mutex_unlock(&smc_create_lgr_pending); mutex_unlock(&smc_create_lgr_pending);
smc_conn_free(&smc->conn); smc_conn_free(&smc->conn);
if (reason_code < 0 && smc->sk.sk_state == SMC_INIT)
sock_put(&smc->sk); /* passive closing */
return reason_code; return reason_code;
} }
......
...@@ -107,6 +107,8 @@ static void smc_close_active_abort(struct smc_sock *smc) ...@@ -107,6 +107,8 @@ static void smc_close_active_abort(struct smc_sock *smc)
} }
switch (sk->sk_state) { switch (sk->sk_state) {
case SMC_INIT: case SMC_INIT:
sk->sk_state = SMC_PEERABORTWAIT;
break;
case SMC_ACTIVE: case SMC_ACTIVE:
sk->sk_state = SMC_PEERABORTWAIT; sk->sk_state = SMC_PEERABORTWAIT;
release_sock(sk); release_sock(sk);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment