Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 40fdfacb authored by Tony Lu's avatar Tony Lu Committed by Greg Kroah-Hartman
Browse files

net/smc: Keep smc_close_final rc during active close

commit 00e158fb91dfaff3f94746f260d11f1a4853506e upstream.

When smc_close_final() returns error, the return code overwrites by
kernel_sock_shutdown() in smc_close_active(). The return code of
smc_close_final() is more important than kernel_sock_shutdown(), and it
will pass to userspace directly.

Fix it by keeping both return codes, if smc_close_final() raises an
error, return it or kernel_sock_shutdown()'s.

Link: https://lore.kernel.org/linux-s390/1f67548e-cbf6-0dce-82b5-10288a4583bd@linux.ibm.com/


Fixes: 606a63c9783a ("net/smc: Ensure the active closing peer first closes clcsock")
Suggested-by: default avatarKarsten Graul <kgraul@linux.ibm.com>
Signed-off-by: default avatarTony Lu <tonylu@linux.alibaba.com>
Reviewed-by: default avatarWen Gu <guwen@linux.alibaba.com>
Acked-by: default avatarKarsten Graul <kgraul@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 11560e97
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -167,6 +167,7 @@ int smc_close_active(struct smc_sock *smc)
	int old_state;
	int old_state;
	long timeout;
	long timeout;
	int rc = 0;
	int rc = 0;
	int rc1 = 0;


	timeout = current->flags & PF_EXITING ?
	timeout = current->flags & PF_EXITING ?
		  0 : sock_flag(sk, SOCK_LINGER) ?
		  0 : sock_flag(sk, SOCK_LINGER) ?
@@ -206,8 +207,11 @@ int smc_close_active(struct smc_sock *smc)
			/* actively shutdown clcsock before peer close it,
			/* actively shutdown clcsock before peer close it,
			 * prevent peer from entering TIME_WAIT state.
			 * prevent peer from entering TIME_WAIT state.
			 */
			 */
			if (smc->clcsock && smc->clcsock->sk)
			if (smc->clcsock && smc->clcsock->sk) {
				rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR);
				rc1 = kernel_sock_shutdown(smc->clcsock,
							   SHUT_RDWR);
				rc = rc ? rc : rc1;
			}
		} else {
		} else {
			/* peer event has changed the state */
			/* peer event has changed the state */
			goto again;
			goto again;