Skip to contentSkip to conversation

nf_conntrack: validate crc32c on SCTP packets hitting PREROUTING hook

PATCH In review Davide Caratti 3 participants 5 messages Jan 2, 2017 – Jan 5, 2017

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover nf_conntrack: validate crc32c on SCTP packets hitting PREROUTING hook

unlike what happens with other protcols, conntrack entries are matched by SCTP packets even when crc32c is incorrect. Moreover, netfilter 'REJECT' target does not generate any ICMP on reception of SCTP packets, because it computes RFC 1624 checksum ad compares it with crc32c in the transport header, resulting in a systematic mismatch.

The above issues can be resolved by implementing .error() callback in SCTP conntrack helper. Patch 1 of this series lets LIBCRC32C be selected with NF_CT_PROTO_SCTP, to allow crc32c validation within nf_conntrack. Patch 2 implements .error() callback in nf_conntrack_l4proto_sctp{4,6}: like other protocols do with the Internet Checksum, sctp_error() validates crc32c in PREROUTING hook, updates the value of skb->ip_summed and returns the result of checksum validation to let conntrack core skip corrupted packets.

Davide Caratti (2):
netfilter: select LIBCRC32C together with SCTP conntrack
netfilter: conntrack: validate SCTP crc32c in PREROUTING

 net/netfilter/Kconfig                   |  2 +-
 net/netfilter/nf_conntrack_proto_sctp.c | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)
Signature · 1 line
2.7.4
#1 lore raw

PATCH 1/2 netfilter: select LIBCRC32C together with SCTP conntrack

nf_conntrack needs to compute crc32c when dealing with SCTP packets. Moreover, NF_NAT_PROTO_SCTP (currently selecting LIBCRC32C) can be enabled only if conntrack support for SCTP is enabled. Therefore, move enabling of kernel support for crc32c so that it is selected when NF_CT_PROTO_SCTP=y.

---
 net/netfilter/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/Kconfig +1 -1
index 63729b4..6d425e3 100644
@@ -162,6 +162,7 @@ config NF_CT_PROTO_SCTP
 	bool 'SCTP protocol connection tracking support'
 	depends on NETFILTER_ADVANCED
 	default y
+	select LIBCRC32C
 	help
 	  With this option enabled, the layer 3 independent connection
 	  tracking code will be able to do state tracking on SCTP connections.
@@ -397,7 +398,6 @@ config NF_NAT_PROTO_SCTP
 	bool
 	default NF_NAT && NF_CT_PROTO_SCTP
 	depends on NF_NAT && NF_CT_PROTO_SCTP
-	select LIBCRC32C
 
 config NF_NAT_AMANDA
 	tristate
Signature · 1 line
2.7.4
Reviewed-by on v1 1/2
#2 lore raw

Re: [PATCH nf-next 1/2] netfilter: select LIBCRC32C together with SCTP conntrack

Quoted 6 lines · Davide Caratti

nf_conntrack needs to compute crc32c when dealing with SCTP packets. Moreover, NF_NAT_PROTO_SCTP (currently selecting LIBCRC32C) can be enabled only if conntrack support for SCTP is enabled. Therefore, move enabling of kernel support for crc32c so that it is selected when NF_CT_PROTO_SCTP=y.

Quoted 32 lines
---
 net/netfilter/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/Kconfig +1 -1
index 63729b4..6d425e3 100644
@@ -162,6 +162,7 @@ config NF_CT_PROTO_SCTP
 	bool 'SCTP protocol connection tracking support'
 	depends on NETFILTER_ADVANCED
 	default y
+	select LIBCRC32C
 	help
 	  With this option enabled, the layer 3 independent connection
 	  tracking code will be able to do state tracking on SCTP connections.
@@ -397,7 +398,6 @@ config NF_NAT_PROTO_SCTP
 	bool
 	default NF_NAT && NF_CT_PROTO_SCTP
 	depends on NF_NAT && NF_CT_PROTO_SCTP
