Subject: [PATCH 07/11] smc: move unhash as early as possible in smc_release()

From: Cong Wang <[email-masked]>
Date: Sat, 5 Jan 2019 23:45:26 -0800

[ Upstream commit 26d92e951fe0a44ee4aec157cabb65a818cc8151 ]

In smc_release() we release smc->clcsock before unhash the smc
sock, but a parallel smc_diag_dump() may be still reading
smc->clcsock, therefore this could cause a use-after-free as
reported by syzbot.

Reported-and-tested-by: [email-masked]
Fixes: 51f1de79ad8e ("net/smc: replace sock_put worker by socket refcounting")
Cc: Ursula Braun <[email-masked]>
Signed-off-by: Cong Wang <[email-masked]>
Reported-by: [email-masked]
Reported-by: [email-masked]
Signed-off-by: David S. Miller <[email-masked]>
---
 net/smc/af_smc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 2b8f95290627..e6e506b2db99 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -144,6 +144,9 @@ static int smc_release(struct socket *sock)
 		sock_set_flag(sk, SOCK_DEAD);
 		sk->sk_shutdown |= SHUTDOWN_MASK;
 	}
+
+	sk->sk_prot->unhash(sk);
+
 	if (smc->clcsock) {
 		if (smc->use_fallback && sk->sk_state == SMC_LISTEN) {
 			/* wake up clcsock accept */
@@ -168,7 +171,6 @@ static int smc_release(struct socket *sock)
 		smc_conn_free(&smc->conn);
 	release_sock(sk);
 
-	sk->sk_prot->unhash(sk);
 	sock_put(sk); /* final sock_put */
 out:
 	return rc;
-- 
2.20.1