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

Bug#917533: linux-image-4.9.0-8-marvell: nfs-kernel-server leaks ports and triggers rkhunter/unhide-tcp



On Fri, 2018-12-28 at 09:58 +0000, Ian Campbell wrote:
> I'm next going to reboot into my locally built kernel with the (likely/hopeful)
> fix applied. I'll follow up in a few days (maybe a week to be sure) if I don't
> see this issue recurring. If it is looking positive at that point I'll also
> ping davem and Trond to requests upstream backports.

It's been a week and I've not had recurrence of the issue, previously I
was seeing it every 2-3 days.

I'm attaching the patch I was using which I described earlier as:

> pkg-kernel git's stretch branch at d9cfad89feb2 ('Revert
> "tracing: Use strlcpy() instead of strcpy() in 
> __trace_find_cmdline()"') plus backports of:
> 
> 8d1b8c62e080 SUNRPC: Refactor TCP socket timeout code into a helper function
> 3ffbc1d65583 net/sunrpc/xprt_sock: fix regression in connection error reporting.
> 9b30889c548a SUNRPC: Ensure we always close the socket after a connection shuts down

I'll also ping upstream about a possible stable backport shortly.

Ian.
From 3f47e65ec1a5b9c456cda19655759d43ec476988 Mon Sep 17 00:00:00 2001
From: Ian Campbell <ijc@hellion.org.uk>
Date: Tue, 25 Dec 2018 09:28:51 +0000
Subject: [PATCH] Backport patches to stop NFS kernel server leak

This tweaks rkhunters hidden port checks
---
 debian/changelog                              |  3 +
 ...-always-close-the-socket-after-a-con.patch | 82 +++++++++++++++++
 ...TCP-socket-timeout-code-into-a-helpe.patch | 88 +++++++++++++++++++
 ...sock-fix-regression-in-connection-er.patch | 50 +++++++++++
 debian/patches/series                         |  3 +
 5 files changed, 226 insertions(+)
 create mode 100644 debian/patches/bugfix/all/SUNRPC-Ensure-we-always-close-the-socket-after-a-con.patch
 create mode 100644 debian/patches/bugfix/all/SUNRPC-Refactor-TCP-socket-timeout-code-into-a-helpe.patch
 create mode 100644 debian/patches/bugfix/all/net-sunrpc-xprt_sock-fix-regression-in-connection-er.patch

diff --git a/debian/changelog b/debian/changelog
index da70135267ba..1c6b7e88734a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -734,6 +734,9 @@ linux (4.9.144-1) UNRELEASED; urgency=medium
   * Refresh inet-frags-avoid-abi-change-in-4.9.134.patch for context changes
     in 4.9.142
 
+  [ Ian Campbell ]
+  * Backport NFS fixes to not trigger rkhunter hidden port scan.
+
  -- Ben Hutchings <ben@decadent.org.uk>  Sat, 08 Dec 2018 20:53:57 +0000
 
 linux (4.9.135-1) stretch; urgency=medium
