]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net/sched: act_mirred: Fix return code in early mirred redirect error paths
authorVictor Nogueira <victor@mojatatu.com>
Mon, 25 May 2026 12:25:54 +0000 (08:25 -0400)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 28 May 2026 10:26:36 +0000 (12:26 +0200)
Since retval is set as TC_ACT_STOLEN in the mirred redirect case, returning
retval in cases where redirect failed will make the callers not register
the skb as being dropped.

Fix this by returning TC_ACT_SHOT instead in such scenarios.

Fixes: 16085e48cb48 ("net/sched: act_mirred: Create function tcf_mirred_to_dev and improve readability")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260413082027.2244884-1-hxzene%40gmail.com
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Link: https://patch.msgid.link/20260525122556.973584-8-jhs@mojatatu.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
net/sched/act_mirred.c

index dbe4a4ff3e08b870aa353e4100fbc22a019ba9f5..553342c55cf7c672a11a9a938532f47a1465301b 100644 (file)
@@ -372,7 +372,8 @@ assign_prev:
                                         dev_is_mac_header_xmit(dev_prev),
                                         m_eaction, retval);
 
-       return retval;
+       /* If the packet wasn't redirected, we have to register as a drop */
+       return TC_ACT_SHOT;
 }
 
 static int tcf_blockcast_mirror(struct sk_buff *skb, struct tcf_mirred *m,
@@ -410,7 +411,7 @@ static int tcf_blockcast(struct sk_buff *skb, struct tcf_mirred *m,
        block = tcf_block_lookup(dev_net(skb->dev), blockid);
        if (!block || xa_empty(&block->ports)) {
                tcf_action_inc_overlimit_qstats(&m->common);
-               return retval;
+               return is_redirect ? TC_ACT_SHOT : retval;
        }
 
        if (is_redirect)
@@ -428,8 +429,8 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
 {
        struct tcf_mirred *m = to_mirred(a);
        int retval = READ_ONCE(m->tcf_action);
+       bool m_mac_header_xmit, is_redirect;
        struct netdev_xmit *xmit;
-       bool m_mac_header_xmit;
        struct net_device *dev;
        bool want_ingress;
        int i, m_eaction;
@@ -462,11 +463,13 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
                return retval;
        }
 
+       is_redirect = tcf_mirred_is_act_redirect(m_eaction);
+
        dev = rcu_dereference_bh(m->tcfm_dev);
        if (unlikely(!dev)) {
                pr_notice_once("tc mirred: target device is gone\n");
                tcf_action_inc_overlimit_qstats(&m->common);
-               return retval;
+               goto err_out;
        }
 
        if (!want_ingress) {
@@ -476,7 +479,7 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
                        pr_notice_once("tc mirred: loop on device %s\n",
                                       netdev_name(dev));
                        tcf_action_inc_overlimit_qstats(&m->common);
-                       return retval;
+                       goto err_out;
                }
                xmit->sched_mirred_dev[xmit->sched_mirred_nest++] = dev;
        }
@@ -489,6 +492,11 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
                xmit->sched_mirred_nest--;
 
        return retval;
+
+err_out:
+       if (is_redirect)
+               retval = TC_ACT_SHOT;
+       return retval;
 }
 
 static void tcf_stats_update(struct tc_action *a, u64 bytes, u64 packets,