-	select LIBCRC32C
 
 config NF_NAT_AMANDA
 	tristate
Signature · 6 lines
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#3 lore raw

PATCH 2/2 netfilter: conntrack: validate SCTP crc32c in PREROUTING

In reply to Davide Caratti

implement sctp_error to let nf_conntrack_in validate crc32c on the packet transport header. Assign skb->ip_summed to CHECKSUM_UNNECESSARY and return NF_ACCEPT in case of successful validation; otherwise, return -NF_ACCEPT to let netfilter skip connection tracking, like other protocols do.

Besides preventing corrupted packets from matching conntrack entries, this fixes functionality of REJECT target: it was not generating any ICMP upon reception of SCTP packets, because it was computing RFC 1624 checksum on the packet and systematically mismatching crc32c in the SCTP header.

---
 net/netfilter/nf_conntrack_proto_sctp.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
net/netfilter/nf_conntrack_proto_sctp.c +32 -0
index a0efde3..44a6474 100644
@@ -22,7 +22,9 @@
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
+#include <net/sctp/checksum.h>
 
+#include <net/netfilter/nf_log.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
@@ -505,6 +507,34 @@ static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
 	return true;
 }
 
+static int sctp_error(struct net *net, struct nf_conn *tpl, struct sk_buff *skb,
+		      unsigned int dataoff, enum ip_conntrack_info *ctinfo,
+		      u8 pf, unsigned int hooknum)
+{
+	const struct sctphdr *sh;
+	struct sctphdr _sctph;
+	const char *logmsg;
+
+	sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
+	if (!sh) {
+		logmsg = "nf_ct_sctp: short packet ";
+		goto out_invalid;
+	}
+	if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
+	    skb->ip_summed == CHECKSUM_NONE) {
+		if (sh->checksum != sctp_compute_cksum(skb, dataoff)) {
+			logmsg = "nf_ct_sctp: bad CRC ";
+			goto out_invalid;
+		}
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	}
+	return NF_ACCEPT;
+out_invalid:
+	if (LOG_INVALID(net, IPPROTO_SCTP))
+		nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "%s", logmsg);
+	return -NF_ACCEPT;
+}
+
 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 
 #include <linux/netfilter/nfnetlink.h>
@@ -752,6 +782,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
 	.packet 		= sctp_packet,
 	.get_timeouts		= sctp_get_timeouts,
 	.new 			= sctp_new,
+	.error			= sctp_error,
 	.me 			= THIS_MODULE,
 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 	.to_nlattr		= sctp_to_nlattr,
@@ -786,6 +817,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
 	.packet 		= sctp_packet,
 	.get_timeouts		= sctp_get_timeouts,
 	.new 			= sctp_new,
+	.error			= sctp_error,
 	.me 			= THIS_MODULE,
 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 	.to_nlattr		= sctp_to_nlattr,
Signature · 1 line
2.7.4
#4 lore raw
In reply to Davide Caratti
Quoted 6 lines · Davide Caratti

unlike what happens with other protcols, conntrack entries are matched by SCTP packets even when crc32c is incorrect. Moreover, netfilter 'REJECT' target does not generate any ICMP on reception of SCTP packets, because it computes RFC 1624 checksum ad compares it with crc32c in the transport header, resulting in a systematic mismatch.

Quoted 7 lines

The above issues can be resolved by implementing .error() callback in SCTP conntrack helper. Patch 1 of this series lets LIBCRC32C be selected with NF_CT_PROTO_SCTP, to allow crc32c validation within nf_conntrack. Patch 2 implements .error() callback in nf_conntrack_l4proto_sctp{4,6}: like other protocols do with the Internet Checksum, sctp_error() validates crc32c in PREROUTING hook, updates the value of skb->ip_summed and returns the result of checksum validation to let conntrack core skip corrupted packets.

Series applied, thanks Davide.