Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 40451fd0 authored by David S. Miller's avatar David S. Miller
Browse files


Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

The following patchset contains Netfilter updates for net-next.
Basically, more incremental updates for br_netfilter from Florian
Westphal, small nf_tables updates (including one fix for rb-tree
locking) and small two-liner to add extra validation for the REJECT6
target.

More specifically, they are:

1) Use the conntrack status flags from br_netfilter to know that DNAT is
   happening. Patch for Florian Westphal.

2) nf_bridge->physoutdev == NULL already indicates that the traffic is
   bridged, so let's get rid of the BRNF_BRIDGED flag. Also from Florian.

3) Another patch to prepare voidization of seq_printf/seq_puts/seq_putc,
   from Joe Perches.

4) Consolidation of nf_tables_newtable() error path.

5) Kill nf_bridge_pad used by br_netfilter from ip_fragment(),
   from Florian Westphal.

6) Access rb-tree root node inside the lock and remove unnecessary
   locking from the get path (we already hold nfnl_lock there), from
   Patrick McHardy.

7) You cannot use a NFT_SET_ELEM_INTERVAL_END when the set doesn't
   support interval, also from Patrick.

8) Enforce IP6T_F_PROTO from ip6t_REJECT to make sure the core is
   actually restricting matches to TCP.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 682f048b e35158e4
Loading
Loading
Loading
Loading
+0 −29
Original line number Original line Diff line number Diff line
@@ -19,23 +19,10 @@ enum nf_br_hook_priorities {


#define BRNF_PKT_TYPE			0x01
#define BRNF_PKT_TYPE			0x01
#define BRNF_BRIDGED_DNAT		0x02
#define BRNF_BRIDGED_DNAT		0x02
#define BRNF_BRIDGED			0x04
#define BRNF_NF_BRIDGE_PREROUTING	0x08
#define BRNF_NF_BRIDGE_PREROUTING	0x08
#define BRNF_8021Q			0x10
#define BRNF_8021Q			0x10
#define BRNF_PPPoE			0x20
#define BRNF_PPPoE			0x20


static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
{
	switch (skb->protocol) {
	case __cpu_to_be16(ETH_P_8021Q):
		return VLAN_HLEN;
	case __cpu_to_be16(ETH_P_PPP_SES):
		return PPPOE_SES_HLEN;
	default:
		return 0;
	}
}

static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
{
{
	if (unlikely(skb->nf_bridge->mask & BRNF_PPPoE))
	if (unlikely(skb->nf_bridge->mask & BRNF_PPPoE))
@@ -45,21 +32,6 @@ static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)


int br_handle_frame_finish(struct sk_buff *skb);
int br_handle_frame_finish(struct sk_buff *skb);


/* This is called by the IP fragmenting code and it ensures there is
 * enough room for the encapsulating header (if there is one). */
static inline unsigned int nf_bridge_pad(const struct sk_buff *skb)
{
	if (skb->nf_bridge)
		return nf_bridge_encap_header_len(skb);
	return 0;
}

struct bridge_skb_cb {
	union {
		__be32 ipv4;
	} daddr;
};

static inline void br_drop_fake_rtable(struct sk_buff *skb)
static inline void br_drop_fake_rtable(struct sk_buff *skb)
{
{
	struct dst_entry *dst = skb_dst(skb);
	struct dst_entry *dst = skb_dst(skb);
@@ -69,7 +41,6 @@ static inline void br_drop_fake_rtable(struct sk_buff *skb)
}
}


#else
#else
#define nf_bridge_pad(skb)			(0)
#define br_drop_fake_rtable(skb)	        do { } while (0)
#define br_drop_fake_rtable(skb)	        do { } while (0)
#endif /* CONFIG_BRIDGE_NETFILTER */
#endif /* CONFIG_BRIDGE_NETFILTER */


+39 −9
Original line number Original line Diff line number Diff line
@@ -37,17 +37,16 @@
#include <net/route.h>
#include <net/route.h>
#include <net/netfilter/br_netfilter.h>
#include <net/netfilter/br_netfilter.h>


#if IS_ENABLED(CONFIG_NF_CONNTRACK)
#include <net/netfilter/nf_conntrack.h>
#endif

#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include "br_private.h"
#include "br_private.h"
#ifdef CONFIG_SYSCTL
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#include <linux/sysctl.h>
#endif
#endif


#define skb_origaddr(skb)	 (((struct bridge_skb_cb *) \
				 (skb->nf_bridge->data))->daddr.ipv4)
#define store_orig_dstaddr(skb)	 (skb_origaddr(skb) = ip_hdr(skb)->daddr)
#define dnat_took_place(skb)	 (skb_origaddr(skb) != ip_hdr(skb)->daddr)

#ifdef CONFIG_SYSCTL
#ifdef CONFIG_SYSCTL
static struct ctl_table_header *brnf_sysctl_header;
static struct ctl_table_header *brnf_sysctl_header;
static int brnf_call_iptables __read_mostly = 1;
static int brnf_call_iptables __read_mostly = 1;
@@ -154,6 +153,18 @@ static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb)
	return nf_bridge;
	return nf_bridge;
}
}


static unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
{
	switch (skb->protocol) {
	case __cpu_to_be16(ETH_P_8021Q):
		return VLAN_HLEN;
	case __cpu_to_be16(ETH_P_PPP_SES):
		return PPPOE_SES_HLEN;
	default:
		return 0;
	}
}

