Commit 1de9770d authored by Wen Gu's avatar Wen Gu Committed by David S. Miller

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

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: 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.comSigned-off-by: default avatarWen Gu <guwen@linux.alibaba.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f1baf68e
...@@ -667,14 +667,17 @@ static void smc_fback_error_report(struct sock *clcsk) ...@@ -667,14 +667,17 @@ static void smc_fback_error_report(struct sock *clcsk)
static int smc_switch_to_fallback(struct smc_sock *smc, int reason_code) static int smc_switch_to_fallback(struct smc_sock *smc, int reason_code)
{ {
struct sock *clcsk; struct sock *clcsk;
int rc = 0;
mutex_lock(&smc->clcsock_release_lock); mutex_lock(&smc->clcsock_release_lock);
if (!smc->clcsock) { if (!smc->clcsock) {
mutex_unlock(&smc->clcsock_release_lock); rc = -EBADF;
return -EBADF; goto out;
} }
clcsk = smc->clcsock->sk; clcsk = smc->clcsock->sk;
if (smc->use_fallback)
goto out;
smc->use_fallback = true; smc->use_fallback = true;
smc->fallback_rsn = reason_code; smc->fallback_rsn = reason_code;
smc_stat_fallback(smc); smc_stat_fallback(smc);
...@@ -702,8 +705,9 @@ static int smc_switch_to_fallback(struct smc_sock *smc, int reason_code) ...@@ -702,8 +705,9 @@ static int smc_switch_to_fallback(struct smc_sock *smc, int reason_code)
smc->clcsock->sk->sk_user_data = smc->clcsock->sk->sk_user_data =
(void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY); (void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY);
} }
out:
mutex_unlock(&smc->clcsock_release_lock); mutex_unlock(&smc->clcsock_release_lock);
return 0; return rc;
} }
/* fall back during connect */ /* fall back during connect */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment