Patch "net/smc: fix dangling sock under state SMC_APPFINCLOSEWAIT" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    net/smc: fix dangling sock under state SMC_APPFINCLOSEWAIT

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     net-smc-fix-dangling-sock-under-state-smc_appfinclos.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit dba702324ca095d05e0e44ceb23b0dacce0bfb20
Author: D. Wythe <alibuda@xxxxxxxxxxxxxxxxx>
Date:   Fri Nov 3 14:07:38 2023 +0800

    net/smc: fix dangling sock under state SMC_APPFINCLOSEWAIT
    
    [ Upstream commit 5211c9729484c923f8d2e06bd29f9322cc42bb8f ]
    
    Considering scenario:
    
                                    smc_cdc_rx_handler
    __smc_release
                                    sock_set_flag
    smc_close_active()
    sock_set_flag
    
    __set_bit(DEAD)                 __set_bit(DONE)
    
    Dues to __set_bit is not atomic, the DEAD or DONE might be lost.
    if the DEAD flag lost, the state SMC_CLOSED  will be never be reached
    in smc_close_passive_work:
    
    if (sock_flag(sk, SOCK_DEAD) &&
            smc_close_sent_any_close(conn)) {
            sk->sk_state = SMC_CLOSED;
    } else {
            /* just shutdown, but not yet closed locally */
            sk->sk_state = SMC_APPFINCLOSEWAIT;
    }
    
    Replace sock_set_flags or __set_bit to set_bit will fix this problem.
    Since set_bit is atomic.
    
    Fixes: b38d732477e4 ("smc: socket closing and linkgroup cleanup")
    Signed-off-by: D. Wythe <alibuda@xxxxxxxxxxxxxxxxx>
    Reviewed-by: Dust Li <dust.li@xxxxxxxxxxxxxxxxx>
    Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index b398d72a7bc39..e070b0e2a30c5 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -136,7 +136,7 @@ static int __smc_release(struct smc_sock *smc)
 
 	if (!smc->use_fallback) {
 		rc = smc_close_active(smc);
-		sock_set_flag(sk, SOCK_DEAD);
+		smc_sock_set_flag(sk, SOCK_DEAD);
 		sk->sk_shutdown |= SHUTDOWN_MASK;
 	} else {
 		if (sk->sk_state != SMC_CLOSED) {
@@ -928,7 +928,7 @@ static int smc_clcsock_accept(struct smc_sock *lsmc, struct smc_sock **new_smc)
 		if (new_clcsock)
 			sock_release(new_clcsock);
 		new_sk->sk_state = SMC_CLOSED;
-		sock_set_flag(new_sk, SOCK_DEAD);
+		smc_sock_set_flag(new_sk, SOCK_DEAD);
 		sock_put(new_sk); /* final */
 		*new_smc = NULL;
 		goto out;
diff --git a/net/smc/smc.h b/net/smc/smc.h
index 878313f8d6c17..8c46eaf014a75 100644
--- a/net/smc/smc.h
+++ b/net/smc/smc.h
@@ -265,4 +265,9 @@ static inline bool using_ipsec(struct smc_sock *smc)
 struct sock *smc_accept_dequeue(struct sock *parent, struct socket *new_sock);
 void smc_close_non_accepted(struct sock *sk);
 
+static inline void smc_sock_set_flag(struct sock *sk, enum sock_flags flag)
+{
+	set_bit(flag, &sk->sk_flags);
+}
+
 #endif	/* __SMC_H */
diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c
index d0b0f4c865b40..68e1155126cf0 100644
--- a/net/smc/smc_cdc.c
+++ b/net/smc/smc_cdc.c
@@ -298,7 +298,7 @@ static void smc_cdc_msg_recv_action(struct smc_sock *smc,
 		smc->sk.sk_shutdown |= RCV_SHUTDOWN;
 		if (smc->clcsock && smc->clcsock->sk)
 			smc->clcsock->sk->sk_shutdown |= RCV_SHUTDOWN;
-		sock_set_flag(&smc->sk, SOCK_DONE);
+		smc_sock_set_flag(&smc->sk, SOCK_DONE);
 		sock_hold(&smc->sk); /* sock_put in close_work */
 		if (!schedule_work(&conn->close_work))
 			sock_put(&smc->sk);
diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c
index 543948d970c52..a704234c1a2ba 100644
--- a/net/smc/smc_close.c
+++ b/net/smc/smc_close.c
@@ -164,7 +164,7 @@ static void smc_close_active_abort(struct smc_sock *smc)
 		break;
 	}
 
-	sock_set_flag(sk, SOCK_DEAD);
+	smc_sock_set_flag(sk, SOCK_DEAD);
 	sk->sk_state_change(sk);
 }
 



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux