aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-4.14/313-v4.16-netfilter-remove-defensive-check-on-malformed-packet.patch
diff options
context:
space:
mode:
authorRafał Miłecki <rafal@milecki.pl>2018-05-08 09:40:43 +0200
committerRafał Miłecki <rafal@milecki.pl>2018-05-08 09:42:07 +0200
commitf9dcdc7fefcab5ec9b15b0f3c87dfebef37ecaa3 (patch)
tree36fd6f2cc4324384f9af19994fb69a20d95f8daf /target/linux/generic/backport-4.14/313-v4.16-netfilter-remove-defensive-check-on-malformed-packet.patch
parent004cc22e4ef8187dd80d5d6be5a2575453ef3699 (diff)
downloadupstream-f9dcdc7fefcab5ec9b15b0f3c87dfebef37ecaa3.tar.gz
upstream-f9dcdc7fefcab5ec9b15b0f3c87dfebef37ecaa3.tar.bz2
upstream-f9dcdc7fefcab5ec9b15b0f3c87dfebef37ecaa3.zip
kernel: mark source kernel for netfilter backports
This helps keeping track on patches & adding new kernels in the future. Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Diffstat (limited to 'target/linux/generic/backport-4.14/313-v4.16-netfilter-remove-defensive-check-on-malformed-packet.patch')
-rw-r--r--target/linux/generic/backport-4.14/313-v4.16-netfilter-remove-defensive-check-on-malformed-packet.patch302
1 files changed, 302 insertions, 0 deletions
diff --git a/target/linux/generic/backport-4.14/313-v4.16-netfilter-remove-defensive-check-on-malformed-packet.patch b/target/linux/generic/backport-4.14/313-v4.16-netfilter-remove-defensive-check-on-malformed-packet.patch
new file mode 100644
index 0000000000..5e56d0dc49
--- /dev/null
+++ b/target/linux/generic/backport-4.14/313-v4.16-netfilter-remove-defensive-check-on-malformed-packet.patch
@@ -0,0 +1,302 @@
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+Date: Sat, 30 Dec 2017 22:41:46 +0100
+Subject: [PATCH] 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 <pablo@netfilter.org>
+---
+
+--- a/net/ipv4/netfilter/iptable_filter.c
++++ b/net/ipv4/netfilter/iptable_filter.c
+@@ -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);
+ }
+
+--- a/net/ipv4/netfilter/iptable_mangle.c
++++ b/net/ipv4/netfilter/iptable_mangle.c
+@@ -49,11 +49,6 @@ ipt_mangle_out(struct sk_buff *skb, cons
+ 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);
+--- a/net/ipv4/netfilter/iptable_raw.c
++++ b/net/ipv4/netfilter/iptable_raw.c
+@@ -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);
+ }
+
+--- a/net/ipv4/netfilter/iptable_security.c
++++ b/net/ipv4/netfilter/iptable_security.c
+@@ -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);
+ }
+
+--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+@@ -154,11 +154,6 @@ static unsigned int ipv4_conntrack_local
+ 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 */
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *tmpl;
+--- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
++++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
+@@ -355,11 +355,6 @@ nf_nat_ipv4_out(void *priv, struct sk_bu
+ #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 &&
+@@ -395,11 +390,6 @@ nf_nat_ipv4_local_fn(void *priv, struct
+ 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) {
+--- a/net/ipv4/netfilter/nf_tables_ipv4.c
++++ b/net/ipv4/netfilter/nf_tables_ipv4.c
+@@ -30,21 +30,6 @@ static unsigned int nft_do_chain_ipv4(vo
+ 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
+ (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,
+--- a/net/ipv4/netfilter/nft_chain_route_ipv4.c
++++ b/net/ipv4/netfilter/nft_chain_route_ipv4.c
+@@ -33,11 +33,6 @@ static unsigned int nf_route_table_hook(
+ 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);
+
+--- a/net/ipv6/netfilter/ip6table_mangle.c
++++ b/net/ipv6/netfilter/ip6table_mangle.c
+@@ -42,14 +42,6 @@ ip6t_mangle_out(struct sk_buff *skb, con
+ 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));
+--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
++++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+@@ -176,11 +176,6 @@ static unsigned int ipv6_conntrack_local
+ 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);
+ }
+
+--- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
++++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
+@@ -372,10 +372,6 @@ nf_nat_ipv6_out(void *priv, struct sk_bu
+ #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 &&
+@@ -411,10 +407,6 @@ nf_nat_ipv6_local_fn(void *priv, struct
+ 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) {
+--- a/net/ipv6/netfilter/nf_tables_ipv6.c
++++ b/net/ipv6/netfilter/nf_tables_ipv6.c
+@@ -28,20 +28,6 @@ static unsigned int nft_do_chain_ipv6(vo
+ 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
+ (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,
+--- a/net/netfilter/nf_tables_inet.c
++++ b/net/netfilter/nf_tables_inet.c
+@@ -38,38 +38,6 @@ static unsigned int nft_do_chain_inet(vo
+ 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
+ (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,