Commit bd569dd9 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Florian Westphal says:

====================
netfilter: updates for net-next

1) Don't respond to ICMP_UNREACH errors with another ICMP_UNREACH
   error.
2) Support fetching the current bridge ethernet address.
   This allows a more flexible approach to packet redirection
   on bridges without need to use hardcoded addresses. From
   Fernando Fernandez Mancera.
3) Zap a few no-longer needed conditionals from ipvs packet path
   and convert to READ/WRITE_ONCE to avoid KCSAN warnings.
   From Zhang Tengfei.
4) Remove a no-longer-used macro argument in ipset, from Zhen Ni.

* tag 'nf-next-25-09-11' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next:
  netfilter: nf_reject: don't reply to icmp error messages
  ipvs: Use READ_ONCE/WRITE_ONCE for ipvs->enable
  netfilter: nft_meta_bridge: introduce NFT_META_BRI_IIFHWADDR support
  netfilter: ipset: Remove unused htable_bits in macro ahash_region
  selftest:net: fixed spelling mistakes
====================

Link: https://patch.msgid.link/20250911143819.14753-1-fw@strlen.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 3456820e db99b2f2
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -959,6 +959,7 @@ enum nft_exthdr_attributes {
 * @NFT_META_SDIF: slave device interface index
 * @NFT_META_SDIFNAME: slave device interface name
 * @NFT_META_BRI_BROUTE: packet br_netfilter_broute bit
 * @NFT_META_BRI_IIFHWADDR: packet input bridge interface ethernet address
 */
enum nft_meta_keys {
	NFT_META_LEN,
@@ -999,6 +1000,7 @@ enum nft_meta_keys {
	NFT_META_SDIFNAME,
	NFT_META_BRI_BROUTE,
	__NFT_META_IIFTYPE,
	NFT_META_BRI_IIFHWADDR,
};

/**
+11 −0
Original line number Diff line number Diff line
@@ -59,6 +59,13 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
		nft_reg_store_be16(dest, htons(p_proto));
		return;
	}
	case NFT_META_BRI_IIFHWADDR:
		br_dev = nft_meta_get_bridge(in);
		if (!br_dev)
			goto err;

		memcpy(dest, br_dev->dev_addr, ETH_ALEN);
		return;
	default:
		return nft_meta_get_eval(expr, regs, pkt);
	}
@@ -86,6 +93,9 @@ static int nft_meta_bridge_get_init(const struct nft_ctx *ctx,
	case NFT_META_BRI_IIFVPROTO:
		len = sizeof(u16);
		break;
	case NFT_META_BRI_IIFHWADDR:
		len = ETH_ALEN;
		break;
	default:
		return nft_meta_get_init(ctx, expr, tb);
	}
@@ -175,6 +185,7 @@ static int nft_meta_bridge_set_validate(const struct nft_ctx *ctx,

	switch (priv->key) {
	case NFT_META_BRI_BROUTE:
	case NFT_META_BRI_IIFHWADDR:
		hooks = 1 << NF_BR_PRE_ROUTING;
		break;
	default:
+25 −0
Original line number Diff line number Diff line
@@ -80,6 +80,27 @@ struct sk_buff *nf_reject_skb_v4_tcp_reset(struct net *net,
}
EXPORT_SYMBOL_GPL(nf_reject_skb_v4_tcp_reset);

static bool nf_skb_is_icmp_unreach(const struct sk_buff *skb)
{
	const struct iphdr *iph = ip_hdr(skb);
	u8 *tp, _type;
	int thoff;

	if (iph->protocol != IPPROTO_ICMP)
		return false;

	thoff = skb_network_offset(skb) + sizeof(*iph);

	tp = skb_header_pointer(skb,
				thoff + offsetof(struct icmphdr, type),
				sizeof(_type), &_type);

	if (!tp)
		return false;

	return *tp == ICMP_DEST_UNREACH;
}

struct sk_buff *nf_reject_skb_v4_unreach(struct net *net,
					 struct sk_buff *oldskb,
					 const struct net_device *dev,
@@ -100,6 +121,10 @@ struct sk_buff *nf_reject_skb_v4_unreach(struct net *net,
	if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
		return NULL;

	/* don't reply to ICMP_DEST_UNREACH with ICMP_DEST_UNREACH. */
	if (nf_skb_is_icmp_unreach(oldskb))
		return NULL;

	/* RFC says return as much as we can without exceeding 576 bytes. */
	len = min_t(unsigned int, 536, oldskb->len);

+30 −0
Original line number Diff line number Diff line
@@ -104,6 +104,32 @@ struct sk_buff *nf_reject_skb_v6_tcp_reset(struct net *net,
}
EXPORT_SYMBOL_GPL(nf_reject_skb_v6_tcp_reset);

static bool nf_skb_is_icmp6_unreach(const struct sk_buff *skb)
{
	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
	u8 proto = ip6h->nexthdr;
	u8 _type, *tp;
	int thoff;
	__be16 fo;

	thoff = ipv6_skip_exthdr(skb, ((u8 *)(ip6h + 1) - skb->data), &proto, &fo);

	if (thoff < 0 || thoff >= skb->len || fo != 0)
		return false;

	if (proto != IPPROTO_ICMPV6)
		return false;

	tp = skb_header_pointer(skb,
				thoff + offsetof(struct icmp6hdr, icmp6_type),
				sizeof(_type), &_type);

	if (!tp)
		return false;

	return *tp == ICMPV6_DEST_UNREACH;
}

struct sk_buff *nf_reject_skb_v6_unreach(struct net *net,
					 struct sk_buff *oldskb,
					 const struct net_device *dev,
@@ -117,6 +143,10 @@ struct sk_buff *nf_reject_skb_v6_unreach(struct net *net,
	if (!nf_reject_ip6hdr_validate(oldskb))
		return NULL;

	/* Don't reply to ICMPV6_DEST_UNREACH with ICMPV6_DEST_UNREACH */
	if (nf_skb_is_icmp6_unreach(oldskb))
		return NULL;

	/* Include "As much of invoking packet as possible without the ICMPv6
	 * packet exceeding the minimum IPv6 MTU" in the ICMP payload.
	 */
+4 −4
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ struct hbucket {
		: jhash_size((htable_bits) - HTABLE_REGION_BITS))
#define ahash_sizeof_regions(htable_bits)		\
	(ahash_numof_locks(htable_bits) * sizeof(struct ip_set_region))
#define ahash_region(n, htable_bits)		\
#define ahash_region(n)		\
	((n) / jhash_size(HTABLE_REGION_BITS))
#define ahash_bucket_start(h,  htable_bits)	\
	((htable_bits) < HTABLE_REGION_BITS ? 0	\
@@ -702,7 +702,7 @@ mtype_resize(struct ip_set *set, bool retried)
#endif
				key = HKEY(data, h->initval, htable_bits);
				m = __ipset_dereference(hbucket(t, key));
				nr = ahash_region(key, htable_bits);
				nr = ahash_region(key);
				if (!m) {
					m = kzalloc(sizeof(*m) +
					    AHASH_INIT_SIZE * dsize,
@@ -852,7 +852,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
	rcu_read_lock_bh();
	t = rcu_dereference_bh(h->table);
	key = HKEY(value, h->initval, t->htable_bits);
	r = ahash_region(key, t->htable_bits);
	r = ahash_region(key);
	atomic_inc(&t->uref);
	elements = t->hregion[r].elements;
	maxelem = t->maxelem;
@@ -1050,7 +1050,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
	rcu_read_lock_bh();
	t = rcu_dereference_bh(h->table);
	key = HKEY(value, h->initval, t->htable_bits);
	r = ahash_region(key, t->htable_bits);
	r = ahash_region(key);
	atomic_inc(&t->uref);
	rcu_read_unlock_bh();

Loading