netfilter: remove defensive check on malformed packets from raw sockets
Subsystems (2)
Pablo Neira Ayuso
maintainerPATCH v2 1/1 netfilter: remove defensive check on malformed packets from raw sockets
Users cannot forge malformed IPv4/IPv6 headers via raw sockets that they can inject into the stack. Specifically, not for IPv4 since 55888dfb6ba7 ("AF_RAW: Augment raw_send_hdrinc to expand skb to fit iphdr->ihl (v2)"). IPv6 raw sockets also ensure that packets have a well-formed IPv6 header available in the skbuff.
At quick glance, br_netfilter also validates layer 3 headers and it drops malformed both IPv4 and IPv6 packets.
Therefore, let's remove this defensive check all over the place.
Signed-off-by Pablo Neira Ayuso <[email protected]>
---
v2: add missing chunk in nf_tables_inet.c
net/ipv4/netfilter/iptable_filter.c | 6 ----- net/ipv4/netfilter/iptable_mangle.c | 5 ---- net/ipv4/netfilter/iptable_raw.c | 6 ----- net/ipv4/netfilter/iptable_security.c | 6 ----- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 5 ---- net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 10 -------- net/ipv4/netfilter/nf_tables_ipv4.c | 17 +------------ net/ipv4/netfilter/nft_chain_route_ipv4.c | 5 ---- net/ipv6/netfilter/ip6table_mangle.c | 8 ------ net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 5 ---- net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 8 ------ net/ipv6/netfilter/nf_tables_ipv6.c | 16 +----------- net/netfilter/nf_tables_inet.c | 34 +------------------------- 13 files changed, 3 insertions(+), 128 deletions(-)
net/ipv4/netfilter/iptable_filter.c +0 -6
@@ -38,12 +38,6 @@ static unsigned int iptable_filter_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { -if (state->hook ==NF_INET_LOCAL_OUT && - (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr ))) -/* root is playing with raw sockets. */ -return NF_ACCEPT ; -return ipt_do_table (skb, state, state->net->ipv4.iptable_filter); }
net/ipv4/netfilter/iptable_mangle.c +0 -5
@@ -49,11 +49,6 @@ ipt_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)u_int32_t mark;int err; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) -return NF_ACCEPT ; -/* Save things which could affect route */ mark = skb->mark; iph =ip_hdr (skb);
net/ipv4/netfilter/iptable_raw.c +0 -6
@@ -26,12 +26,6 @@ static unsigned int iptable_raw_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { -if (state->hook ==NF_INET_LOCAL_OUT && - (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr ))) -/* root is playing with raw sockets. */ -return NF_ACCEPT ; -return ipt_do_table (skb, state, state->net->ipv4.iptable_raw); }
net/ipv4/netfilter/iptable_security.c +0 -6
@@ -43,12 +43,6 @@ static unsigned int iptable_security_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { -if (state->hook ==NF_INET_LOCAL_OUT && - (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr ))) -/* Somebody is playing with raw sockets. */ -return NF_ACCEPT ; -return ipt_do_table (skb, state, state->net->ipv4.iptable_security); }
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +0 -5
@@ -154,11 +154,6 @@ static unsigned int ipv4_conntrack_local(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) -return NF_ACCEPT ; - if (ip_is_fragment(ip_hdr(skb))) /* IP_NODEFRAG setsockopt set */ return NF_ACCEPT;
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +0 -10
@@ -356,11 +356,6 @@ nf_nat_ipv4_out(void *priv, struct sk_buff *skb,#endif unsigned int ret; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) -return NF_ACCEPT ; - ret =nf_nat_ipv4_fn (priv, skb, state, do_chain);#ifdef CONFIG_XFRM if (ret != NF_DROP && ret != NF_STOLEN &&
@@ -396,11 +391,6 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,unsigned int ret;int err; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) -return NF_ACCEPT ; - ret =nf_nat_ipv4_fn (priv, skb, state, do_chain);if (ret !=NF_DROP && ret !=NF_STOLEN && (ct =nf_ct_get (skb, &ctinfo)) !=NULL ) {
net/ipv4/netfilter/nf_tables_ipv4.c +1 -16
@@ -30,21 +30,6 @@ static unsigned int nft_do_chain_ipv4(void *priv,return nft_do_chain (&pkt, priv); } -static unsigned int nft_ipv4_output (void *priv, -struct sk_buff *skb, -const struct nf_hook_state *state) -{ -if (unlikely (skb->len <sizeof (struct iphdr ) || -ip_hdr (skb)->ihl <sizeof (struct iphdr ) /4 )) { -if (net_ratelimit ()) -pr_info ("nf_tables_ipv4: ignoring short SOCK_RAW " -"packet\n" ); -return NF_ACCEPT ; - } - -return nft_do_chain_ipv4 (priv, skb, state); -} -static struct nft_af_info nft_af_ipv4__read_mostly = { .family =NFPROTO_IPV4 , .nhooks =NF_INET_NUMHOOKS ,
@@ -91,7 +76,7 @@ static const struct nf_chain_type filter_ipv4 = { (1 << NF_INET_POST_ROUTING), .hooks = { [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, - [NF_INET_LOCAL_OUT] = nft_ipv4_output, + [NF_INET_LOCAL_OUT] = nft_do_chain_ipv4, [NF_INET_FORWARD] = nft_do_chain_ipv4, [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, [NF_INET_POST_ROUTING] = nft_do_chain_ipv4,
net/ipv4/netfilter/nft_chain_route_ipv4.c +0 -5
@@ -33,11 +33,6 @@ static unsigned int nf_route_table_hook(void *priv,const struct iphdr *iph;int err; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) -return NF_ACCEPT ; -nft_set_pktinfo (&pkt, skb, state);nft_set_pktinfo_ipv4 (&pkt, skb);
net/ipv6/netfilter/ip6table_mangle.c +0 -8
@@ -42,14 +42,6 @@ ip6t_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)u_int8_t hop_limit;u_int32_t flowlabel, mark;int err; -#if 0 -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct iphdr ) || -ip_hdrlen (skb) <sizeof (struct iphdr )) { -net_warn_ratelimited ("ip6t_hook: happy cracking\n" ); -return NF_ACCEPT ; - } -#endif /* save source/dest address, mark, hoplimit, flowlabel, priority, */ memcpy (&saddr, &ipv6_hdr (skb)->saddr,sizeof (saddr));
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +0 -5
@@ -176,11 +176,6 @@ static unsigned int ipv6_conntrack_local(void *priv,struct sk_buff *skb, const struct nf_hook_state *state) { -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct ipv6hdr )) { -net_notice_ratelimited ("ipv6_conntrack_local: packet too short\n" ); -return NF_ACCEPT ; - } return nf_conntrack_in(state->net, PF_INET6, state->hook, skb); }
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +0 -8
@@ -369,10 +369,6 @@ nf_nat_ipv6_out(void *priv, struct sk_buff *skb,#endif unsigned int ret; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct ipv6hdr )) -return NF_ACCEPT ; - ret =nf_nat_ipv6_fn (priv, skb, state, do_chain);#ifdef CONFIG_XFRM if (ret != NF_DROP && ret != NF_STOLEN &&
@@ -408,10 +404,6 @@ nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,unsigned int ret;int err; -/* root is playing with raw sockets. */ -if (skb->len <sizeof (struct ipv6hdr )) -return NF_ACCEPT ; - ret =nf_nat_ipv6_fn (priv, skb, state, do_chain);if (ret !=NF_DROP && ret !=NF_STOLEN && (ct =nf_ct_get (skb, &ctinfo)) !=NULL ) {
net/ipv6/netfilter/nf_tables_ipv6.c +1 -15
@@ -28,20 +28,6 @@ static unsigned int nft_do_chain_ipv6(void *priv,return nft_do_chain (&pkt, priv); } -static unsigned int nft_ipv6_output (void *priv, -struct sk_buff *skb, -const struct nf_hook_state *state) -{ -if (unlikely (skb->len <sizeof (struct ipv6hdr ))) { -if (net_ratelimit ()) -pr_info ("nf_tables_ipv6: ignoring short SOCK_RAW " -"packet\n" ); -return NF_ACCEPT ; - } - -return nft_do_chain_ipv6 (priv, skb, state); -} -static struct nft_af_info nft_af_ipv6__read_mostly = { .family =NFPROTO_IPV6 , .nhooks =NF_INET_NUMHOOKS ,
@@ -88,7 +74,7 @@ static const struct nf_chain_type filter_ipv6 = { (1 << NF_INET_POST_ROUTING), .hooks = { [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, - [NF_INET_LOCAL_OUT] = nft_ipv6_output, + [NF_INET_LOCAL_OUT] = nft_do_chain_ipv6, [NF_INET_FORWARD] = nft_do_chain_ipv6, [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, [NF_INET_POST_ROUTING] = nft_do_chain_ipv6,
net/netfilter/nf_tables_inet.c +1 -33
@@ -38,38 +38,6 @@ static unsigned int nft_do_chain_inet(void *priv, struct sk_buff *skb,return nft_do_chain (&pkt, priv); } -static unsigned int nft_inet_output (void *priv,struct sk_buff *skb, -const struct nf_hook_state *state) -{ -struct nft_pktinfo pkt; - -nft_set_pktinfo (&pkt, skb, state); - -switch (state->pf) { -case NFPROTO_IPV4 : -if (unlikely (skb->len <sizeof (struct iphdr ) || -ip_hdr (skb)->ihl <sizeof (struct iphdr ) /4 )) { -if (net_ratelimit ()) -pr_info ("ignoring short SOCK_RAW packet\n" ); -return NF_ACCEPT ; - } -nft_set_pktinfo_ipv4 (&pkt, skb); -break ; -case NFPROTO_IPV6 : -if (unlikely (skb->len <sizeof (struct ipv6hdr ))) { -if (net_ratelimit ()) -pr_info ("ignoring short SOCK_RAW packet\n" ); -return NF_ACCEPT ; - } -nft_set_pktinfo_ipv6 (&pkt, skb); -break ; -default : -break ; - } - -return nft_do_chain (&pkt, priv); -} -static struct nft_af_info nft_af_inet__read_mostly = { .family =NFPROTO_INET , .nhooks =NF_INET_NUMHOOKS ,
@@ -116,7 +84,7 @@ static const struct nf_chain_type filter_inet = { (1 << NF_INET_POST_ROUTING), .hooks = { [NF_INET_LOCAL_IN] = nft_do_chain_inet, - [NF_INET_LOCAL_OUT] = nft_inet_output, + [NF_INET_LOCAL_OUT] = nft_do_chain_inet, [NF_INET_FORWARD] = nft_do_chain_inet, [NF_INET_PRE_ROUTING] = nft_do_chain_inet, [NF_INET_POST_ROUTING] = nft_do_chain_inet,
Signature · 1 line
2.11.0