]> git.itanic.dy.fi Git - linux-stable/commitdiff
netfilter: make nftables drops visible in net dropmonitor
authorFlorian Westphal <fw@strlen.de>
Wed, 11 Oct 2023 07:59:38 +0000 (09:59 +0200)
committerFlorian Westphal <fw@strlen.de>
Wed, 18 Oct 2023 08:26:43 +0000 (10:26 +0200)
net_dropmonitor blames core.c:nf_hook_slow.
Add NF_DROP_REASON() helper and use it in nft_do_chain().

The helper releases the skb, so exact drop location becomes
available. Calling code will observe the NF_STOLEN verdict
instead.

Adjust nf_hook_slow so we can embed an erro value wih
NF_STOLEN verdicts, just like we do for NF_DROP.

After this, drop in nftables can be pinpointed to a drop due
to a rule or the chain policy.

Signed-off-by: Florian Westphal <fw@strlen.de>
include/linux/netfilter.h
net/netfilter/core.c
net/netfilter/nf_tables_core.c

index d68644b7c299ebc5fec7360563c204d934439f8c..80900d9109920f686f971e431b95361a831fcc26 100644 (file)
@@ -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)
 {
index ef4e76e5aef9f5e1ecc27a9423b94aa96101154c..3126911f5042592a33594053c1225c265a2fd2c1 100644 (file)
@@ -639,10 +639,10 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
                        if (ret == 1)
                                continue;
                        return ret;
+               case NF_STOLEN:
+                       return NF_DROP_GETERR(verdict);
                default:
-                       /* Implicit handling for NF_STOLEN, as well as any other
-                        * non conventional verdicts.
-                        */
+                       WARN_ON_ONCE(1);
                        return 0;
                }
        }
index 6009b423f60aae61e75ca91dcdaf73bc9bee26a8..8b536d7ef6c245ff27bd656a6400131bacd029fa 100644 (file)
@@ -308,10 +308,11 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
 
        switch (regs.verdict.code & NF_VERDICT_MASK) {
        case NF_ACCEPT:
-       case NF_DROP:
        case NF_QUEUE:
        case NF_STOLEN:
                return regs.verdict.code;
+       case NF_DROP:
+               return NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
        }
 
        switch (regs.verdict.code) {
@@ -342,6 +343,9 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
        if (static_branch_unlikely(&nft_counters_enabled))
                nft_update_chain_stats(basechain, pkt);
 
+       if (nft_base_chain(basechain)->policy == NF_DROP)
+               return NF_DROP_REASON(pkt->skb, SKB_DROP_REASON_NETFILTER_DROP, EPERM);
+
        return nft_base_chain(basechain)->policy;
 }
 EXPORT_SYMBOL_GPL(nft_do_chain);