]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfilter: nft_reject_inet: allow to use reject from inet ingress
authorPablo Neira Ayuso <pablo@netfilter.org>
Sat, 31 Oct 2020 10:24:08 +0000 (11:24 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 28 Aug 2025 14:22:59 +0000 (16:22 +0200)
[ Upstream commit 117ca1f8920cf4087bf82f44bd2a51b49d6aae63 ]

Enhance validation to support for reject from inet ingress chains.

Note that, reject from inet ingress and netdev ingress differ.

Reject packets from inet ingress are sent through ip_local_out() since
inet reject emulates the IP layer receive path. So the reject packet
follows to classic IP output and postrouting paths.

The reject action from netdev ingress assumes the packet not yet entered
the IP layer, so the reject packet is sent through dev_queue_xmit().
Therefore, reject packets from netdev ingress do not follow the classic
IP output and postrouting paths.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Stable-dep-of: 91a79b792204 ("netfilter: nf_reject: don't leak dst refcount for loopback packets")
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/ipv4/netfilter/nf_reject_ipv4.c
net/ipv6/netfilter/nf_reject_ipv6.c
net/netfilter/nft_reject_inet.c

index efe14a6a5d9b8aa4206810b3c2f3f9058ac08910..d232e0251142cfd6eb336508b7707e04d84c9b52 100644 (file)
@@ -125,7 +125,8 @@ void nf_send_reset(struct net *net, struct sock *sk, struct sk_buff *oldskb,
        if (!oth)
                return;
 
-       if (hook == NF_INET_PRE_ROUTING && nf_reject_fill_skb_dst(oldskb))
+       if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) &&
+           nf_reject_fill_skb_dst(oldskb) < 0)
                return;
 
        if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
@@ -193,7 +194,8 @@ void nf_send_unreach(struct sk_buff *skb_in, int code, int hook)
        if (iph->frag_off & htons(IP_OFFSET))
                return;
 
-       if (hook == NF_INET_PRE_ROUTING && nf_reject_fill_skb_dst(skb_in))
+       if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) &&
+           nf_reject_fill_skb_dst(skb_in) < 0)
                return;
 
        if (skb_csum_unnecessary(skb_in) || !nf_reject_verify_csum(proto)) {
index df572724f254d8bd735d75d369bbc5b88a76ef52..b396559f68b4f93f792d838b3a637a0a3902bc9e 100644 (file)
@@ -161,7 +161,7 @@ void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb,
        fl6.fl6_sport = otcph->dest;
        fl6.fl6_dport = otcph->source;
 
-       if (hook == NF_INET_PRE_ROUTING) {
+       if (hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) {
                nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false);
                if (!dst)
                        return;
@@ -259,7 +259,8 @@ void nf_send_unreach6(struct net *net, struct sk_buff *skb_in,
        if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
                skb_in->dev = net->loopback_dev;
 
-       if (hooknum == NF_INET_PRE_ROUTING && nf_reject6_fill_skb_dst(skb_in))
+       if ((hooknum == NF_INET_PRE_ROUTING || hooknum == NF_INET_INGRESS) &&
+           nf_reject6_fill_skb_dst(skb_in) < 0)
                return;
 
        icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
index 115aa446f6d528f8b38f8f71a20c16db32fbbc22..554caf967baa20b322a65bff4ab6d8e82515a55e 100644 (file)
@@ -60,6 +60,18 @@ static void nft_reject_inet_eval(const struct nft_expr *expr,
        regs->verdict.code = NF_DROP;
 }
 
+static int nft_reject_inet_validate(const struct nft_ctx *ctx,
+                                   const struct nft_expr *expr,
+                                   const struct nft_data **data)
+{
+       return nft_chain_validate_hooks(ctx->chain,
+                                       (1 << NF_INET_LOCAL_IN) |
+                                       (1 << NF_INET_FORWARD) |
+                                       (1 << NF_INET_LOCAL_OUT) |
+                                       (1 << NF_INET_PRE_ROUTING) |
+                                       (1 << NF_INET_INGRESS));
+}
+
 static struct nft_expr_type nft_reject_inet_type;
 static const struct nft_expr_ops nft_reject_inet_ops = {
        .type           = &nft_reject_inet_type,
@@ -67,7 +79,7 @@ static const struct nft_expr_ops nft_reject_inet_ops = {
        .eval           = nft_reject_inet_eval,
        .init           = nft_reject_init,
        .dump           = nft_reject_dump,
-       .validate       = nft_reject_validate,
+       .validate       = nft_reject_inet_validate,
 };
 
 static struct nft_expr_type nft_reject_inet_type __read_mostly = {