Commit 49909147 authored by Litao Jiao's avatar Litao Jiao
Browse files

net/smc: Avoid overwriting the copies of clcsock callback functions

mainline inclusion
from mainline-v5.17-rc5
commit 1de9770d
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I76JHC
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/smc?id=1de9770d121ee9294794cca0e0be8fbfa0134ee8



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

The callback functions of clcsock will be saved and replaced during
the fallback. But if the fallback happens more than once, then the
copies of these callback functions will be overwritten incorrectly,
resulting in a loop call issue:

clcsk->sk_error_report
 |- smc_fback_error_report() <------------------------------|
     |- smc_fback_forward_wakeup()                          | (loop)
         |- clcsock_callback()  (incorrectly overwritten)   |
             |- smc->clcsk_error_report() ------------------|

So this patch fixes the issue by saving these function pointers only
once in the fallback and avoiding overwriting.

Reported-by: default avatar <syzbot+4de3c0e8a263e1e499bc@syzkaller.appspotmail.com>
Fixes: 341adeec ("net/smc: Forward wakeup to smc socket waitqueue after fallback")
Link: https://lore.kernel.org/r/0000000000006d045e05d78776f6@google.com


Signed-off-by: default avatarWen Gu <guwen@linux.alibaba.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarLitao Jiao <jiaolitao@sangfor.com.cn>
parent cfaf3c09
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -706,14 +706,17 @@ static void smc_fback_error_report(struct sock *clcsk)
static int smc_switch_to_fallback(struct smc_sock *smc)
{
	struct sock *clcsk;
	int rc = 0;

	mutex_lock(&smc->clcsock_release_lock);
	if (!smc->clcsock) {
		mutex_unlock(&smc->clcsock_release_lock);
		return -EBADF;
		rc = -EBADF;
		goto out;
	}
	clcsk = smc->clcsock->sk;

	if (smc->use_fallback)
		goto out;
	smc->use_fallback = true;
	if (smc->sk.sk_socket && smc->sk.sk_socket->file) {
		smc->clcsock->file = smc->sk.sk_socket->file;
@@ -738,8 +741,9 @@ static int smc_switch_to_fallback(struct smc_sock *smc)
		smc->clcsock->sk->sk_user_data =
			(void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY);
	}
out:
	mutex_unlock(&smc->clcsock_release_lock);
	return 0;
	return rc;
}

/* fall back during connect */