Blob Blame History Raw
From: Florian Westphal <fw@strlen.de>
Date: Fri, 28 Jan 2022 13:13:32 +0100
Subject: [PATCH] netfilter: conntrack: don't refresh sctp entries in closed state
Patch-mainline: v5.17-rc4
Git-commit: 77b337196a9d87f3d6bb9b07c0436ecafbffda1e
References: bsc#1197389

Vivek Thrivikraman reported:
 An SCTP server application which is accessed continuously by client
 application.
 When the session disconnects the client retries to establish a connection.
 After restart of SCTP server application the session is not established
 because of stale conntrack entry with connection state CLOSED as below.

 (removing this entry manually established new connection):

 sctp 9 CLOSED src=10.141.189.233 [..]  [ASSURED]

Just skip timeout update of closed entries, we don't want them to
stay around forever.

SUSE-NOTE: This patch depends on cc5453a5b7e90c39f713091a7ebc53c1f87d1700:
netfilter: conntrack: allow sctp hearbeat after connection re-use

That patch breaks KABI on 15-SP2, only the 'ignore' boolean variable is needed
here, so it was added to this patch. In case backport of the mentioned patch is
needed, this one needs to be refreshed

Reported-and-tested-by: Vivek Thrivikraman <vivek.thrivikraman@est.tech>
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1579
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Ali Abdallah <ali.abdallah@suse.com>
---
 net/netfilter/nf_conntrack_proto_sctp.c |   14 ++++++++++++++
 1 file changed, 14 insertions(+)

--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -369,6 +369,7 @@ int nf_conntrack_sctp_packet(struct nf_c
 	u_int32_t offset, count;
 	unsigned int *timeouts;
 	unsigned long map[256 / sizeof(unsigned long)] = { 0 };
+	bool ignore = false;
 
 	if (sctp_error(skb, dataoff, state))
 		return -NF_ACCEPT;
@@ -462,6 +463,15 @@ int nf_conntrack_sctp_packet(struct nf_c
 			pr_debug("Setting vtag %x for dir %d\n",
 				 ih->init_tag, !dir);
 			ct->proto.sctp.vtag[!dir] = ih->init_tag;
+
+			/* don't renew timeout on init retransmit so
+			 * port reuse by client or NAT middlebox cannot
+			 * keep entry alive indefinitely (incl. nat info).
+			 */
+			if (new_state == SCTP_CONNTRACK_CLOSED &&
+			    old_state == SCTP_CONNTRACK_CLOSED &&
+			    nf_ct_is_confirmed(ct))
+				ignore = true;
 		}
 
 		ct->proto.sctp.state = new_state;
@@ -470,6 +480,10 @@ int nf_conntrack_sctp_packet(struct nf_c
 	}
 	spin_unlock_bh(&ct->lock);
 
+	/* allow but do not refresh timeout */
+	if (ignore)
+		return NF_ACCEPT;
+
 	timeouts = nf_ct_timeout_lookup(ct);
 	if (!timeouts)
 		timeouts = nf_sctp_pernet(nf_ct_net(ct))->timeouts;