Commit da9ffbd6 authored by Wen Gu's avatar Wen Gu Committed by Litao Jiao
Browse files

anolis: net/smc: Avoid clcsock access panic

anolis inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I79GVV
CVE: NA

Reference: https://gitee.com/anolis/cloud-kernel/commit/6111a29e707fe83f89eb4dedc22e401b3c544389



--------------------------------

ANBZ: #1742

This patch is a set of the workaround for clcsock access panic.

There are two kinds of invalid access of clcsock.
1) Access smc->clcsock when smc->clcsock is reset to NULL;
2) Access smc->clcsock->sk when sock_release(clcsock);

In upstream implementation, only 1) happens, and it is fixed by
c0bf3d8a ("net/smc: Transitional solution for clcsock race
issue").

In anolis implementation, 1) and 2) are both reproduced. They
are mainly triggered by c5e5a9f9c5d8 ("net/smc: Keep first contact
clcsock"). In anolis smc implementation, The first contact's
clcsock is saved in link struct and may be released during smc
link clear. After that, if smc->clcsock is accessed, a NULL pointer
panic will happen.

This patch provides a workaround for these. To eradicate such
issues, We may need to avoid using first contact's clcsock as
erdma link.

Fixes: c0bf3d8a ("net/smc: Transitional solution for clcsock race issue").
Signed-off-by: default avatarWen Gu <guwen@linux.alibaba.com>
Reviewed-by: default avatarTony Lu <tonylu@linux.alibaba.com>
Acked-by: default avatarTony Lu <tonylu@linux.alibaba.com>
Link: https://gitee.com/anolis/cloud-kernel/pulls/577


Signed-off-by: default avatarGengbiao Shen <shengengbiao@sangfor.com.cn>
parent 5d7785de
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1149,6 +1149,11 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
		break;
	}

	if (!smc->clcsock ||
	    (smc->clcsock && !smc->clcsock->sk)) {
		rc = -EBADF;
		goto out;
	}
	smc_copy_sock_settings_to_clc(smc);
	tcp_sk(smc->clcsock->sk)->syn_smc = 1;
	if (smc->connect_nonblock) {
@@ -1211,10 +1216,12 @@ static int smc_clcsock_accept(struct smc_sock *lsmc, struct smc_sock **new_smc)
		lsk->sk_err = -rc;
	if (rc < 0 || lsk->sk_state == SMC_CLOSED) {
		new_sk->sk_prot->unhash(new_sk);
		mutex_lock(&lsmc->clcsock_release_lock);
		if (new_clcsock)
			sock_release(new_clcsock);
		new_sk->sk_state = SMC_CLOSED;
		sock_set_flag(new_sk, SOCK_DEAD);
		mutex_unlock(&lsmc->clcsock_release_lock);
		sock_put(new_sk); /* final */
		*new_smc = NULL;
		goto out;