diff options
author | Ursula Braun <ubraun@linux.ibm.com> | 2018-07-05 10:15:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-07-07 07:25:13 -0400 |
commit | e1bbdd57047454dad068dc36612dd60a57f4c58f (patch) | |
tree | 76e741e90f29cedf93a749cb68d9695704482958 /net/smc | |
parent | 000244d3dc1f8114e38fe9ee2d9a0986404d9cbe (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.c | 15 | ||||
-rw-r--r-- | net/smc/smc_close.c | 2 |
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); |