Commit 37fb1c81 authored by David S. Miller's avatar David S. Miller
Browse files


Florian Westphal says:

====================
netfilter next pull request 2023-10-18

This series contains initial netfilter skb drop_reason support, from
myself.

First few patches fix up a few spots to make sure we won't trip
when followup patches embed error numbers in the upper bits
(we already do this in some places).

Then, nftables and bridge netfilter get converted to call kfree_skb_reason
directly to let tooling pinpoint exact location of packet drops,
rather than the existing NF_DROP catchall in nf_hook_slow().

I would like to eventually convert all netfilter modules, but as some
callers cannot deal with NF_STOLEN (notably act_ct), more preparation
work is needed for this.

Last patch gets rid of an ugly 'de-const' cast in nftables.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 810799a0 25600167
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -22,6 +22,16 @@ static inline int NF_DROP_GETERR(int verdict)
	return -(verdict >> NF_VERDICT_QBITS);
}

static __always_inline int
NF_DROP_REASON(struct sk_buff *skb, enum skb_drop_reason reason, u32 err)
{
	BUILD_BUG_ON(err > 0xffff);

	kfree_skb_reason(skb, reason);

	return ((err << 16) | NF_STOLEN);
}

static inline int nf_inet_addr_cmp(const union nf_inet_addr *a1,
				   const union nf_inet_addr *a2)
{
+1 −1
Original line number Diff line number Diff line
@@ -462,7 +462,7 @@ struct nft_set_ops {
					       const struct nft_set *set,
					       const struct nft_set_elem *elem,
					       unsigned int flags);
	void				(*commit)(const struct nft_set *set);
	void				(*commit)(struct nft_set *set);
	void				(*abort)(const struct nft_set *set);
	u64				(*privsize)(const struct nlattr * const nla[],
						    const struct nft_set_desc *desc);
+13 −13
Original line number Diff line number Diff line
@@ -486,11 +486,11 @@ static unsigned int br_nf_pre_routing(void *priv,
	struct brnf_net *brnet;

	if (unlikely(!pskb_may_pull(skb, len)))
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_PKT_TOO_SMALL, 0);

	p = br_port_get_rcu(state->in);
	if (p == NULL)
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_DEV_READY, 0);
	br = p->br;

	brnet = net_generic(state->net, brnf_net_id);
@@ -501,7 +501,7 @@ static unsigned int br_nf_pre_routing(void *priv,
			return NF_ACCEPT;
		if (!ipv6_mod_enabled()) {
			pr_warn_once("Module ipv6 is disabled, so call_ip6tables is not supported.");
			return NF_DROP;
			return NF_DROP_REASON(skb, SKB_DROP_REASON_IPV6DISABLED, 0);
		}

		nf_bridge_pull_encap_header_rcsum(skb);
@@ -518,12 +518,12 @@ static unsigned int br_nf_pre_routing(void *priv,
	nf_bridge_pull_encap_header_rcsum(skb);

	if (br_validate_ipv4(state->net, skb))
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_IP_INHDR, 0);

	if (!nf_bridge_alloc(skb))
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_NOMEM, 0);
	if (!setup_pre_routing(skb, state->net))
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_DEV_READY, 0);

	nf_bridge = nf_bridge_info_get(skb);
	nf_bridge->ipv4_daddr = ip_hdr(skb)->daddr;
@@ -590,15 +590,15 @@ static unsigned int br_nf_forward_ip(void *priv,
	/* Need exclusive nf_bridge_info since we might have multiple
	 * different physoutdevs. */
	if (!nf_bridge_unshare(skb))
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_NOMEM, 0);

	nf_bridge = nf_bridge_info_get(skb);
	if (!nf_bridge)
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_NOMEM, 0);

	parent = bridge_parent(state->out);
	if (!parent)
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_DEV_READY, 0);

	if (IS_IP(skb) || is_vlan_ip(skb, state->net) ||
	    is_pppoe_ip(skb, state->net))
@@ -618,13 +618,13 @@ static unsigned int br_nf_forward_ip(void *priv,

	if (pf == NFPROTO_IPV4) {
		if (br_validate_ipv4(state->net, skb))
			return NF_DROP;
			return NF_DROP_REASON(skb, SKB_DROP_REASON_IP_INHDR, 0);
		IPCB(skb)->frag_max_size = nf_bridge->frag_max_size;
	}

	if (pf == NFPROTO_IPV6) {
		if (br_validate_ipv6(state->net, skb))
			return NF_DROP;
			return NF_DROP_REASON(skb, SKB_DROP_REASON_IP_INHDR, 0);
		IP6CB(skb)->frag_max_size = nf_bridge->frag_max_size;
	}

@@ -666,7 +666,7 @@ static unsigned int br_nf_forward_arp(void *priv,
	}

	if (unlikely(!pskb_may_pull(skb, sizeof(struct arphdr))))
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_PKT_TOO_SMALL, 0);

	if (arp_hdr(skb)->ar_pln != 4) {
		if (is_vlan_arp(skb, state->net))
@@ -831,7 +831,7 @@ static unsigned int br_nf_post_routing(void *priv,
		return NF_ACCEPT;

	if (!realoutdev)
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_DEV_READY, 0);

	if (IS_IP(skb) || is_vlan_ip(skb, state->net) ||
	    is_pppoe_ip(skb, state->net))
+3 −3
Original line number Diff line number Diff line
@@ -161,13 +161,13 @@ unsigned int br_nf_pre_routing_ipv6(void *priv,
	struct nf_bridge_info *nf_bridge;

	if (br_validate_ipv6(state->net, skb))
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_IP_INHDR, 0);

	nf_bridge = nf_bridge_alloc(skb);
	if (!nf_bridge)
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_NOMEM, 0);
	if (!setup_pre_routing(skb, state->net))
		return NF_DROP;
		return NF_DROP_REASON(skb, SKB_DROP_REASON_DEV_READY, 0);

	nf_bridge = nf_bridge_info_get(skb);
	nf_bridge->ipv6_daddr = ipv6_hdr(skb)->daddr;
+5 −4
Original line number Diff line number Diff line
@@ -36,12 +36,12 @@ static const struct xt_table packet_mangler = {
static unsigned int
ipt_mangle_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
	unsigned int ret;
	unsigned int ret, verdict;
	const struct iphdr *iph;
	u_int8_t tos;
	__be32 saddr, daddr;
	u_int32_t mark;
	u32 mark;
	int err;
	u8 tos;

	/* Save things which could affect route */
	mark = skb->mark;
@@ -51,8 +51,9 @@ ipt_mangle_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *stat
	tos = iph->tos;

	ret = ipt_do_table(priv, skb, state);
	verdict = ret & NF_VERDICT_MASK;
	/* Reroute for ANY change. */
	if (ret != NF_DROP && ret != NF_STOLEN) {
	if (verdict != NF_DROP && verdict != NF_STOLEN) {
		iph = ip_hdr(skb);

		if (iph->saddr != saddr ||
Loading