* [PATCH 0/6] Netfilter/IPVS fixes for net
@ 2013-10-01 9:08 Pablo Neira Ayuso
2013-10-01 16:39 ` David Miller
0 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2013-10-01 9:08 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
Hi David,
The following patchset contains Netfilter/IPVS fixes for your net
tree, they are:
* Fix BUG_ON splat due to malformed TCP packets seen by synproxy, from
Patrick McHardy.
* Fix possible weight overflow in lblc and lblcr schedulers due to
32-bits arithmetics, from Simon Kirby.
* Fix possible memory access race in the lblc and lblcr schedulers,
introduced when it was converted to use RCU, two patches from
Julian Anastasov.
* Fix hard dependency on CPU 0 when reading per-cpu stats in the
rate estimator, from Julian Anastasov.
* Fix race that may lead to object use after release, when invoking
ipvsadm -C && ipvsadm -R, introduced when adding RCU, from Julian
Anastasov.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master
Thanks!
----------------------------------------------------------------
The following changes since commit 61c5923a2f2d8ab98a1e3c76f17e0f4a871ec75b:
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf (2013-09-17 20:22:53 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master
for you to fetch changes up to f4a87e7bd2eaef26a3ca25437ce8b807de2966ad:
netfilter: synproxy: fix BUG_ON triggered by corrupt TCP packets (2013-09-30 12:44:38 +0200)
----------------------------------------------------------------
Julian Anastasov (4):
ipvs: make the service replacement more robust
ipvs: do not use dest after ip_vs_dest_put in LBLC
ipvs: do not use dest after ip_vs_dest_put in LBLCR
ipvs: stats should not depend on CPU 0
Patrick McHardy (1):
netfilter: synproxy: fix BUG_ON triggered by corrupt TCP packets
Simon Kirby (1):
ipvs: fix overflow on dest weight multiply
include/net/ip_vs.h | 9 +--
include/net/netfilter/nf_conntrack_synproxy.h | 2 +-
net/ipv4/netfilter/ipt_SYNPROXY.c | 10 ++-
net/ipv6/netfilter/ip6t_SYNPROXY.c | 10 ++-
net/netfilter/ipvs/ip_vs_core.c | 12 +++-
net/netfilter/ipvs/ip_vs_ctl.c | 86 ++++++++++---------------
net/netfilter/ipvs/ip_vs_est.c | 4 +-
net/netfilter/ipvs/ip_vs_lblc.c | 72 ++++++++++-----------
net/netfilter/ipvs/ip_vs_lblcr.c | 62 ++++++++----------
net/netfilter/ipvs/ip_vs_nq.c | 8 +--
net/netfilter/ipvs/ip_vs_sed.c | 8 +--
net/netfilter/ipvs/ip_vs_wlc.c | 6 +-
net/netfilter/nf_synproxy_core.c | 12 ++--
13 files changed, 143 insertions(+), 158 deletions(-)
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 0/6] Netfilter/IPVS fixes for net
2013-10-01 9:08 [PATCH 0/6] Netfilter/IPVS " Pablo Neira Ayuso
@ 2013-10-01 16:39 ` David Miller
0 siblings, 0 replies; 14+ messages in thread
From: David Miller @ 2013-10-01 16:39 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Tue, 1 Oct 2013 11:08:25 +0200
> The following patchset contains Netfilter/IPVS fixes for your net
> tree, they are:
>
> * Fix BUG_ON splat due to malformed TCP packets seen by synproxy, from
> Patrick McHardy.
>
> * Fix possible weight overflow in lblc and lblcr schedulers due to
> 32-bits arithmetics, from Simon Kirby.
>
> * Fix possible memory access race in the lblc and lblcr schedulers,
> introduced when it was converted to use RCU, two patches from
> Julian Anastasov.
>
> * Fix hard dependency on CPU 0 when reading per-cpu stats in the
> rate estimator, from Julian Anastasov.
>
> * Fix race that may lead to object use after release, when invoking
> ipvsadm -C && ipvsadm -R, introduced when adding RCU, from Julian
> Anastasov.
>
> You can pull these changes from:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master
Pulled, thanks Pablo.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 0/6] netfilter/ipvs fixes for net
@ 2014-10-31 12:18 Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 1/6] ipvs: Avoid null-pointer deref in debug code Pablo Neira Ayuso
` (6 more replies)
0 siblings, 7 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-10-31 12:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
Hi David,
The following patchset contains fixes for netfilter/ipvs. This round of
fixes is larger than usual at this stage, specifically because of the
nf_tables bridge reject fixes that I would like to see in 3.18. The
patches are:
1) Fix a null-pointer dereference that may occur when logging
errors. This problem was introduced by 4a4739d56b0 ("ipvs: Pull
out crosses_local_route_boundary logic") in v3.17-rc5.
2) Update hook mask in nft_reject_bridge so we can also filter out
packets from there. This fixes 36d2af5 ("netfilter: nf_tables: allow
to filter from prerouting and postrouting"), which needs this chunk
to work.
3) Two patches to refactor common code to forge the IPv4 and IPv6
reject packets from the bridge. These are required by the nf_tables
reject bridge fix.
4) Fix nft_reject_bridge by avoiding the use of the IP stack to reject
packets from the bridge. The idea is to forge the reject packets and
inject them to the original port via br_deliver() which is now
exported for that purpose.
5) Restrict nft_reject_bridge to bridge prerouting and input hooks.
the original skbuff may cloned after prerouting when the bridge stack
needs to flood it to several bridge ports, it is too late to reject
the traffic.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
Thanks!
----------------------------------------------------------------
The following changes since commit 7965ee93719921ea5978f331da653dfa2d7b99f5:
netfilter: nft_compat: fix wrong target lookup in nft_target_select_ops() (2014-10-27 22:17:46 +0100)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master
for you to fetch changes up to 127917c29a432c3b798e014a1714e9c1af0f87fe:
netfilter: nft_reject_bridge: restrict reject to prerouting and input (2014-10-31 12:50:09 +0100)
----------------------------------------------------------------
Alex Gartrell (1):
ipvs: Avoid null-pointer deref in debug code
Pablo Neira Ayuso (5):
netfilter: nf_tables_bridge: update hook_mask to allow {pre,post}routing
netfilter: nf_reject_ipv4: split nf_send_reset() in smaller functions
netfilter: nf_reject_ipv6: split nf_send_reset6() in smaller functions
netfilter: nft_reject_bridge: don't use IP stack to reject traffic
netfilter: nft_reject_bridge: restrict reject to prerouting and input
include/net/netfilter/ipv4/nf_reject.h | 10 +
include/net/netfilter/ipv6/nf_reject.h | 10 +
net/bridge/br_forward.c | 1 +
net/bridge/netfilter/nf_tables_bridge.c | 6 +-
net/bridge/netfilter/nft_reject_bridge.c | 296 ++++++++++++++++++++++++++++--
net/ipv4/netfilter/nf_reject_ipv4.c | 88 ++++++---
net/ipv6/netfilter/nf_reject_ipv6.c | 175 +++++++++++-------
net/netfilter/ipvs/ip_vs_xmit.c | 4 +-
8 files changed, 483 insertions(+), 107 deletions(-)
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/6] ipvs: Avoid null-pointer deref in debug code
2014-10-31 12:18 [PATCH 0/6] netfilter/ipvs fixes for net Pablo Neira Ayuso
@ 2014-10-31 12:18 ` Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 2/6] netfilter: nf_tables_bridge: update hook_mask to allow {pre,post}routing Pablo Neira Ayuso
` (5 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-10-31 12:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
From: Alex Gartrell <agartrell@fb.com>
Use daddr instead of reaching into dest.
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Alex Gartrell <agartrell@fb.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
net/netfilter/ipvs/ip_vs_xmit.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 91f17c1..437a366 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -316,7 +316,7 @@ __ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode,
local))) {
IP_VS_DBG_RL("We are crossing local and non-local addresses"
- " daddr=%pI4\n", &dest->addr.ip);
+ " daddr=%pI4\n", &daddr);
goto err_put;
}
@@ -458,7 +458,7 @@ __ip_vs_get_out_rt_v6(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode,
local))) {
IP_VS_DBG_RL("We are crossing local and non-local addresses"
- " daddr=%pI6\n", &dest->addr.in6);
+ " daddr=%pI6\n", daddr);
goto err_put;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/6] netfilter: nf_tables_bridge: update hook_mask to allow {pre,post}routing
2014-10-31 12:18 [PATCH 0/6] netfilter/ipvs fixes for net Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 1/6] ipvs: Avoid null-pointer deref in debug code Pablo Neira Ayuso
@ 2014-10-31 12:18 ` Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 3/6] netfilter: nf_reject_ipv4: split nf_send_reset() in smaller functions Pablo Neira Ayuso
` (4 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-10-31 12:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
Fixes: 36d2af5 ("netfilter: nf_tables: allow to filter from prerouting and postrouting")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/bridge/netfilter/nf_tables_bridge.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index da17a5e..074c557 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -75,9 +75,11 @@ static const struct nf_chain_type filter_bridge = {
.type = NFT_CHAIN_T_DEFAULT,
.family = NFPROTO_BRIDGE,
.owner = THIS_MODULE,
- .hook_mask = (1 << NF_BR_LOCAL_IN) |
+ .hook_mask = (1 << NF_BR_PRE_ROUTING) |
+ (1 << NF_BR_LOCAL_IN) |
(1 << NF_BR_FORWARD) |
- (1 << NF_BR_LOCAL_OUT),
+ (1 << NF_BR_LOCAL_OUT) |
+ (1 << NF_BR_POST_ROUTING),
};
static int __init nf_tables_bridge_init(void)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/6] netfilter: nf_reject_ipv4: split nf_send_reset() in smaller functions
2014-10-31 12:18 [PATCH 0/6] netfilter/ipvs fixes for net Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 1/6] ipvs: Avoid null-pointer deref in debug code Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 2/6] netfilter: nf_tables_bridge: update hook_mask to allow {pre,post}routing Pablo Neira Ayuso
@ 2014-10-31 12:18 ` Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 4/6] netfilter: nf_reject_ipv6: split nf_send_reset6() " Pablo Neira Ayuso
` (3 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-10-31 12:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
That can be reused by the reject bridge expression to build the reject
packet. The new functions are:
* nf_reject_ip_tcphdr_get(): to sanitize and to obtain the TCP header.
* nf_reject_iphdr_put(): to build the IPv4 header.
* nf_reject_ip_tcphdr_put(): to build the TCP header.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/ipv4/nf_reject.h | 10 ++++
net/ipv4/netfilter/nf_reject_ipv4.c | 88 ++++++++++++++++++++++----------
2 files changed, 72 insertions(+), 26 deletions(-)
diff --git a/include/net/netfilter/ipv4/nf_reject.h b/include/net/netfilter/ipv4/nf_reject.h
index e842719..03e928a 100644
--- a/include/net/netfilter/ipv4/nf_reject.h
+++ b/include/net/netfilter/ipv4/nf_reject.h
@@ -1,6 +1,8 @@
#ifndef _IPV4_NF_REJECT_H
#define _IPV4_NF_REJECT_H
+#include <linux/skbuff.h>
+#include <net/ip.h>
#include <net/icmp.h>
static inline void nf_send_unreach(struct sk_buff *skb_in, int code)
@@ -10,4 +12,12 @@ static inline void nf_send_unreach(struct sk_buff *skb_in, int code)
void nf_send_reset(struct sk_buff *oldskb, int hook);
+const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb,
+ struct tcphdr *_oth, int hook);
+struct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb,
+ const struct sk_buff *oldskb,
+ __be16 protocol, int ttl);
+void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb,
+ const struct tcphdr *oth);
+
#endif /* _IPV4_NF_REJECT_H */
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c
index 92b303d..1baaa83 100644
--- a/net/ipv4/netfilter/nf_reject_ipv4.c
+++ b/net/ipv4/netfilter/nf_reject_ipv4.c
@@ -12,43 +12,39 @@
#include <net/route.h>
#include <net/dst.h>
#include <linux/netfilter_ipv4.h>
+#include <net/netfilter/ipv4/nf_reject.h>
-/* Send RST reply */
-void nf_send_reset(struct sk_buff *oldskb, int hook)
+const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb,
+ struct tcphdr *_oth, int hook)
{
- struct sk_buff *nskb;
- const struct iphdr *oiph;
- struct iphdr *niph;
const struct tcphdr *oth;
- struct tcphdr _otcph, *tcph;
/* IP header checks: fragment. */
if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
- return;
+ return NULL;
oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
- sizeof(_otcph), &_otcph);
+ sizeof(struct tcphdr), _oth);
if (oth == NULL)
- return;
+ return NULL;
/* No RST for RST. */
if (oth->rst)
- return;
-
- if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
- return;
+ return NULL;
/* Check checksum */
if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
- return;
- oiph = ip_hdr(oldskb);
+ return NULL;
- nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
- LL_MAX_HEADER, GFP_ATOMIC);
- if (!nskb)
- return;
+ return oth;
+}
+EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_get);
- skb_reserve(nskb, LL_MAX_HEADER);
+struct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb,
+ const struct sk_buff *oldskb,
+ __be16 protocol, int ttl)
+{
+ struct iphdr *niph, *oiph = ip_hdr(oldskb);
skb_reset_network_header(nskb);
niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
@@ -57,10 +53,23 @@ void nf_send_reset(struct sk_buff *oldskb, int hook)
niph->tos = 0;
niph->id = 0;
niph->frag_off = htons(IP_DF);
- niph->protocol = IPPROTO_TCP;
+ niph->protocol = protocol;
niph->check = 0;
niph->saddr = oiph->daddr;
niph->daddr = oiph->saddr;
+ niph->ttl = ttl;
+
+ nskb->protocol = htons(ETH_P_IP);
+
+ return niph;
+}
+EXPORT_SYMBOL_GPL(nf_reject_iphdr_put);
+
+void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb,
+ const struct tcphdr *oth)
+{
+ struct iphdr *niph = ip_hdr(nskb);
+ struct tcphdr *tcph;
skb_reset_transport_header(nskb);
tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
@@ -69,9 +78,9 @@ void nf_send_reset(struct sk_buff *oldskb, int hook)
tcph->dest = oth->source;
tcph->doff = sizeof(struct tcphdr) / 4;
- if (oth->ack)
+ if (oth->ack) {
tcph->seq = oth->ack_seq;
- else {
+ } else {
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
oldskb->len - ip_hdrlen(oldskb) -
(oth->doff << 2));
@@ -84,16 +93,43 @@ void nf_send_reset(struct sk_buff *oldskb, int hook)
nskb->ip_summed = CHECKSUM_PARTIAL;
nskb->csum_start = (unsigned char *)tcph - nskb->head;
nskb->csum_offset = offsetof(struct tcphdr, check);
+}
+EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put);
+
+/* Send RST reply */
+void nf_send_reset(struct sk_buff *oldskb, int hook)
+{
+ struct sk_buff *nskb;
+ const struct iphdr *oiph;
+ struct iphdr *niph;
+ const struct tcphdr *oth;
+ struct tcphdr _oth;
+
+ oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook);
+ if (!oth)
+ return;
+
+ if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
+ return;
+
+ oiph = ip_hdr(oldskb);
+
+ nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
+ LL_MAX_HEADER, GFP_ATOMIC);
+ if (!nskb)
+ return;
/* ip_route_me_harder expects skb->dst to be set */
skb_dst_set_noref(nskb, skb_dst(oldskb));
- nskb->protocol = htons(ETH_P_IP);
+ skb_reserve(nskb, LL_MAX_HEADER);
+ niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP,
+ ip4_dst_hoplimit(skb_dst(nskb)));
+ nf_reject_ip_tcphdr_put(nskb, oldskb, oth);
+
if (ip_route_me_harder(nskb, RTN_UNSPEC))
goto free_nskb;
- niph->ttl = ip4_dst_hoplimit(skb_dst(nskb));
-
/* "Never happens" */
if (nskb->len > dst_mtu(skb_dst(nskb)))
goto free_nskb;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 4/6] netfilter: nf_reject_ipv6: split nf_send_reset6() in smaller functions
2014-10-31 12:18 [PATCH 0/6] netfilter/ipvs fixes for net Pablo Neira Ayuso
` (2 preceding siblings ...)
2014-10-31 12:18 ` [PATCH 3/6] netfilter: nf_reject_ipv4: split nf_send_reset() in smaller functions Pablo Neira Ayuso
@ 2014-10-31 12:18 ` Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 5/6] netfilter: nft_reject_bridge: don't use IP stack to reject traffic Pablo Neira Ayuso
` (2 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-10-31 12:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
That can be reused by the reject bridge expression to build the reject
packet. The new functions are:
* nf_reject_ip6_tcphdr_get(): to sanitize and to obtain the TCP header.
* nf_reject_ip6hdr_put(): to build the IPv6 header.
* nf_reject_ip6_tcphdr_put(): to build the TCP header.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/ipv6/nf_reject.h | 10 ++
net/ipv6/netfilter/nf_reject_ipv6.c | 175 ++++++++++++++++++++------------
2 files changed, 119 insertions(+), 66 deletions(-)
diff --git a/include/net/netfilter/ipv6/nf_reject.h b/include/net/netfilter/ipv6/nf_reject.h
index 48e1881..23216d4 100644
--- a/include/net/netfilter/ipv6/nf_reject.h
+++ b/include/net/netfilter/ipv6/nf_reject.h
@@ -15,4 +15,14 @@ nf_send_unreach6(struct net *net, struct sk_buff *skb_in, unsigned char code,
void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook);
+const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb,
+ struct tcphdr *otcph,
+ unsigned int *otcplen, int hook);
+struct ipv6hdr *nf_reject_ip6hdr_put(struct sk_buff *nskb,
+ const struct sk_buff *oldskb,
+ __be16 protocol, int hoplimit);
+void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb,
+ const struct sk_buff *oldskb,
+ const struct tcphdr *oth, unsigned int otcplen);
+
#endif /* _IPV6_NF_REJECT_H */
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c
index 20d9def..015eb8a 100644
--- a/net/ipv6/netfilter/nf_reject_ipv6.c
+++ b/net/ipv6/netfilter/nf_reject_ipv6.c
@@ -12,116 +12,102 @@
#include <net/ip6_fib.h>
#include <net/ip6_checksum.h>
#include <linux/netfilter_ipv6.h>
+#include <net/netfilter/ipv6/nf_reject.h>
-void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
+const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb,
+ struct tcphdr *otcph,
+ unsigned int *otcplen, int hook)
{
- struct sk_buff *nskb;
- struct tcphdr otcph, *tcph;
- unsigned int otcplen, hh_len;
- int tcphoff, needs_ack;
const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
- struct ipv6hdr *ip6h;
-#define DEFAULT_TOS_VALUE 0x0U
- const __u8 tclass = DEFAULT_TOS_VALUE;
- struct dst_entry *dst = NULL;
u8 proto;
__be16 frag_off;
- struct flowi6 fl6;
-
- if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
- (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
- pr_debug("addr is not unicast.\n");
- return;
- }
+ int tcphoff;
proto = oip6h->nexthdr;
- tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off);
+ tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
+ &proto, &frag_off);
if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
pr_debug("Cannot get TCP header.\n");
- return;
+ return NULL;
}
- otcplen = oldskb->len - tcphoff;
+ *otcplen = oldskb->len - tcphoff;
/* IP header checks: fragment, too short. */
- if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) {
- pr_debug("proto(%d) != IPPROTO_TCP, "
- "or too short. otcplen = %d\n",
- proto, otcplen);
- return;
+ if (proto != IPPROTO_TCP || *otcplen < sizeof(struct tcphdr)) {
+ pr_debug("proto(%d) != IPPROTO_TCP or too short (len = %d)\n",
+ proto, *otcplen);
+ return NULL;
}
- if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr)))
- BUG();
+ otcph = skb_header_pointer(oldskb, tcphoff, sizeof(struct tcphdr),
+ otcph);
+ if (otcph == NULL)
+ return NULL;
/* No RST for RST. */
- if (otcph.rst) {
+ if (otcph->rst) {
pr_debug("RST is set\n");
- return;
+ return NULL;
}
/* Check checksum. */
if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) {
pr_debug("TCP checksum is invalid\n");
- return;
- }
-
- memset(&fl6, 0, sizeof(fl6));
- fl6.flowi6_proto = IPPROTO_TCP;
- fl6.saddr = oip6h->daddr;
- fl6.daddr = oip6h->saddr;
- fl6.fl6_sport = otcph.dest;
- fl6.fl6_dport = otcph.source;
- security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
- dst = ip6_route_output(net, NULL, &fl6);
- if (dst == NULL || dst->error) {
- dst_release(dst);
- return;
- }
- dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
- if (IS_ERR(dst))
- return;
-
- hh_len = (dst->dev->hard_header_len + 15)&~15;
- nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
- + sizeof(struct tcphdr) + dst->trailer_len,
- GFP_ATOMIC);
-
- if (!nskb) {
- net_dbg_ratelimited("cannot alloc skb\n");
- dst_release(dst);
- return;
+ return NULL;
}
- skb_dst_set(nskb, dst);
+ return otcph;
+}
+EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_get);
- skb_reserve(nskb, hh_len + dst->header_len);
+struct ipv6hdr *nf_reject_ip6hdr_put(struct sk_buff *nskb,
+ const struct sk_buff *oldskb,
+ __be16 protocol, int hoplimit)
+{
+ struct ipv6hdr *ip6h;
+ const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
+#define DEFAULT_TOS_VALUE 0x0U
+ const __u8 tclass = DEFAULT_TOS_VALUE;
skb_put(nskb, sizeof(struct ipv6hdr));
skb_reset_network_header(nskb);
ip6h = ipv6_hdr(nskb);
ip6_flow_hdr(ip6h, tclass, 0);
- ip6h->hop_limit = ip6_dst_hoplimit(dst);
- ip6h->nexthdr = IPPROTO_TCP;
+ ip6h->hop_limit = hoplimit;
+ ip6h->nexthdr = protocol;
ip6h->saddr = oip6h->daddr;
ip6h->daddr = oip6h->saddr;
+ nskb->protocol = htons(ETH_P_IPV6);
+
+ return ip6h;
+}
+EXPORT_SYMBOL_GPL(nf_reject_ip6hdr_put);
+
+void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb,
+ const struct sk_buff *oldskb,
+ const struct tcphdr *oth, unsigned int otcplen)
+{
+ struct tcphdr *tcph;
+ int needs_ack;
+
skb_reset_transport_header(nskb);
tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
/* Truncate to length (no data) */
tcph->doff = sizeof(struct tcphdr)/4;
- tcph->source = otcph.dest;
- tcph->dest = otcph.source;
+ tcph->source = oth->dest;
+ tcph->dest = oth->source;
- if (otcph.ack) {
+ if (oth->ack) {
needs_ack = 0;
- tcph->seq = otcph.ack_seq;
+ tcph->seq = oth->ack_seq;
tcph->ack_seq = 0;
} else {
needs_ack = 1;
- tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
- + otcplen - (otcph.doff<<2));
+ tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
+ otcplen - (oth->doff<<2));
tcph->seq = 0;
}
@@ -139,6 +125,63 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
sizeof(struct tcphdr), IPPROTO_TCP,
csum_partial(tcph,
sizeof(struct tcphdr), 0));
+}
+EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put);
+
+void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
+{
+ struct sk_buff *nskb;
+ struct tcphdr _otcph;
+ const struct tcphdr *otcph;
+ unsigned int otcplen, hh_len;
+ const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
+ struct ipv6hdr *ip6h;
+ struct dst_entry *dst = NULL;
+ struct flowi6 fl6;
+
+ if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
+ (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
+ pr_debug("addr is not unicast.\n");
+ return;
+ }
+
+ otcph = nf_reject_ip6_tcphdr_get(oldskb, &_otcph, &otcplen, hook);
+ if (!otcph)
+ return;
+
+ memset(&fl6, 0, sizeof(fl6));
+ fl6.flowi6_proto = IPPROTO_TCP;
+ fl6.saddr = oip6h->daddr;
+ fl6.daddr = oip6h->saddr;
+ fl6.fl6_sport = otcph->dest;
+ fl6.fl6_dport = otcph->source;
+ security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
+ dst = ip6_route_output(net, NULL, &fl6);
+ if (dst == NULL || dst->error) {
+ dst_release(dst);
+ return;
+ }
+ dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+ if (IS_ERR(dst))
+ return;
+
+ hh_len = (dst->dev->hard_header_len + 15)&~15;
+ nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
+ + sizeof(struct tcphdr) + dst->trailer_len,
+ GFP_ATOMIC);
+
+ if (!nskb) {
+ net_dbg_ratelimited("cannot alloc skb\n");
+ dst_release(dst);
+ return;
+ }
+
+ skb_dst_set(nskb, dst);
+
+ skb_reserve(nskb, hh_len + dst->header_len);
+ ip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP,
+ ip6_dst_hoplimit(dst));
+ nf_reject_ip6_tcphdr_put(nskb, oldskb, otcph, otcplen);
nf_ct_attach(nskb, oldskb);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 5/6] netfilter: nft_reject_bridge: don't use IP stack to reject traffic
2014-10-31 12:18 [PATCH 0/6] netfilter/ipvs fixes for net Pablo Neira Ayuso
` (3 preceding siblings ...)
2014-10-31 12:18 ` [PATCH 4/6] netfilter: nf_reject_ipv6: split nf_send_reset6() " Pablo Neira Ayuso
@ 2014-10-31 12:18 ` Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 6/6] netfilter: nft_reject_bridge: restrict reject to prerouting and input Pablo Neira Ayuso
2014-10-31 16:30 ` [PATCH 0/6] netfilter/ipvs fixes for net David Miller
6 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-10-31 12:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
If the packet is received via the bridge stack, this cannot reject
packets from the IP stack.
This adds functions to build the reject packet and send it from the
bridge stack. Comments and assumptions on this patch:
1) Validate the IPv4 and IPv6 headers before further processing,
given that the packet comes from the bridge stack, we cannot assume
they are clean. Truncated packets are dropped, we follow similar
approach in the existing iptables match/target extensions that need
to inspect layer 4 headers that is not available. This also includes
packets that are directed to multicast and broadcast ethernet
addresses.
2) br_deliver() is exported to inject the reject packet via
bridge localout -> postrouting. So the approach is similar to what
we already do in the iptables reject target. The reject packet is
sent to the bridge port from which we have received the original
packet.
3) The reject packet is forged based on the original packet. The TTL
is set based on sysctl_ip_default_ttl for IPv4 and per-net
ipv6.devconf_all hoplimit for IPv6.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/bridge/br_forward.c | 1 +
net/bridge/netfilter/nft_reject_bridge.c | 263 ++++++++++++++++++++++++++++--
2 files changed, 254 insertions(+), 10 deletions(-)
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 992ec49..44cb786 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -112,6 +112,7 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
kfree_skb(skb);
}
+EXPORT_SYMBOL_GPL(br_deliver);
/* called with rcu_read_lock */
void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
index a764795..31b27e1 100644
--- a/net/bridge/netfilter/nft_reject_bridge.c
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -16,6 +16,237 @@
#include <net/netfilter/nft_reject.h>
#include <net/netfilter/ipv4/nf_reject.h>
#include <net/netfilter/ipv6/nf_reject.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include "../br_private.h"
+
+static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb,
+ struct sk_buff *nskb)
+{
+ struct ethhdr *eth;
+
+ eth = (struct ethhdr *)skb_push(nskb, ETH_HLEN);
+ skb_reset_mac_header(nskb);
+ ether_addr_copy(eth->h_source, eth_hdr(oldskb)->h_dest);
+ ether_addr_copy(eth->h_dest, eth_hdr(oldskb)->h_source);
+ eth->h_proto = eth_hdr(oldskb)->h_proto;
+ skb_pull(nskb, ETH_HLEN);
+}
+
+static int nft_reject_iphdr_validate(struct sk_buff *oldskb)
+{
+ struct iphdr *iph;
+ u32 len;
+
+ if (!pskb_may_pull(oldskb, sizeof(struct iphdr)))
+ return 0;
+
+ iph = ip_hdr(oldskb);
+ if (iph->ihl < 5 || iph->version != 4)
+ return 0;
+
+ len = ntohs(iph->tot_len);
+ if (oldskb->len < len)
+ return 0;
+ else if (len < (iph->ihl*4))
+ return 0;
+
+ if (!pskb_may_pull(oldskb, iph->ihl*4))
+ return 0;
+
+ return 1;
+}
+
+static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook)
+{
+ struct sk_buff *nskb;
+ struct iphdr *niph;
+ const struct tcphdr *oth;
+ struct tcphdr _oth;
+
+ if (!nft_reject_iphdr_validate(oldskb))
+ return;
+
+ oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook);
+ if (!oth)
+ return;
+
+ nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
+ LL_MAX_HEADER, GFP_ATOMIC);
+ if (!nskb)
+ return;
+
+ skb_reserve(nskb, LL_MAX_HEADER);
+ niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP,
+ sysctl_ip_default_ttl);
+ nf_reject_ip_tcphdr_put(nskb, oldskb, oth);
+ niph->ttl = sysctl_ip_default_ttl;
+ niph->tot_len = htons(nskb->len);
+ ip_send_check(niph);
+
+ nft_reject_br_push_etherhdr(oldskb, nskb);
+
+ br_deliver(br_port_get_rcu(oldskb->dev), nskb);
+}
+
+static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook,
+ u8 code)
+{
+ struct sk_buff *nskb;
+ struct iphdr *niph;
+ struct icmphdr *icmph;
+ unsigned int len;
+ void *payload;
+ __wsum csum;
+
+ if (!nft_reject_iphdr_validate(oldskb))
+ return;
+
+ /* IP header checks: fragment. */
+ if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
+ return;
+
+ /* RFC says return as much as we can without exceeding 576 bytes. */
+ len = min_t(unsigned int, 536, oldskb->len);
+
+ if (!pskb_may_pull(oldskb, len))
+ return;
+
+ if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), 0))
+ return;
+
+ nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmphdr) +
+ LL_MAX_HEADER + len, GFP_ATOMIC);
+ if (!nskb)
+ return;
+
+ skb_reserve(nskb, LL_MAX_HEADER);
+ niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_ICMP,
+ sysctl_ip_default_ttl);
+
+ skb_reset_transport_header(nskb);
+ icmph = (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr));
+ memset(icmph, 0, sizeof(*icmph));
+ icmph->type = ICMP_DEST_UNREACH;
+ icmph->code = code;
+
+ payload = skb_put(nskb, len);
+ memcpy(payload, skb_network_header(oldskb), len);
+
+ csum = csum_partial((void *)icmph, len + sizeof(struct icmphdr), 0);
+ icmph->checksum = csum_fold(csum);
+
+ niph->tot_len = htons(nskb->len);
+ ip_send_check(niph);
+
+ nft_reject_br_push_etherhdr(oldskb, nskb);
+
+ br_deliver(br_port_get_rcu(oldskb->dev), nskb);
+}
+
+static int nft_reject_ip6hdr_validate(struct sk_buff *oldskb)
+{
+ struct ipv6hdr *hdr;
+ u32 pkt_len;
+
+ if (!pskb_may_pull(oldskb, sizeof(struct ipv6hdr)))
+ return 0;
+
+ hdr = ipv6_hdr(oldskb);
+ if (hdr->version != 6)
+ return 0;
+
+ pkt_len = ntohs(hdr->payload_len);
+ if (pkt_len + sizeof(struct ipv6hdr) > oldskb->len)
+ return 0;
+
+ return 1;
+}
+
+static void nft_reject_br_send_v6_tcp_reset(struct net *net,
+ struct sk_buff *oldskb, int hook)
+{
+ struct sk_buff *nskb;
+ const struct tcphdr *oth;
+ struct tcphdr _oth;
+ unsigned int otcplen;
+ struct ipv6hdr *nip6h;
+
+ if (!nft_reject_ip6hdr_validate(oldskb))
+ return;
+
+ oth = nf_reject_ip6_tcphdr_get(oldskb, &_oth, &otcplen, hook);
+ if (!oth)
+ return;
+
+ nskb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(struct tcphdr) +
+ LL_MAX_HEADER, GFP_ATOMIC);
+ if (!nskb)
+ return;
+
+ skb_reserve(nskb, LL_MAX_HEADER);
+ nip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP,
+ net->ipv6.devconf_all->hop_limit);
+ nf_reject_ip6_tcphdr_put(nskb, oldskb, oth, otcplen);
+ nip6h->payload_len = htons(nskb->len - sizeof(struct ipv6hdr));
+
+ nft_reject_br_push_etherhdr(oldskb, nskb);
+
+ br_deliver(br_port_get_rcu(oldskb->dev), nskb);
+}
+
+static void nft_reject_br_send_v6_unreach(struct net *net,
+ struct sk_buff *oldskb, int hook,
+ u8 code)
+{
+ struct sk_buff *nskb;
+ struct ipv6hdr *nip6h;
+ struct icmp6hdr *icmp6h;
+ unsigned int len;
+ void *payload;
+
+ if (!nft_reject_ip6hdr_validate(oldskb))
+ return;
+
+ /* Include "As much of invoking packet as possible without the ICMPv6
+ * packet exceeding the minimum IPv6 MTU" in the ICMP payload.
+ */
+ len = min_t(unsigned int, 1220, oldskb->len);
+
+ if (!pskb_may_pull(oldskb, len))
+ return;
+
+ nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmp6hdr) +
+ LL_MAX_HEADER + len, GFP_ATOMIC);
+ if (!nskb)
+ return;
+
+ skb_reserve(nskb, LL_MAX_HEADER);
+ nip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_ICMPV6,
+ net->ipv6.devconf_all->hop_limit);
+
+ skb_reset_transport_header(nskb);
+ icmp6h = (struct icmp6hdr *)skb_put(nskb, sizeof(struct icmp6hdr));
+ memset(icmp6h, 0, sizeof(*icmp6h));
+ icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
+ icmp6h->icmp6_code = code;
+
+ payload = skb_put(nskb, len);
+ memcpy(payload, skb_network_header(oldskb), len);
+ nip6h->payload_len = htons(nskb->len - sizeof(struct ipv6hdr));
+
+ icmp6h->icmp6_cksum =
+ csum_ipv6_magic(&nip6h->saddr, &nip6h->daddr,
+ nskb->len - sizeof(struct ipv6hdr),
+ IPPROTO_ICMPV6,
+ csum_partial(icmp6h,
+ nskb->len - sizeof(struct ipv6hdr),
+ 0));
+
+ nft_reject_br_push_etherhdr(oldskb, nskb);
+
+ br_deliver(br_port_get_rcu(oldskb->dev), nskb);
+}
static void nft_reject_bridge_eval(const struct nft_expr *expr,
struct nft_data data[NFT_REG_MAX + 1],
@@ -23,35 +254,46 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
{
struct nft_reject *priv = nft_expr_priv(expr);
struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
+ const unsigned char *dest = eth_hdr(pkt->skb)->h_dest;
+
+ if (is_broadcast_ether_addr(dest) ||
+ is_multicast_ether_addr(dest))
+ goto out;
switch (eth_hdr(pkt->skb)->h_proto) {
case htons(ETH_P_IP):
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
- nf_send_unreach(pkt->skb, priv->icmp_code);
+ nft_reject_br_send_v4_unreach(pkt->skb,
+ pkt->ops->hooknum,
+ priv->icmp_code);
break;
case NFT_REJECT_TCP_RST:
- nf_send_reset(pkt->skb, pkt->ops->hooknum);
+ nft_reject_br_send_v4_tcp_reset(pkt->skb,
+ pkt->ops->hooknum);
break;
case NFT_REJECT_ICMPX_UNREACH:
- nf_send_unreach(pkt->skb,
- nft_reject_icmp_code(priv->icmp_code));
+ nft_reject_br_send_v4_unreach(pkt->skb,
+ pkt->ops->hooknum,
+ nft_reject_icmp_code(priv->icmp_code));
break;
}
break;
case htons(ETH_P_IPV6):
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
- nf_send_unreach6(net, pkt->skb, priv->icmp_code,
- pkt->ops->hooknum);
+ nft_reject_br_send_v6_unreach(net, pkt->skb,
+ pkt->ops->hooknum,
+ priv->icmp_code);
break;
case NFT_REJECT_TCP_RST:
- nf_send_reset6(net, pkt->skb, pkt->ops->hooknum);
+ nft_reject_br_send_v6_tcp_reset(net, pkt->skb,
+ pkt->ops->hooknum);
break;
case NFT_REJECT_ICMPX_UNREACH:
- nf_send_unreach6(net, pkt->skb,
- nft_reject_icmpv6_code(priv->icmp_code),
- pkt->ops->hooknum);
+ nft_reject_br_send_v6_unreach(net, pkt->skb,
+ pkt->ops->hooknum,
+ nft_reject_icmpv6_code(priv->icmp_code));
break;
}
break;
@@ -59,6 +301,7 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
/* No explicit way to reject this protocol, drop it. */
break;
}
+out:
data[NFT_REG_VERDICT].verdict = NF_DROP;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 6/6] netfilter: nft_reject_bridge: restrict reject to prerouting and input
2014-10-31 12:18 [PATCH 0/6] netfilter/ipvs fixes for net Pablo Neira Ayuso
` (4 preceding siblings ...)
2014-10-31 12:18 ` [PATCH 5/6] netfilter: nft_reject_bridge: don't use IP stack to reject traffic Pablo Neira Ayuso
@ 2014-10-31 12:18 ` Pablo Neira Ayuso
2014-10-31 16:30 ` [PATCH 0/6] netfilter/ipvs fixes for net David Miller
6 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-10-31 12:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
Restrict the reject expression to the prerouting and input bridge
hooks. If we allow this to be used from forward or any other later
bridge hook, if the frame is flooded to several ports, we'll end up
sending several reject packets, one per cloned packet.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/bridge/netfilter/nft_reject_bridge.c | 33 +++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
index 31b27e1..654c901 100644
--- a/net/bridge/netfilter/nft_reject_bridge.c
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -18,6 +18,7 @@
#include <net/netfilter/ipv6/nf_reject.h>
#include <linux/ip.h>
#include <net/ip.h>
+#include <linux/netfilter_bridge.h>
#include "../br_private.h"
static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb,
@@ -305,12 +306,34 @@ out:
data[NFT_REG_VERDICT].verdict = NF_DROP;
}
+static int nft_reject_bridge_validate_hooks(const struct nft_chain *chain)
+{
+ struct nft_base_chain *basechain;
+
+ if (chain->flags & NFT_BASE_CHAIN) {
+ basechain = nft_base_chain(chain);
+
+ switch (basechain->ops[0].hooknum) {
+ case NF_BR_PRE_ROUTING:
+ case NF_BR_LOCAL_IN:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ }
+ return 0;
+}
+
static int nft_reject_bridge_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[])
{
struct nft_reject *priv = nft_expr_priv(expr);
- int icmp_code;
+ int icmp_code, err;
+
+ err = nft_reject_bridge_validate_hooks(ctx->chain);
+ if (err < 0)
+ return err;
if (tb[NFTA_REJECT_TYPE] == NULL)
return -EINVAL;
@@ -359,6 +382,13 @@ nla_put_failure:
return -1;
}
+static int nft_reject_bridge_validate(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nft_data **data)
+{
+ return nft_reject_bridge_validate_hooks(ctx->chain);
+}
+
static struct nft_expr_type nft_reject_bridge_type;
static const struct nft_expr_ops nft_reject_bridge_ops = {
.type = &nft_reject_bridge_type,
@@ -366,6 +396,7 @@ static const struct nft_expr_ops nft_reject_bridge_ops = {
.eval = nft_reject_bridge_eval,
.init = nft_reject_bridge_init,
.dump = nft_reject_bridge_dump,
+ .validate = nft_reject_bridge_validate,
};
static struct nft_expr_type nft_reject_bridge_type __read_mostly = {
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 0/6] netfilter/ipvs fixes for net
2014-10-31 12:18 [PATCH 0/6] netfilter/ipvs fixes for net Pablo Neira Ayuso
` (5 preceding siblings ...)
2014-10-31 12:18 ` [PATCH 6/6] netfilter: nft_reject_bridge: restrict reject to prerouting and input Pablo Neira Ayuso
@ 2014-10-31 16:30 ` David Miller
6 siblings, 0 replies; 14+ messages in thread
From: David Miller @ 2014-10-31 16:30 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Fri, 31 Oct 2014 13:18:26 +0100
> The following patchset contains fixes for netfilter/ipvs. This round of
> fixes is larger than usual at this stage, specifically because of the
> nf_tables bridge reject fixes that I would like to see in 3.18. The
> patches are:
...
> You can pull these changes from:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
Pulled, thanks Pablo.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 0/6] netfilter/ipvs fixes for net
@ 2015-01-10 18:50 Pablo Neira Ayuso
2015-01-12 5:15 ` David Miller
0 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2015-01-10 18:50 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
Hi David,
The following patchset contains netfilter/ipvs fixes, they are:
1) Small fix for the FTP helper in IPVS, a diff variable may be left
unset when CONFIG_IP_VS_IPV6 is set. Patch from Dan Carpenter.
2) Fix nf_tables port NAT in little endian archs, patch from leroy
christophe.
3) Fix race condition between conntrack confirmation and flush from
userspace. This is the second reincarnation to resolve this problem.
4) Make sure inner messages in the batch come with the nfnetlink header.
5) Relax strict check from nfnetlink_bind() that may break old userspace
applications using all 1s group mask.
6) Schedule removal of chains once no sets and rules refer to them in
the new nf_tables ruleset flush command. Reported by Asbjoern Sloth
Toennesen.
Note that this batch comes later than usual because of the short
winter holidays.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
Have a happy new year, thanks!
----------------------------------------------------------------
The following changes since commit ac9a3d84e121196263636f2d38d439a45888005a:
be2net: Fix incorrect setting of tunnel offload flag in netdev features (2014-12-18 12:51:29 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git master
for you to fetch changes up to a2f18db0c68fec96631c10cad9384c196e9008ac:
netfilter: nf_tables: fix flush ruleset chain dependencies (2015-01-06 22:27:48 +0100)
----------------------------------------------------------------
Dan Carpenter (1):
ipvs: uninitialized data with IP_VS_IPV6
Pablo Neira Ayuso (5):
Merge tag 'ipvs2-for-v3.19' of https://git.kernel.org/.../horms/ipvs-next into ipvs-next
netfilter: conntrack: fix race between confirmation and flush
netfilter: nfnetlink: validate nfnetlink header from batch
netfilter: nfnetlink: relax strict multicast group check from netlink_bind
netfilter: nf_tables: fix flush ruleset chain dependencies
leroy christophe (1):
netfilter: nf_tables: fix port natting in little endian archs
net/ipv4/netfilter/nft_redir_ipv4.c | 8 ++++----
net/ipv6/netfilter/nft_redir_ipv6.c | 8 ++++----
net/netfilter/ipvs/ip_vs_ftp.c | 10 +++++-----
net/netfilter/nf_conntrack_core.c | 20 +++++++++-----------
net/netfilter/nf_tables_api.c | 14 +++++++++-----
net/netfilter/nfnetlink.c | 5 +++--
net/netfilter/nft_nat.c | 8 ++++----
7 files changed, 38 insertions(+), 35 deletions(-)
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 0/6] netfilter/ipvs fixes for net
2015-01-10 18:50 [PATCH 0/6] netfilter/ipvs " Pablo Neira Ayuso
@ 2015-01-12 5:15 ` David Miller
0 siblings, 0 replies; 14+ messages in thread
From: David Miller @ 2015-01-12 5:15 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Sat, 10 Jan 2015 19:50:02 +0100
> The following patchset contains netfilter/ipvs fixes, they are:
...
> Note that this batch comes later than usual because of the short
> winter holidays.
>
> You can pull these changes from:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
>
> Have a happy new year, thanks!
Happy new year to you too Pablo!
Pulled, thanks a lot.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 0/6] Netfilter/IPVS fixes for net
@ 2016-07-12 16:10 Pablo Neira Ayuso
2016-07-12 17:22 ` David Miller
0 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2016-07-12 16:10 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
Hi David,
The following patchset contains Netfilter/IPVS fixes for your net tree.
they are:
1) Fix leak in the error path of nft_expr_init(), from Liping Zhang.
2) Tracing from nf_tables cannot be disabled, also from Zhang.
3) Fix an integer overflow on 32bit archs when setting the number of
hashtable buckets, from Florian Westphal.
4) Fix configuration of ipvs sync in backup mode with IPv6 address,
from Quentin Armitage via Simon Horman.
5) Fix incorrect timeout calculation in nft_ct NFT_CT_EXPIRATION,
from Florian Westphal.
6) Skip clash resolution in conntrack insertion races if NAT is in
place.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
We're rather late in the release cycle of 4.7, so if these cannot get
upstream I'll make sure to submit them to -stable, no problem.
Thanks!
----------------------------------------------------------------
The following changes since commit acd43fe85b2d1dbad55ce211b8817e6d6687246f:
Merge branch 'mlx4-fixes' (2016-06-22 16:38:17 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git HEAD
for you to fetch changes up to 590b52e10d410e1439ae86be9fe19d75fdab628b:
netfilter: conntrack: skip clash resolution if nat is in place (2016-07-12 16:28:41 +0200)
----------------------------------------------------------------
Florian Westphal (2):
netfilter: conntrack: avoid integer overflow when resizing
netfilter: nft_ct: fix expiration getter
Liping Zhang (2):
netfilter: nf_tables: fix memory leak if expr init fails
netfilter: nft_meta: set skb->nf_trace appropriately
Pablo Neira Ayuso (2):
Merge tag 'ipvs-fixes2-for-v4.7' of https://git.kernel.org/.../horms/ipvs
netfilter: conntrack: skip clash resolution if nat is in place
Quentin Armitage (1):
ipvs: fix bind to link-local mcast IPv6 address in backup
include/net/netfilter/nf_conntrack.h | 8 ++++++++
net/netfilter/ipvs/ip_vs_sync.c | 6 ++++--
net/netfilter/nf_conntrack_core.c | 8 ++++++++
net/netfilter/nf_tables_api.c | 4 +++-
net/netfilter/nft_ct.c | 6 +-----
net/netfilter/nft_meta.c | 2 +-
6 files changed, 25 insertions(+), 9 deletions(-)
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 0/6] Netfilter/IPVS fixes for net
2016-07-12 16:10 [PATCH 0/6] Netfilter/IPVS " Pablo Neira Ayuso
@ 2016-07-12 17:22 ` David Miller
0 siblings, 0 replies; 14+ messages in thread
From: David Miller @ 2016-07-12 17:22 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Tue, 12 Jul 2016 18:10:56 +0200
> The following patchset contains Netfilter/IPVS fixes for your net tree.
> they are:
>
> 1) Fix leak in the error path of nft_expr_init(), from Liping Zhang.
>
> 2) Tracing from nf_tables cannot be disabled, also from Zhang.
>
> 3) Fix an integer overflow on 32bit archs when setting the number of
> hashtable buckets, from Florian Westphal.
>
> 4) Fix configuration of ipvs sync in backup mode with IPv6 address,
> from Quentin Armitage via Simon Horman.
>
> 5) Fix incorrect timeout calculation in nft_ct NFT_CT_EXPIRATION,
> from Florian Westphal.
>
> 6) Skip clash resolution in conntrack insertion races if NAT is in
> place.
>
> You can pull these changes from:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
Pulled, thanks Pablo.
> We're rather late in the release cycle of 4.7, so if these cannot
> get upstream I'll make sure to submit them to -stable, no problem.
I'm pretty sure there is going to be an -rc8, don't worry...
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2016-07-12 17:22 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-31 12:18 [PATCH 0/6] netfilter/ipvs fixes for net Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 1/6] ipvs: Avoid null-pointer deref in debug code Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 2/6] netfilter: nf_tables_bridge: update hook_mask to allow {pre,post}routing Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 3/6] netfilter: nf_reject_ipv4: split nf_send_reset() in smaller functions Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 4/6] netfilter: nf_reject_ipv6: split nf_send_reset6() " Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 5/6] netfilter: nft_reject_bridge: don't use IP stack to reject traffic Pablo Neira Ayuso
2014-10-31 12:18 ` [PATCH 6/6] netfilter: nft_reject_bridge: restrict reject to prerouting and input Pablo Neira Ayuso
2014-10-31 16:30 ` [PATCH 0/6] netfilter/ipvs fixes for net David Miller
-- strict thread matches above, loose matches on Subject: below --
2016-07-12 16:10 [PATCH 0/6] Netfilter/IPVS " Pablo Neira Ayuso
2016-07-12 17:22 ` David Miller
2015-01-10 18:50 [PATCH 0/6] netfilter/ipvs " Pablo Neira Ayuso
2015-01-12 5:15 ` David Miller
2013-10-01 9:08 [PATCH 0/6] Netfilter/IPVS " Pablo Neira Ayuso
2013-10-01 16:39 ` David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).