net/smc: move unhash before release of clcsock

[ Upstream commit f61bca58f6c36e666c2b807697f25e5e98708162 ]

Commit <26d92e951fe0>
("net/smc: move unhash as early as possible in smc_release()")
fixes one occurrence in the smc code, but the same pattern exists
in other places. This patch covers the remaining occurrences and
makes sure, the unhash operation is done before the smc->clcsock is
released. This avoids a potential use-after-free in smc_diag_dump().

Reviewed-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Ursula Braun 2019-04-11 11:17:34 +02:00 committed by Greg Kroah-Hartman
parent cd54dc4cd3
commit 3ddc2a1007

View file

@ -848,11 +848,11 @@ static int smc_clcsock_accept(struct smc_sock *lsmc, struct smc_sock **new_smc)
if (rc < 0)
lsk->sk_err = -rc;
if (rc < 0 || lsk->sk_state == SMC_CLOSED) {
new_sk->sk_prot->unhash(new_sk);
if (new_clcsock)
sock_release(new_clcsock);
new_sk->sk_state = SMC_CLOSED;
sock_set_flag(new_sk, SOCK_DEAD);
new_sk->sk_prot->unhash(new_sk);
sock_put(new_sk); /* final */
*new_smc = NULL;
goto out;
@ -903,11 +903,11 @@ struct sock *smc_accept_dequeue(struct sock *parent,
smc_accept_unlink(new_sk);
if (new_sk->sk_state == SMC_CLOSED) {
new_sk->sk_prot->unhash(new_sk);
if (isk->clcsock) {
sock_release(isk->clcsock);
isk->clcsock = NULL;
}
new_sk->sk_prot->unhash(new_sk);
sock_put(new_sk); /* final */
continue;
}
@ -932,6 +932,7 @@ void smc_close_non_accepted(struct sock *sk)
sock_set_flag(sk, SOCK_DEAD);
sk->sk_shutdown |= SHUTDOWN_MASK;
}
sk->sk_prot->unhash(sk);
if (smc->clcsock) {
struct socket *tcp;
@ -947,7 +948,6 @@ void smc_close_non_accepted(struct sock *sk)
smc_conn_free(&smc->conn);
}
release_sock(sk);
sk->sk_prot->unhash(sk);
sock_put(sk); /* final sock_put */
}