summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWen Gu <guwen@linux.alibaba.com>2022-02-09 17:10:53 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-02-23 14:03:12 +0300
commit7de7ba7a8bd4fde0141de8674c13514d0072f0e6 (patch)
tree065f0bc135914c1f6e7411e6dcb1739c34ebd4d6
parentf8ba235c4927b5f970c868ac101ec42ca16c183a (diff)
downloadlinux-7de7ba7a8bd4fde0141de8674c13514d0072f0e6.tar.xz
net/smc: Avoid overwriting the copies of clcsock callback functions
commit 1de9770d121ee9294794cca0e0be8fbfa0134ee8 upstream. 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: 341adeec9ada ("net/smc: Forward wakeup to smc socket waitqueue after fallback") Link: https://lore.kernel.org/r/0000000000006d045e05d78776f6@google.com Signed-off-by: Wen Gu <guwen@linux.alibaba.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/smc/af_smc.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 96dee4a62385..eff22065e197 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -649,14 +649,17 @@ static void smc_fback_error_report(struct sock *clcsk)
static int smc_switch_to_fallback(struct smc_sock *smc, int reason_code)
{
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;
smc->fallback_rsn = reason_code;
smc_stat_fallback(smc);
@@ -683,8 +686,9 @@ static int smc_switch_to_fallback(struct smc_sock *smc, int reason_code)
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 */