aboutsummaryrefslogtreecommitdiffstats
path: root/net/smc
diff options
context:
space:
mode:
authorUrsula Braun <ubraun@linux.ibm.com>2018-07-05 10:15:30 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-07 07:25:13 -0400
commite1bbdd57047454dad068dc36612dd60a57f4c58f (patch)
tree76e741e90f29cedf93a749cb68d9695704482958 /net/smc
parent000244d3dc1f8114e38fe9ee2d9a0986404d9cbe (diff)
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: 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> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/smc')
-rw-r--r--net/smc/af_smc.c15
-rw-r--r--net/smc/smc_close.c2
2 files changed, 12 insertions, 5 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index e017b6a4452b..5334157f5065 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -147,7 +147,8 @@ static int smc_release(struct socket *sock)
147 smc->clcsock = NULL; 147 smc->clcsock = NULL;
148 } 148 }
149 if (smc->use_fallback) { 149 if (smc->use_fallback) {
150 sock_put(sk); /* passive closing */ 150 if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT)
151 sock_put(sk); /* passive closing */
151 sk->sk_state = SMC_CLOSED; 152 sk->sk_state = SMC_CLOSED;
152 sk->sk_state_change(sk); 153 sk->sk_state_change(sk);
153 } 154 }
@@ -417,12 +418,18 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code)
417{ 418{
418 int rc; 419 int rc;
419 420
420 if (reason_code < 0) /* error, fallback is not possible */ 421 if (reason_code < 0) { /* error, fallback is not possible */
422 if (smc->sk.sk_state == SMC_INIT)
423 sock_put(&smc->sk); /* passive closing */
421 return reason_code; 424 return reason_code;
425 }
422 if (reason_code != SMC_CLC_DECL_REPLY) { 426 if (reason_code != SMC_CLC_DECL_REPLY) {
423 rc = smc_clc_send_decline(smc, reason_code); 427 rc = smc_clc_send_decline(smc, reason_code);
424 if (rc < 0) 428 if (rc < 0) {
429 if (smc->sk.sk_state == SMC_INIT)
430 sock_put(&smc->sk); /* passive closing */
425 return rc; 431 return rc;
432 }
426 } 433 }
427 return smc_connect_fallback(smc); 434 return smc_connect_fallback(smc);
428} 435}
@@ -435,8 +442,6 @@ static int smc_connect_abort(struct smc_sock *smc, int reason_code,
435 smc_lgr_forget(smc->conn.lgr); 442 smc_lgr_forget(smc->conn.lgr);
436 mutex_unlock(&smc_create_lgr_pending); 443 mutex_unlock(&smc_create_lgr_pending);
437 smc_conn_free(&smc->conn); 444 smc_conn_free(&smc->conn);
438 if (reason_code < 0 && smc->sk.sk_state == SMC_INIT)
439 sock_put(&smc->sk); /* passive closing */
440 return reason_code; 445 return reason_code;
441} 446}
442 447
diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c
index fa41d9881741..ac961dfb1ea1 100644
--- a/net/smc/smc_close.c
+++ b/net/smc/smc_close.c
@@ -107,6 +107,8 @@ static void smc_close_active_abort(struct smc_sock *smc)
107 } 107 }
108 switch (sk->sk_state) { 108 switch (sk->sk_state) {
109 case SMC_INIT: 109 case SMC_INIT:
110 sk->sk_state = SMC_PEERABORTWAIT;
111 break;
110 case SMC_ACTIVE: 112 case SMC_ACTIVE:
111 sk->sk_state = SMC_PEERABORTWAIT; 113 sk->sk_state = SMC_PEERABORTWAIT;
112 release_sock(sk); 114 release_sock(sk);