static inline void nf_bridge_push_encap_header(struct sk_buff *skb)
static inline void nf_bridge_push_encap_header(struct sk_buff *skb)
{
{
	unsigned int len = nf_bridge_encap_header_len(skb);
	unsigned int len = nf_bridge_encap_header_len(skb);
@@ -322,6 +333,22 @@ free_skb:
	return 0;
	return 0;
}
}


static bool dnat_took_place(const struct sk_buff *skb)
{
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
	enum ip_conntrack_info ctinfo;
	struct nf_conn *ct;

	ct = nf_ct_get(skb, &ctinfo);
	if (!ct || nf_ct_is_untracked(ct))
		return false;

	return test_bit(IPS_DST_NAT_BIT, &ct->status);
#else
	return false;
#endif
}

/* This requires some explaining. If DNAT has taken place,
/* This requires some explaining. If DNAT has taken place,
 * we will need to fix up the destination Ethernet address.
 * we will need to fix up the destination Ethernet address.
 *
 *
@@ -625,7 +652,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
		return NF_DROP;
		return NF_DROP;
	if (!setup_pre_routing(skb))
	if (!setup_pre_routing(skb))
		return NF_DROP;
		return NF_DROP;
	store_orig_dstaddr(skb);

	skb->protocol = htons(ETH_P_IP);
	skb->protocol = htons(ETH_P_IP);


	NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, skb->dev, NULL,
	NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, skb->dev, NULL,
@@ -721,8 +748,6 @@ static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops,
	if (pf == NFPROTO_IPV4 && br_parse_ip_options(skb))
	if (pf == NFPROTO_IPV4 && br_parse_ip_options(skb))
		return NF_DROP;
		return NF_DROP;


	/* The physdev module checks on this */
	nf_bridge->mask |= BRNF_BRIDGED;
	nf_bridge->physoutdev = skb->dev;
	nf_bridge->physoutdev = skb->dev;
	if (pf == NFPROTO_IPV4)
	if (pf == NFPROTO_IPV4)
		skb->protocol = htons(ETH_P_IP);
		skb->protocol = htons(ETH_P_IP);
@@ -842,7 +867,12 @@ static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops,
	struct net_device *realoutdev = bridge_parent(skb->dev);
	struct net_device *realoutdev = bridge_parent(skb->dev);
	u_int8_t pf;
	u_int8_t pf;


	if (!nf_bridge || !(nf_bridge->mask & BRNF_BRIDGED))
	/* if nf_bridge is set, but ->physoutdev is NULL, this packet came in
	 * on a bridge, but was delivered locally and is now being routed:
	 *
	 * POST_ROUTING was already invoked from the ip stack.
	 */
	if (!nf_bridge || !nf_bridge->physoutdev)
		return NF_ACCEPT;
		return NF_ACCEPT;


	if (!realoutdev)
	if (!realoutdev)
+1 −4
Original line number Original line Diff line number Diff line
@@ -636,10 +636,7 @@ slow_path:
	left = skb->len - hlen;		/* Space per frame */
	left = skb->len - hlen;		/* Space per frame */
	ptr = hlen;		/* Where to start from */
	ptr = hlen;		/* Where to start from */


	/* for bridged IP traffic encapsulated inside f.e. a vlan header,
	ll_rs = LL_RESERVED_SPACE(rt->dst.dev);
	 * we need to make room for the encapsulating header
	 */
	ll_rs = LL_RESERVED_SPACE_EXTRA(rt->dst.dev, nf_bridge_pad(skb));


	/*
	/*
	 *	Fragment the datagram.
	 *	Fragment the datagram.
+3 −1
Original line number Original line Diff line number Diff line
@@ -300,7 +300,9 @@ static int exp_seq_show(struct seq_file *s, void *v)
		    __nf_ct_l3proto_find(exp->tuple.src.l3num),
		    __nf_ct_l3proto_find(exp->tuple.src.l3num),
		    __nf_ct_l4proto_find(exp->tuple.src.l3num,
		    __nf_ct_l4proto_find(exp->tuple.src.l3num,
					 exp->tuple.dst.protonum));
					 exp->tuple.dst.protonum));
	return seq_putc(s, '\n');
	seq_putc(s, '\n');

	return 0;
}
}


static const struct seq_operations exp_seq_ops = {
static const struct seq_operations exp_seq_ops = {
+2 −1
Original line number Original line Diff line number Diff line
@@ -83,7 +83,8 @@ static int reject_tg6_check(const struct xt_tgchk_param *par)
		return -EINVAL;
		return -EINVAL;
	} else if (rejinfo->with == IP6T_TCP_RESET) {
	} else if (rejinfo->with == IP6T_TCP_RESET) {
		/* Must specify that it's a TCP packet */
		/* Must specify that it's a TCP packet */
		if (e->ipv6.proto != IPPROTO_TCP ||
		if (!(e->ipv6.flags & IP6T_F_PROTO) ||
		    e->ipv6.proto != IPPROTO_TCP ||
		    (e->ipv6.invflags & XT_INV_PROTO)) {
		    (e->ipv6.invflags & XT_INV_PROTO)) {
			pr_info("TCP_RESET illegal for non-tcp\n");
			pr_info("TCP_RESET illegal for non-tcp\n");
			return -EINVAL;
			return -EINVAL;
Loading