diff --git a/debian/patches/bugfix/all/SUNRPC-Ensure-we-always-close-the-socket-after-a-con.patch b/debian/patches/bugfix/all/SUNRPC-Ensure-we-always-close-the-socket-after-a-con.patch
new file mode 100644
index 000000000000..5e99fe42a090
--- /dev/null
+++ b/debian/patches/bugfix/all/SUNRPC-Ensure-we-always-close-the-socket-after-a-con.patch
@@ -0,0 +1,82 @@
+From b0494c706325fdd1ec6b4fdef1d1f0cc12f4f4ad Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Mon, 5 Feb 2018 10:20:06 -0500
+Subject: [PATCH 3/3] SUNRPC: Ensure we always close the socket after a
+ connection shuts down
+
+Ensure that we release the TCP socket once it is in the TCP_CLOSE or
+TCP_TIME_WAIT state (and only then) so that we don't confuse rkhunter
+and its ilk.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+(cherry picked from commit 9b30889c548a4d45bfe6226e58de32504c1d682f)
+---
+ net/sunrpc/xprtsock.c | 23 ++++++++++-------------
+ 1 file changed, 10 insertions(+), 13 deletions(-)
+
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index d5422d479a22..5be417ed1311 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -798,13 +798,6 @@ static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt)
+ 	smp_mb__after_atomic();
+ }
+ 
+-static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+-{
+-	xs_sock_reset_connection_flags(xprt);
+-	/* Mark transport as closed and wake up all pending tasks */
+-	xprt_disconnect_done(xprt);
+-}
+-
+ /**
+  * xs_error_report - callback to handle TCP socket state errors
+  * @sk: socket
+@@ -824,9 +817,6 @@ static void xs_error_report(struct sock *sk)
+ 	err = -sk->sk_err;
+ 	if (err == 0)
+ 		goto out;
+-	/* Is this a reset event? */
+-	if (sk->sk_state == TCP_CLOSE)
+-		xs_sock_mark_closed(xprt);
+ 	dprintk("RPC:       xs_error_report client %p, error=%d...\n",
+ 			xprt, -err);
+ 	trace_rpc_socket_error(xprt, sk->sk_socket, err);
+@@ -1619,9 +1609,11 @@ static void xs_tcp_state_change(struct sock *sk)
+ 		if (test_and_clear_bit(XPRT_SOCK_CONNECTING,
+ 					&transport->sock_state))
+ 			xprt_clear_connecting(xprt);
++		clear_bit(XPRT_CLOSING, &xprt->state);
+ 		if (sk->sk_err)
+ 			xprt_wake_pending_tasks(xprt, -sk->sk_err);
+-		xs_sock_mark_closed(xprt);
++		/* Trigger the socket release */
++		xs_tcp_force_close(xprt);
+ 	}
+  out:
+ 	read_unlock_bh(&sk->sk_callback_lock);
+@@ -2227,14 +2219,19 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt)
+ {
+ 	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+ 	struct socket *sock = transport->sock;
++	int skst = transport->inet ? transport->inet->sk_state : TCP_CLOSE;
+ 
+ 	if (sock == NULL)
+ 		return;
+-	if (xprt_connected(xprt)) {
++	switch (skst) {
++	default:
+ 		kernel_sock_shutdown(sock, SHUT_RDWR);
+ 		trace_rpc_socket_shutdown(xprt, sock);
+-	} else
++		break;
++	case TCP_CLOSE:
++	case TCP_TIME_WAIT:
+ 		xs_reset_transport(transport);
++	}
+ }
+ 
+ static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
+-- 
+2.19.2
+
diff --git a/debian/patches/bugfix/all/SUNRPC-Refactor-TCP-socket-timeout-code-into-a-helpe.patch b/debian/patches/bugfix/all/SUNRPC-Refactor-TCP-socket-timeout-code-into-a-helpe.patch
new file mode 100644
index 000000000000..6c340ac30cc1
--- /dev/null
+++ b/debian/patches/bugfix/all/SUNRPC-Refactor-TCP-socket-timeout-code-into-a-helpe.patch
@@ -0,0 +1,88 @@
+From d85eb2e56e66f56207d8d55972d456891b45b1ec Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Wed, 8 Feb 2017 11:17:53 -0500
+Subject: [PATCH 1/3] SUNRPC: Refactor TCP socket timeout code into a helper
+ function
+
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+(cherry picked from commit 8d1b8c62e0805af7df900ef121389778d2126997)
+---
+ net/sunrpc/xprtsock.c | 45 +++++++++++++++++++++++++------------------
+ 1 file changed, 26 insertions(+), 19 deletions(-)
+
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index 1bf9153004cd..f2b769891b2b 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -2235,6 +2235,31 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt)
+ 		xs_reset_transport(transport);
+ }
+ 
++static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
++		struct socket *sock)
++{
++	unsigned int keepidle = DIV_ROUND_UP(xprt->timeout->to_initval, HZ);
++	unsigned int keepcnt = xprt->timeout->to_retries + 1;
++	unsigned int opt_on = 1;
++	unsigned int timeo;
++
++	/* TCP Keepalive options */
++	kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
++			(char *)&opt_on, sizeof(opt_on));
++	kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,
++			(char *)&keepidle, sizeof(keepidle));
++	kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
++			(char *)&keepidle, sizeof(keepidle));
++	kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
++			(char *)&keepcnt, sizeof(keepcnt));
++
++	/* TCP user timeout (see RFC5482) */
++	timeo = jiffies_to_msecs(xprt->timeout->to_initval) *
++		(xprt->timeout->to_retries + 1);
++	kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT,
++			(char *)&timeo, sizeof(timeo));
++}
++
+ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
+ {
+ 	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+@@ -2242,22 +2267,8 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
+ 
+ 	if (!transport->inet) {
+ 		struct sock *sk = sock->sk;
+-		unsigned int keepidle = xprt->timeout->to_initval / HZ;
+-		unsigned int keepcnt = xprt->timeout->to_retries + 1;
+-		unsigned int opt_on = 1;
+-		unsigned int timeo;
+ 		unsigned int addr_pref = IPV6_PREFER_SRC_PUBLIC;
+ 
+-		/* TCP Keepalive options */
+-		kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
+-				(char *)&opt_on, sizeof(opt_on));
+-		kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,
+-				(char *)&keepidle, sizeof(keepidle));
+-		kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
+-				(char *)&keepidle, sizeof(keepidle));
+-		kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
+-				(char *)&keepcnt, sizeof(keepcnt));
+-
+ 		/* Avoid temporary address, they are bad for long-lived
+ 		 * connections such as NFS mounts.
+ 		 * RFC4941, section 3.6 suggests that:
+@@ -2268,11 +2279,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
+ 		kernel_setsockopt(sock, SOL_IPV6, IPV6_ADDR_PREFERENCES,
+ 				(char *)&addr_pref, sizeof(addr_pref));
+ 
+-		/* TCP user timeout (see RFC5482) */
+-		timeo = jiffies_to_msecs(xprt->timeout->to_initval) *
+-			(xprt->timeout->to_retries + 1);
+-		kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT,
+-				(char *)&timeo, sizeof(timeo));
++		xs_tcp_set_socket_timeouts(xprt, sock);
+ 
+ 		write_lock_bh(&sk->sk_callback_lock);
+ 
+-- 
+2.19.2
+
diff --git a/debian/patches/bugfix/all/net-sunrpc-xprt_sock-fix-regression-in-connection-er.patch b/debian/patches/bugfix/all/net-sunrpc-xprt_sock-fix-regression-in-connection-er.patch
new file mode 100644
index 000000000000..555a2aa0bb1e
--- /dev/null
+++ b/debian/patches/bugfix/all/net-sunrpc-xprt_sock-fix-regression-in-connection-er.patch
@@ -0,0 +1,50 @@
+From fe460ecd8dde88f9a6955420678b44e2f402995d Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.com>
+Date: Wed, 19 Jul 2017 14:05:01 +1000
+Subject: [PATCH 2/3] net/sunrpc/xprt_sock: fix regression in connection error
+ reporting.
+
+Commit 3d4762639dd3 ("tcp: remove poll() flakes when receiving
+RST") in v4.12 changed the order in which ->sk_state_change()
+and ->sk_error_report() are called when a socket is shut
+down - sk_state_change() is now called first.
+
+This causes xs_tcp_state_change() -> xs_sock_mark_closed() ->
+xprt_disconnect_done() to wake all pending tasked with -EAGAIN.
+When the ->sk_error_report() callback arrives, it is too late to
+pass the error on, and it is lost.
+
+As easy way to demonstrate the problem caused is to try to start
+rpc.nfsd while rcpbind isn't running.
+nfsd will attempt a tcp connection to rpcbind.  A ECONNREFUSED
+error is returned, but sunrpc code loses the error and keeps
+retrying.  If it saw the ECONNREFUSED, it would abort.
+
+To fix this, handle the sk->sk_err in the TCP_CLOSE branch of
+xs_tcp_state_change().
+
+Fixes: 3d4762639dd3 ("tcp: remove poll() flakes when receiving RST")
+Cc: stable@vger.kernel.org (v4.12)
+Signed-off-by: NeilBrown <neilb@suse.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+(cherry picked from commit 3ffbc1d65583394be12801655781dd2b079ce169)
+---
+ net/sunrpc/xprtsock.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index f2b769891b2b..d5422d479a22 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -1619,6 +1619,8 @@ static void xs_tcp_state_change(struct sock *sk)
+ 		if (test_and_clear_bit(XPRT_SOCK_CONNECTING,
+ 					&transport->sock_state))
+ 			xprt_clear_connecting(xprt);
++		if (sk->sk_err)
++			xprt_wake_pending_tasks(xprt, -sk->sk_err);
+ 		xs_sock_mark_closed(xprt);
+ 	}
+  out:
+-- 
+2.19.2
+
diff --git a/debian/patches/series b/debian/patches/series
index 95b0dfa575f3..c9abd00cccee 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -103,6 +103,9 @@ bugfix/x86/mmap-add-an-exception-to-the-stack-gap-for-hotspot-jvm.patch
 bugfix/all/xen-time-do-not-decrease-steal-time-after-live-migra.patch
 bugfix/all/nfsd-increase-DRC-cache-limit.patch
 bugfix/all/netfilter-xt_hashlimit-fix-integer-divide-round-to-z.patch
+bugfix/all/SUNRPC-Refactor-TCP-socket-timeout-code-into-a-helpe.patch
+bugfix/all/net-sunrpc-xprt_sock-fix-regression-in-connection-er.patch
+bugfix/all/SUNRPC-Ensure-we-always-close-the-socket-after-a-con.patch
 
 # Miscellaneous features
 features/all/netfilter-nft_ct-add-notrack-support.patch
-- 
2.19.2


Reply to: