netfilter: conntrack: validate SCTP crc32c in PREROUTING
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. Signed-off-by: Davide Caratti <dcaratti@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
300ae14946
commit
cf6e007eef
@ -22,7 +22,9 @@
|
|||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/interrupt.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.h>
|
||||||
#include <net/netfilter/nf_conntrack_l4proto.h>
|
#include <net/netfilter/nf_conntrack_l4proto.h>
|
||||||
#include <net/netfilter/nf_conntrack_ecache.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;
|
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)
|
#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
|
||||||
|
|
||||||
#include <linux/netfilter/nfnetlink.h>
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
@ -752,6 +782,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
|
|||||||
.packet = sctp_packet,
|
.packet = sctp_packet,
|
||||||
.get_timeouts = sctp_get_timeouts,
|
.get_timeouts = sctp_get_timeouts,
|
||||||
.new = sctp_new,
|
.new = sctp_new,
|
||||||
|
.error = sctp_error,
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
|
#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
|
||||||
.to_nlattr = sctp_to_nlattr,
|
.to_nlattr = sctp_to_nlattr,
|
||||||
@ -786,6 +817,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
|
|||||||
.packet = sctp_packet,
|
.packet = sctp_packet,
|
||||||
.get_timeouts = sctp_get_timeouts,
|
.get_timeouts = sctp_get_timeouts,
|
||||||
.new = sctp_new,
|
.new = sctp_new,
|
||||||
|
.error = sctp_error,
|
||||||
.me = THIS_MODULE,
|
.me = THIS_MODULE,
|
||||||
#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
|
#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
|
||||||
.to_nlattr = sctp_to_nlattr,
|
.to_nlattr = sctp_to_nlattr,
|
||||||
|
Loading…
Reference in New Issue
Block a user