net/smc: move unhash before release of clcsock
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>
This commit is contained in:
Родитель
8ef659f1a8
Коммит
f61bca58f6
|
@ -884,11 +884,11 @@ static int smc_clcsock_accept(struct smc_sock *lsmc, struct smc_sock **new_smc)
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
lsk->sk_err = -rc;
|
lsk->sk_err = -rc;
|
||||||
if (rc < 0 || lsk->sk_state == SMC_CLOSED) {
|
if (rc < 0 || lsk->sk_state == SMC_CLOSED) {
|
||||||
|
new_sk->sk_prot->unhash(new_sk);
|
||||||
if (new_clcsock)
|
if (new_clcsock)
|
||||||
sock_release(new_clcsock);
|
sock_release(new_clcsock);
|
||||||
new_sk->sk_state = SMC_CLOSED;
|
new_sk->sk_state = SMC_CLOSED;
|
||||||
sock_set_flag(new_sk, SOCK_DEAD);
|
sock_set_flag(new_sk, SOCK_DEAD);
|
||||||
new_sk->sk_prot->unhash(new_sk);
|
|
||||||
sock_put(new_sk); /* final */
|
sock_put(new_sk); /* final */
|
||||||
*new_smc = NULL;
|
*new_smc = NULL;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -939,11 +939,11 @@ struct sock *smc_accept_dequeue(struct sock *parent,
|
||||||
|
|
||||||
smc_accept_unlink(new_sk);
|
smc_accept_unlink(new_sk);
|
||||||
if (new_sk->sk_state == SMC_CLOSED) {
|
if (new_sk->sk_state == SMC_CLOSED) {
|
||||||
|
new_sk->sk_prot->unhash(new_sk);
|
||||||
if (isk->clcsock) {
|
if (isk->clcsock) {
|
||||||
sock_release(isk->clcsock);
|
sock_release(isk->clcsock);
|
||||||
isk->clcsock = NULL;
|
isk->clcsock = NULL;
|
||||||
}
|
}
|
||||||
new_sk->sk_prot->unhash(new_sk);
|
|
||||||
sock_put(new_sk); /* final */
|
sock_put(new_sk); /* final */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -973,6 +973,7 @@ void smc_close_non_accepted(struct sock *sk)
|
||||||
sock_set_flag(sk, SOCK_DEAD);
|
sock_set_flag(sk, SOCK_DEAD);
|
||||||
sk->sk_shutdown |= SHUTDOWN_MASK;
|
sk->sk_shutdown |= SHUTDOWN_MASK;
|
||||||
}
|
}
|
||||||
|
sk->sk_prot->unhash(sk);
|
||||||
if (smc->clcsock) {
|
if (smc->clcsock) {
|
||||||
struct socket *tcp;
|
struct socket *tcp;
|
||||||
|
|
||||||
|
@ -988,7 +989,6 @@ void smc_close_non_accepted(struct sock *sk)
|
||||||
smc_conn_free(&smc->conn);
|
smc_conn_free(&smc->conn);
|
||||||
}
|
}
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
sk->sk_prot->unhash(sk);
|
|
||||||
sock_put(sk); /* final sock_put */
|
sock_put(sk); /* final sock_put */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче