Commit 90be7a5c authored by David S. Miller's avatar David S. Miller
Browse files


netfilter pull request 24-04-11

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

Patches #1 and #2 add missing rcu read side lock when iterating over
expression and object type list which could race with module removal.

Patch #3 prevents promisc packet from visiting the bridge/input hook
	 to amend a recent fix to address conntrack confirmation race
	 in br_netfilter and nf_conntrack_bridge.

Patch #4 adds and uses iterate decorator type to fetch the current
	 pipapo set backend datastructure view when netlink dumps the
	 set elements.

Patch #5 fixes removal of duplicate elements in the pipapo set backend.

Patch #6 flowtable validates pppoe header before accessing it.

Patch #7 fixes flowtable datapath for pppoe packets, otherwise lookup
         fails and pppoe packets follow classic path.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2ae9a897 6db5dc7b
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -336,7 +336,7 @@ int nf_flow_rule_route_ipv6(struct net *net, struct flow_offload *flow,
int nf_flow_table_offload_init(void);
void nf_flow_table_offload_exit(void);

static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
static inline __be16 __nf_flow_pppoe_proto(const struct sk_buff *skb)
{
	__be16 proto;

@@ -352,6 +352,16 @@ static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
	return 0;
}

static inline bool nf_flow_pppoe_proto(struct sk_buff *skb, __be16 *inner_proto)
{
	if (!pskb_may_pull(skb, PPPOE_SES_HLEN))
		return false;

	*inner_proto = __nf_flow_pppoe_proto(skb);

	return true;
}

#define NF_FLOW_TABLE_STAT_INC(net, count) __this_cpu_inc((net)->ft.stat->count)
#define NF_FLOW_TABLE_STAT_DEC(net, count) __this_cpu_dec((net)->ft.stat->count)
#define NF_FLOW_TABLE_STAT_INC_ATOMIC(net, count)	\
+14 −0
Original line number Diff line number Diff line
@@ -307,9 +307,23 @@ static inline void *nft_elem_priv_cast(const struct nft_elem_priv *priv)
	return (void *)priv;
}


/**
 * enum nft_iter_type - nftables set iterator type
 *
 * @NFT_ITER_READ: read-only iteration over set elements
 * @NFT_ITER_UPDATE: iteration under mutex to update set element state
 */
enum nft_iter_type {
	NFT_ITER_UNSPEC,
	NFT_ITER_READ,
	NFT_ITER_UPDATE,
};

struct nft_set;
struct nft_set_iter {
	u8		genmask;
	enum nft_iter_type type:8;
	unsigned int	count;
	unsigned int	skip;
	int		err;
+11 −4
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)
	return netif_receive_skb(skb);
}

static int br_pass_frame_up(struct sk_buff *skb)
static int br_pass_frame_up(struct sk_buff *skb, bool promisc)
{
	struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
	struct net_bridge *br = netdev_priv(brdev);
@@ -65,6 +65,8 @@ static int br_pass_frame_up(struct sk_buff *skb)
	br_multicast_count(br, NULL, skb, br_multicast_igmp_type(skb),
			   BR_MCAST_DIR_TX);

	BR_INPUT_SKB_CB(skb)->promisc = promisc;

	return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,
		       dev_net(indev), NULL, skb, indev, NULL,
		       br_netif_receive_skb);
@@ -82,6 +84,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
	struct net_bridge_mcast *brmctx;
	struct net_bridge_vlan *vlan;
	struct net_bridge *br;
	bool promisc;
	u16 vid = 0;
	u8 state;

@@ -137,7 +140,9 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
	if (p->flags & BR_LEARNING)
		br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, 0);

	local_rcv = !!(br->dev->flags & IFF_PROMISC);
	promisc = !!(br->dev->flags & IFF_PROMISC);
	local_rcv = promisc;

	if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
		/* by definition the broadcast is also a multicast address */
		if (is_broadcast_ether_addr(eth_hdr(skb)->h_dest)) {
@@ -200,7 +205,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
		unsigned long now = jiffies;

		if (test_bit(BR_FDB_LOCAL, &dst->flags))
			return br_pass_frame_up(skb);
			return br_pass_frame_up(skb, false);

		if (now != dst->used)
			dst->used = now;
@@ -213,7 +218,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
	}

	if (local_rcv)
		return br_pass_frame_up(skb);
		return br_pass_frame_up(skb, promisc);

out:
	return 0;
@@ -386,6 +391,8 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
				goto forward;
		}

		BR_INPUT_SKB_CB(skb)->promisc = false;

		/* The else clause should be hit when nf_hook():
		 *   - returns < 0 (drop/error)
		 *   - returns = 0 (stolen/nf_queue)
+6 −0
Original line number Diff line number Diff line
@@ -600,11 +600,17 @@ static unsigned int br_nf_local_in(void *priv,
				   struct sk_buff *skb,
				   const struct nf_hook_state *state)
{
	bool promisc = BR_INPUT_SKB_CB(skb)->promisc;
	struct nf_conntrack *nfct = skb_nfct(skb);
	const struct nf_ct_hook *ct_hook;
	struct nf_conn *ct;
	int ret;

	if (promisc) {
		nf_reset_ct(skb);
		return NF_ACCEPT;
	}

	if (!nfct || skb->pkt_type == PACKET_HOST)
		return NF_ACCEPT;

+1 −0
Original line number Diff line number Diff line
@@ -589,6 +589,7 @@ struct br_input_skb_cb {
#endif
	u8 proxyarp_replied:1;
	u8 src_port_isolated:1;
	u8 promisc:1;
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
	u8 vlan_filtered:1;
#endif
Loading