net: sched: act_mirred: drop dst for the direction from egress to ingress
authorXin Long <lucien.xin@gmail.com>
Fri, 12 Nov 2021 16:33:11 +0000 (11:33 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Nov 2021 08:48:38 +0000 (09:48 +0100)
[ Upstream commit f799ada6bf2397c351220088b9b0980125c77280 ]

Without dropping dst, the packets sent from local mirred/redirected
to ingress will may still use the old dst. ip_rcv() will drop it as
the old dst is for output and its .input is dst_discard.

This patch is to fix by also dropping dst for those packets that are
mirred or redirected from egress to ingress in act_mirred.

Note that we don't drop it for the direction change from ingress to
egress, as on which there might be a user case attaching a metadata
dst by act_tunnel_key that would be used later.

Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Cong Wang <cong.wang@bytedance.com>
Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/sched/act_mirred.c

index d64b0ee..efc963a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/if_arp.h>
 #include <net/net_namespace.h>
 #include <net/netlink.h>
+#include <net/dst.h>
 #include <net/pkt_sched.h>
 #include <net/pkt_cls.h>
 #include <linux/tc_act/tc_mirred.h>
@@ -228,6 +229,7 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
        bool want_ingress;
        bool is_redirect;
        bool expects_nh;
+       bool at_ingress;
        int m_eaction;
        int mac_len;
        bool at_nh;
@@ -263,7 +265,8 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
         * ingress - that covers the TC S/W datapath.
         */
        is_redirect = tcf_mirred_is_act_redirect(m_eaction);
-       use_reinsert = skb_at_tc_ingress(skb) && is_redirect &&
+       at_ingress = skb_at_tc_ingress(skb);
+       use_reinsert = at_ingress && is_redirect &&
                       tcf_mirred_can_reinsert(retval);
        if (!use_reinsert) {
                skb2 = skb_clone(skb, GFP_ATOMIC);
@@ -271,10 +274,12 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
                        goto out;
        }
 
+       want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
+
        /* All mirred/redirected skbs should clear previous ct info */
        nf_reset_ct(skb2);
-
-       want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
+       if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */
+               skb_dst_drop(skb2);
 
        expects_nh = want_ingress || !m_mac_header_xmit;
        at_nh = skb->data == skb_network_header(skb);