diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c index 10219f55aad14d795dabe4331458bd1b73c22789..b6abd0efea22c0c9726090b5de60e648b86e09a0 100644 --- a/net/smc/smc_close.c +++ b/net/smc/smc_close.c @@ -30,7 +30,8 @@ void smc_clcsock_release(struct smc_sock *smc) mutex_lock(&smc->clcsock_release_lock); if (smc->clcsock) { tcp = smc->clcsock; - smc->clcsock = NULL; + WRITE_ONCE(smc->clcsock, NULL); + synchronize_rcu(); sock_release(tcp); } mutex_unlock(&smc->clcsock_release_lock); diff --git a/net/smc/smc_diag.c b/net/smc/smc_diag.c index 8ed2f6689b017098ff8e8a3c15b8104d69643437..9672933206261decdddfde4edcc30b95b294dc92 100644 --- a/net/smc/smc_diag.c +++ b/net/smc/smc_diag.c @@ -35,26 +35,32 @@ static struct smc_diag_dump_ctx *smc_dump_context(struct netlink_callback *cb) static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) { struct smc_sock *smc = smc_sk(sk); + struct socket *clcsock; memset(r, 0, sizeof(*r)); r->diag_family = sk->sk_family; sock_diag_save_cookie(sk, r->id.idiag_cookie); - if (!smc->clcsock) - return; - r->id.idiag_sport = htons(smc->clcsock->sk->sk_num); - r->id.idiag_dport = smc->clcsock->sk->sk_dport; - r->id.idiag_if = smc->clcsock->sk->sk_bound_dev_if; + + rcu_read_lock(); + clcsock = READ_ONCE(smc->clcsock); + if (!clcsock) + goto unlock; + r->id.idiag_sport = htons(clcsock->sk->sk_num); + r->id.idiag_dport = clcsock->sk->sk_dport; + r->id.idiag_if = clcsock->sk->sk_bound_dev_if; if (sk->sk_protocol == SMCPROTO_SMC) { - r->id.idiag_src[0] = smc->clcsock->sk->sk_rcv_saddr; - r->id.idiag_dst[0] = smc->clcsock->sk->sk_daddr; + r->id.idiag_src[0] = clcsock->sk->sk_rcv_saddr; + r->id.idiag_dst[0] = clcsock->sk->sk_daddr; #if IS_ENABLED(CONFIG_IPV6) } else if (sk->sk_protocol == SMCPROTO_SMC6) { - memcpy(&r->id.idiag_src, &smc->clcsock->sk->sk_v6_rcv_saddr, - sizeof(smc->clcsock->sk->sk_v6_rcv_saddr)); - memcpy(&r->id.idiag_dst, &smc->clcsock->sk->sk_v6_daddr, - sizeof(smc->clcsock->sk->sk_v6_daddr)); + memcpy(&r->id.idiag_src, &clcsock->sk->sk_v6_rcv_saddr, + sizeof(clcsock->sk->sk_v6_rcv_saddr)); + memcpy(&r->id.idiag_dst, &clcsock->sk->sk_v6_daddr, + sizeof(clcsock->sk->sk_v6_daddr)); #endif } +unlock: + rcu_read_unlock(); } static int smc_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,