]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: dsa: Fix skb ownership in taggers
authorLinus Walleij <linusw@kernel.org>
Thu, 25 Jun 2026 07:47:01 +0000 (09:47 +0200)
committerJakub Kicinski <kuba@kernel.org>
Sat, 27 Jun 2026 22:44:12 +0000 (15:44 -0700)
The tag_8021q.c tagger calls vlan_insert_tag() in dsa_8021q_xmit().
vlan_insert_tag() will consume the skb with kfree_skb() on failure
and return NULL.

When NULL is returned as error code to ->xmit() in dsa_user_xmit()
it will free the same skb again leading to a double-free.

The idea of dsa_user_xmit() and dsa_switch_rcv() dropping the skb
they held before the call to ->xmit() and ->rcv() is conceptually
wrong: the pattern elsewhere in the networking code is that consumers
drop their skb:s on failure.

Modify the ->xmit() and ->rcv() call sites to not drop the SKB if
the taggers return NULL from any of these calls. Move those drops into
the taggers so every callback error path that retains ownership consumes
the skb before returning NULL.

Keep the existing helper ownership rules: VLAN insertion helpers already
free on failure (this is the case in tag_8021q.c), while deferred
transmit paths either transfer the skb reference to worker context or
hold a worker reference with skb_get() and drop the caller's reference.

For SJA1105 meta RX, transfer the buffered stampable skb under the meta
lock and return NULL while the skb is waiting for its meta frame: the
skb is not dropped in this case.

NOTICE: Backporting patches to taggers (e.g. for stable kernels) after
this point cannot be mechanical or they will introduce double
kfree_skb().

Reported-by: Sashiko AI Review <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/r/20260610153952.1685895-1-kuba@kernel.org/
Suggested-by: Jakub Kicinski <kuba@kernel.org>
Acked-by: David Yang <mmyangfl@gmail.com> # yt921x
Acked-by: Kurt Kanzenbach <kurt@linutronix.de> # hellcreek
Reviewed-by: Wei Fang <wei.fang@nxp.com> # netc
Signed-off-by: Linus Walleij <linusw@kernel.org>
Link: https://patch.msgid.link/20260625-dsa-fix-free-skb-v5-1-b5931e4cbdb0@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
24 files changed:
net/dsa/tag.c
net/dsa/tag_ar9331.c
net/dsa/tag_brcm.c
net/dsa/tag_dsa.c
net/dsa/tag_gswip.c
net/dsa/tag_hellcreek.c
net/dsa/tag_ksz.c
net/dsa/tag_lan9303.c
net/dsa/tag_mtk.c
net/dsa/tag_mxl-gsw1xx.c
net/dsa/tag_mxl862xx.c
net/dsa/tag_netc.c
net/dsa/tag_ocelot.c
net/dsa/tag_ocelot_8021q.c
net/dsa/tag_qca.c
net/dsa/tag_rtl4_a.c
net/dsa/tag_rtl8_4.c
net/dsa/tag_rzn1_a5psw.c
net/dsa/tag_sja1105.c
net/dsa/tag_trailer.c
net/dsa/tag_vsc73xx_8021q.c
net/dsa/tag_xrs700x.c
net/dsa/tag_yt921x.c
net/dsa/user.c

index 79ad105902d9780de56cfac7852abbd80829ffa8..991732d6eae2c32175795d6d87b4309eedc6b8e0 100644 (file)
@@ -79,15 +79,16 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
                if (likely(skb->dev)) {
                        dsa_default_offload_fwd_mark(skb);
                        nskb = skb;
+               } else {
+                       /* Just drop the skb if we can't find the user */
+                       kfree_skb(skb);
                }
        } else {
                nskb = cpu_dp->rcv(skb, dev);
        }
 
-       if (!nskb) {
-               kfree_skb(skb);
+       if (!nskb)
                return 0;
-       }
 
        skb = nskb;
        skb_push(skb, ETH_HLEN);
@@ -107,11 +108,10 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
 
        if (unlikely(cpu_dp->ds->untag_bridge_pvid ||
                     cpu_dp->ds->untag_vlan_aware_bridge_pvid)) {
+               /* dsa_software_vlan_untag() drops skb on failure */
                nskb = dsa_software_vlan_untag(skb);
-               if (!nskb) {
-                       kfree_skb(skb);
+               if (!nskb)
                        return 0;
-               }
                skb = nskb;
        }
 
index cbb588ca73aaf50ae0f261c842392a45c2bc5d46..2e2388143b02511c936438868d604d2ad7f1ac8c 100644 (file)
@@ -51,8 +51,10 @@ static struct sk_buff *ar9331_tag_rcv(struct sk_buff *skb,
        u8 ver, port;
        u16 hdr;
 
-       if (unlikely(!pskb_may_pull(skb, AR9331_HDR_LEN)))
+       if (unlikely(!pskb_may_pull(skb, AR9331_HDR_LEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        hdr = le16_to_cpu(*(__le16 *)skb_mac_header(skb));
 
@@ -60,12 +62,14 @@ static struct sk_buff *ar9331_tag_rcv(struct sk_buff *skb,
        if (unlikely(ver != AR9331_HDR_VERSION)) {
                netdev_warn_once(ndev, "%s:%i wrong header version 0x%2x\n",
                                 __func__, __LINE__, hdr);
+               kfree_skb(skb);
                return NULL;
        }
 
        if (unlikely(hdr & AR9331_HDR_FROM_CPU)) {
                netdev_warn_once(ndev, "%s:%i packet should not be from cpu 0x%2x\n",
                                 __func__, __LINE__, hdr);
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -75,8 +79,10 @@ static struct sk_buff *ar9331_tag_rcv(struct sk_buff *skb,
        port = FIELD_GET(AR9331_HDR_PORT_NUM_MASK, hdr);
 
        skb->dev = dsa_conduit_find_user(ndev, 0, port);
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        return skb;
 }
index cf94204390543f1584bab3b5f0fd60c858402303..411e3b57d16af5fe0dae78f5f3f9773c59596881 100644 (file)
@@ -102,9 +102,9 @@ static struct sk_buff *brcm_tag_xmit_ll(struct sk_buff *skb,
         * (including FCS and tag) because the length verification is done after
         * the Broadcom tag is stripped off the ingress packet.
         *
-        * Let dsa_user_xmit() free the SKB
+        * Free the SKB on error.
         */
-       if (__skb_put_padto(skb, ETH_ZLEN + BRCM_TAG_LEN, false))
+       if (skb_put_padto(skb, ETH_ZLEN + BRCM_TAG_LEN))
                return NULL;
 
        skb_push(skb, BRCM_TAG_LEN);
@@ -151,27 +151,35 @@ static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb,
        int source_port;
        u8 *brcm_tag;
 
-       if (unlikely(!pskb_may_pull(skb, BRCM_TAG_LEN)))
+       if (unlikely(!pskb_may_pull(skb, BRCM_TAG_LEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        brcm_tag = skb->data - offset;
 
        /* The opcode should never be different than 0b000 */
-       if (unlikely((brcm_tag[0] >> BRCM_OPCODE_SHIFT) & BRCM_OPCODE_MASK))
+       if (unlikely((brcm_tag[0] >> BRCM_OPCODE_SHIFT) & BRCM_OPCODE_MASK)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* We should never see a reserved reason code without knowing how to
         * handle it
         */
-       if (unlikely(brcm_tag[2] & BRCM_EG_RC_RSVD))
+       if (unlikely(brcm_tag[2] & BRCM_EG_RC_RSVD)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Locate which port this is coming from */
        source_port = brcm_tag[3] & BRCM_EG_PID_MASK;
 
        skb->dev = dsa_conduit_find_user(dev, 0, source_port);
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Remove Broadcom tag and update checksum */
        skb_pull_rcsum(skb, BRCM_TAG_LEN);
@@ -228,8 +236,10 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
        __be16 *proto;
        u8 *brcm_tag;
 
-       if (unlikely(!pskb_may_pull(skb, BRCM_LEG_TAG_LEN + VLAN_HLEN)))
+       if (unlikely(!pskb_may_pull(skb, BRCM_LEG_TAG_LEN + VLAN_HLEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        brcm_tag = dsa_etype_header_pos_rx(skb);
        proto = (__be16 *)(brcm_tag + BRCM_LEG_TAG_LEN);
@@ -237,8 +247,10 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
        source_port = brcm_tag[5] & BRCM_LEG_PORT_ID;
 
        skb->dev = dsa_conduit_find_user(dev, 0, source_port);
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* The internal switch in BCM63XX SoCs always tags on egress on the CPU
         * port. We use VID 0 internally for untagged traffic, so strip the tag
@@ -273,10 +285,8 @@ static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb,
         * need to make sure that packets are at least 70 bytes
         * (including FCS and tag) because the length verification is done after
         * the Broadcom tag is stripped off the ingress packet.
-        *
-        * Let dsa_user_xmit() free the SKB
         */
-       if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false))
+       if (skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN))
                return NULL;
 
        skb_push(skb, BRCM_LEG_TAG_LEN);
@@ -325,10 +335,8 @@ static struct sk_buff *brcm_leg_fcs_tag_xmit(struct sk_buff *skb,
         * need to make sure that packets are at least 70 bytes (including FCS
         * and tag) because the length verification is done after the Broadcom
         * tag is stripped off the ingress packet.
-        *
-        * Let dsa_user_xmit() free the SKB.
         */
-       if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false))
+       if (skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN))
                return NULL;
 
        fcs_len = skb->len;
@@ -351,8 +359,9 @@ static struct sk_buff *brcm_leg_fcs_tag_xmit(struct sk_buff *skb,
        brcm_tag[5] = dp->index & BRCM_LEG_PORT_ID;
 
        /* Original FCS value */
-       if (__skb_pad(skb, ETH_FCS_LEN, false))
+       if (skb_pad(skb, ETH_FCS_LEN))
                return NULL;
+
        skb_put_data(skb, &fcs_val, ETH_FCS_LEN);
 
        return skb;
index 2a2c4fb61a65c6e89f1c405aca6032dd236de5ba..d5ffee35fbb53b1317ea2ff7ac4c4b56bbd54d0a 100644 (file)
@@ -224,6 +224,7 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,
                        /* Remote management is not implemented yet,
                         * drop.
                         */
+                       kfree_skb(skb);
                        return NULL;
                case DSA_CODE_ARP_MIRROR:
                case DSA_CODE_POLICY_MIRROR:
@@ -244,12 +245,14 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,
                        /* Reserved code, this could be anything. Drop
                         * seems like the safest option.
                         */
+                       kfree_skb(skb);
                        return NULL;
                }
 
                break;
 
        default:
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -271,8 +274,10 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,
                                                 source_port);
        }
 
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* When using LAG offload, skb->dev is not a DSA user interface,
         * so we cannot call dsa_default_offload_fwd_mark and we need to
@@ -335,8 +340,10 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
 
 static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev)
 {
-       if (unlikely(!pskb_may_pull(skb, DSA_HLEN)))
+       if (unlikely(!pskb_may_pull(skb, DSA_HLEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        return dsa_rcv_ll(skb, dev, 0);
 }
@@ -375,8 +382,10 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
 
 static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev)
 {
-       if (unlikely(!pskb_may_pull(skb, EDSA_HLEN)))
+       if (unlikely(!pskb_may_pull(skb, EDSA_HLEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        skb_pull_rcsum(skb, EDSA_HLEN - DSA_HLEN);
 
index 5fa436121087b456d4cebcf1d5d19eef33f3dc91..5c407d448c9fee2b0027c7acf5ac992e9754468f 100644 (file)
@@ -80,16 +80,20 @@ static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
        int port;
        u8 *gswip_tag;
 
-       if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))
+       if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        gswip_tag = skb->data - ETH_HLEN;
 
        /* Get source port information */
        port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT;
        skb->dev = dsa_conduit_find_user(dev, 0, port);
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* remove GSWIP tag */
        skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);
index 544ab15685a2b80ca9404a2524f5c728a65e1262..dd9f328f31821046caa35a895ebf10165665b7a2 100644 (file)
@@ -27,8 +27,10 @@ static struct sk_buff *hellcreek_xmit(struct sk_buff *skb,
         * checksums after the switch strips the tag.
         */
        if (skb->ip_summed == CHECKSUM_PARTIAL &&
-           skb_checksum_help(skb))
+           skb_checksum_help(skb)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Tag encoding */
        tag  = skb_put(skb, HELLCREEK_TAG_LEN);
@@ -47,11 +49,14 @@ static struct sk_buff *hellcreek_rcv(struct sk_buff *skb,
        skb->dev = dsa_conduit_find_user(dev, 0, port);
        if (!skb->dev) {
                netdev_warn_once(dev, "Failed to get source port: %d\n", port);
+               kfree_skb(skb);
                return NULL;
        }
 
-       if (pskb_trim_rcsum(skb, skb->len - HELLCREEK_TAG_LEN))
+       if (pskb_trim_rcsum(skb, skb->len - HELLCREEK_TAG_LEN)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        dsa_default_offload_fwd_mark(skb);
 
index d2475c3bbb7d227bb42b0368914275b00fb2784a..67fa89f102e070d82ca5938ef0ce0f9e964d1d3e 100644 (file)
@@ -88,11 +88,15 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
                                      unsigned int port, unsigned int len)
 {
        skb->dev = dsa_conduit_find_user(dev, 0, port);
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
-       if (pskb_trim_rcsum(skb, skb->len - len))
+       if (pskb_trim_rcsum(skb, skb->len - len)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        dsa_default_offload_fwd_mark(skb);
 
@@ -123,8 +127,10 @@ static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
        struct ethhdr *hdr;
        u8 *tag;
 
-       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Tag encoding */
        tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
@@ -141,8 +147,10 @@ static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev)
 {
        u8 *tag;
 
-       if (skb_linearize(skb))
+       if (skb_linearize(skb)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
 
@@ -255,22 +263,24 @@ static struct sk_buff *ksz_defer_xmit(struct dsa_port *dp, struct sk_buff *skb)
        xmit_work_fn = tagger_data->xmit_work_fn;
        xmit_worker = priv->xmit_worker;
 
-       if (!xmit_work_fn || !xmit_worker)
+       if (!xmit_work_fn || !xmit_worker) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        xmit_work = kzalloc_obj(*xmit_work, GFP_ATOMIC);
-       if (!xmit_work)
+       if (!xmit_work) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        kthread_init_work(&xmit_work->work, xmit_work_fn);
-       /* Increase refcount so the kfree_skb in dsa_user_xmit
-        * won't really free the packet.
-        */
        xmit_work->dp = dp;
        xmit_work->skb = skb_get(skb);
 
        kthread_queue_work(xmit_worker, &xmit_work->work);
 
+       kfree_skb(skb);
        return NULL;
 }
 
@@ -284,8 +294,10 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
        __be16 *tag;
        u16 val;
 
-       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Tag encoding */
        ksz_xmit_timestamp(dp, skb);
@@ -310,8 +322,10 @@ static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev)
        unsigned int port;
        u8 *tag;
 
-       if (skb_linearize(skb))
+       if (skb_linearize(skb)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Tag decoding */
        tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
@@ -352,8 +366,10 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
        struct ethhdr *hdr;
        u8 *tag;
 
-       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Tag encoding */
        ksz_xmit_timestamp(dp, skb);
@@ -418,8 +434,10 @@ static struct sk_buff *lan937x_xmit(struct sk_buff *skb,
        __be16 *tag;
        u16 val;
 
-       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        ksz_xmit_timestamp(dp, skb);
 
index 258e5d7dc5ef8454c85532d1b744323cb5c203aa..d1194696499ab87964c83922a39e5b5e5e8b14c4 100644 (file)
@@ -85,6 +85,7 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev)
        if (unlikely(!pskb_may_pull(skb, LAN9303_TAG_LEN))) {
                dev_warn_ratelimited(&dev->dev,
                                     "Dropping packet, cannot pull\n");
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -102,6 +103,7 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev)
        skb->dev = dsa_conduit_find_user(dev, 0, source_port);
        if (!skb->dev) {
                dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n");
+               kfree_skb(skb);
                return NULL;
        }
 
index dea3eecaf093df29b78473a3a4a0a2ecc8ad3026..c7dc7731675ec0b0a70319daf88463e367006496 100644 (file)
@@ -72,8 +72,10 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)
        int port;
        __be16 *phdr;
 
-       if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
+       if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        phdr = dsa_etype_header_pos_rx(skb);
        hdr = ntohs(*phdr);
@@ -87,8 +89,10 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)
        port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
 
        skb->dev = dsa_conduit_find_user(dev, 0, port);
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        dsa_default_offload_fwd_mark(skb);
 
index 60f7c445e656107fb7778818f760067443ae309a..4b1b6ef94196344dc8c6c961ec39f8690b13a436 100644 (file)
@@ -73,6 +73,7 @@ static struct sk_buff *gsw1xx_tag_rcv(struct sk_buff *skb,
 
        if (unlikely(!pskb_may_pull(skb, GSW1XX_HEADER_LEN))) {
                dev_warn_ratelimited(&dev->dev, "Dropping packet, cannot pull SKB\n");
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -81,6 +82,7 @@ static struct sk_buff *gsw1xx_tag_rcv(struct sk_buff *skb,
        if (unlikely(ntohs(gsw1xx_tag[0]) != ETH_P_MXLGSW)) {
                dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid special tag\n");
                dev_warn_ratelimited(&dev->dev, "Tag: %8ph\n", gsw1xx_tag);
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -90,6 +92,7 @@ static struct sk_buff *gsw1xx_tag_rcv(struct sk_buff *skb,
        if (!skb->dev) {
                dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n");
                dev_warn_ratelimited(&dev->dev, "Tag: %8ph\n", gsw1xx_tag);
+               kfree_skb(skb);
                return NULL;
        }
 
index 8daefeb8d49dfacf31a8d28da8f37ce8e4a8a322..87b80ddf094632fd2842be9ef63daa277fd5596c 100644 (file)
@@ -64,6 +64,7 @@ static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,
 
        if (unlikely(!pskb_may_pull(skb, MXL862_HEADER_LEN))) {
                dev_warn_ratelimited(&dev->dev, "Cannot pull SKB, packet dropped\n");
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -73,6 +74,7 @@ static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,
                dev_warn_ratelimited(&dev->dev,
                                     "Invalid special tag marker, packet dropped, tag: %8ph\n",
                                     mxl862_tag);
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -83,6 +85,7 @@ static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,
                dev_warn_ratelimited(&dev->dev,
                                     "Invalid source port, packet dropped, tag: %8ph\n",
                                     mxl862_tag);
+               kfree_skb(skb);
                return NULL;
        }
 
index ccedfe3a80b64d835f024880c583c108b8c94c8d..df72a61796ad5f41bca04cf765218b06a0094fe0 100644 (file)
@@ -131,14 +131,13 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,
        int type, subtype;
 
        if (unlikely(!pskb_may_pull(skb, NETC_TAG_MAX_LEN)))
-               return NULL;
+               goto err_free_skb;
 
        tag_cmn = dsa_etype_header_pos_rx(skb);
        if (ntohs(tag_cmn->tpid) != ETH_P_NXP_NETC) {
                dev_warn_ratelimited(&ndev->dev, "Unknown TPID 0x%04x\n",
                                     ntohs(tag_cmn->tpid));
-
-               return NULL;
+               goto err_free_skb;
        }
 
        if (tag_cmn->qos & NETC_TAG_QV)
@@ -149,14 +148,13 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,
        if (!sw_id) {
                dev_warn_ratelimited(&ndev->dev,
                                     "VEPA switch ID is not supported yet\n");
-
-               return NULL;
+               goto err_free_skb;
        }
 
        port = FIELD_GET(NETC_TAG_PORT, tag_cmn->switch_port);
        skb->dev = dsa_conduit_find_user(ndev, sw_id, port);
        if (!skb->dev)
-               return NULL;
+               goto err_free_skb;
 
        type = FIELD_GET(NETC_TAG_TYPE, tag_cmn->type);
        subtype = FIELD_GET(NETC_TAG_SUBTYPE, tag_cmn->type);
@@ -165,11 +163,11 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,
        } else if (type == NETC_TAG_TO_HOST) {
                /* Currently only subtype0 supported */
                if (subtype != NETC_TAG_TH_SUBTYPE0)
-                       return NULL;
+                       goto err_free_skb;
        } else {
                dev_warn_ratelimited(&ndev->dev,
                                     "Unexpected  tag type %d\n", type);
-               return NULL;
+               goto err_free_skb;
        }
 
        /* Remove Switch tag from the frame */
@@ -178,6 +176,10 @@ static struct sk_buff *netc_rcv(struct sk_buff *skb,
        dsa_strip_etype_header(skb, tag_len);
 
        return skb;
+
+err_free_skb:
+       kfree_skb(skb);
+       return NULL;
 }
 
 static void netc_flow_dissect(const struct sk_buff *skb, __be16 *proto,
index 3405def79c2def187fe70de8f8e0a5be8377c87d..d208c7322cd6264d8374ca38dd25f6ff8a6c7620 100644 (file)
@@ -107,14 +107,16 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
        ocelot_xfh_get_rew_val(extraction, &rew_val);
 
        skb->dev = dsa_conduit_find_user(netdev, 0, src_port);
-       if (!skb->dev)
+       if (!skb->dev) {
                /* The switch will reflect back some frames sent through
                 * sockets opened on the bare DSA conduit. These will come back
                 * with src_port equal to the index of the CPU port, for which
                 * there is no user registered. So don't print any error
                 * message here (ignore and drop those frames).
                 */
+               kfree_skb(skb);
                return NULL;
+       }
 
        dsa_default_offload_fwd_mark(skb);
        skb->priority = qos_class;
index e89d9254e90a3a29b8ecac7b2aeacdd1df03a34c..f50f1cd83f161cca7e73e7289f0f8e47918c5b5f 100644 (file)
@@ -33,30 +33,34 @@ static struct sk_buff *ocelot_defer_xmit(struct dsa_port *dp,
        xmit_work_fn = data->xmit_work_fn;
        xmit_worker = priv->xmit_worker;
 
-       if (!xmit_work_fn || !xmit_worker)
+       if (!xmit_work_fn || !xmit_worker) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* PTP over IP packets need UDP checksumming. We may have inherited
         * NETIF_F_HW_CSUM from the DSA conduit, but these packets are not sent
         * through the DSA conduit, so calculate the checksum here.
         */
-       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        xmit_work = kzalloc_obj(*xmit_work, GFP_ATOMIC);
-       if (!xmit_work)
+       if (!xmit_work) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Calls felix_port_deferred_xmit in felix.c */
        kthread_init_work(&xmit_work->work, xmit_work_fn);
-       /* Increase refcount so the kfree_skb in dsa_user_xmit
-        * won't really free the packet.
-        */
        xmit_work->dp = dp;
        xmit_work->skb = skb_get(skb);
 
        kthread_queue_work(xmit_worker, &xmit_work->work);
 
+       kfree_skb(skb);
        return NULL;
 }
 
@@ -84,8 +88,10 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
        dsa_8021q_rcv(skb, &src_port, &switch_id, NULL, NULL);
 
        skb->dev = dsa_conduit_find_user(netdev, switch_id, src_port);
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        dsa_default_offload_fwd_mark(skb);
 
index 9e3b429e8b362510e659c2ed5975caba21aad26c..510792fbfa92dd40be2ddcae446ea0c512506cf4 100644 (file)
@@ -46,16 +46,20 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)
 
        tagger_data = ds->tagger_data;
 
-       if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN)))
+       if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        phdr = dsa_etype_header_pos_rx(skb);
        hdr = ntohs(*phdr);
 
        /* Make sure the version is correct */
        ver = FIELD_GET(QCA_HDR_RECV_VERSION, hdr);
-       if (unlikely(ver != QCA_HDR_VERSION))
+       if (unlikely(ver != QCA_HDR_VERSION)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Get pk type */
        pk_type = FIELD_GET(QCA_HDR_RECV_TYPE, hdr);
@@ -64,6 +68,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)
        if (pk_type == QCA_HDR_RECV_TYPE_RW_REG_ACK) {
                if (likely(tagger_data->rw_reg_ack_handler))
                        tagger_data->rw_reg_ack_handler(ds, skb);
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -71,6 +76,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)
        if (pk_type == QCA_HDR_RECV_TYPE_MIB) {
                if (likely(tagger_data->mib_autocast_handler))
                        tagger_data->mib_autocast_handler(ds, skb);
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -78,8 +84,10 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)
        port = FIELD_GET(QCA_HDR_RECV_SOURCE_PORT, hdr);
 
        skb->dev = dsa_conduit_find_user(dev, 0, port);
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Remove QCA tag and recalculate checksum */
        skb_pull_rcsum(skb, QCA_HDR_LEN);
index 3cc63eacfa0352e98d1748bd7912b36e225deee9..590ea3b921c9d9740c3b715b088d490ef2939358 100644 (file)
@@ -41,7 +41,7 @@ static struct sk_buff *rtl4a_tag_xmit(struct sk_buff *skb,
        u16 out;
 
        /* Pad out to at least 60 bytes */
-       if (unlikely(__skb_put_padto(skb, ETH_ZLEN, false)))
+       if (unlikely(eth_skb_pad(skb)))
                return NULL;
 
        netdev_dbg(dev, "add realtek tag to package to port %d\n",
@@ -75,8 +75,10 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
        u8 prot;
        u8 port;
 
-       if (unlikely(!pskb_may_pull(skb, RTL4_A_HDR_LEN)))
+       if (unlikely(!pskb_may_pull(skb, RTL4_A_HDR_LEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        tag = dsa_etype_header_pos_rx(skb);
        p = (__be16 *)tag;
@@ -92,6 +94,7 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
        prot = (protport >> RTL4_A_PROTOCOL_SHIFT) & 0x0f;
        if (prot != RTL4_A_PROTOCOL_RTL8366RB) {
                netdev_err(dev, "unknown realtek protocol 0x%01x\n", prot);
+               kfree_skb(skb);
                return NULL;
        }
        port = protport & 0xff;
@@ -99,6 +102,7 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
        skb->dev = dsa_conduit_find_user(dev, 0, port);
        if (!skb->dev) {
                netdev_dbg(dev, "could not find user for port %d\n", port);
+               kfree_skb(skb);
                return NULL;
        }
 
index 852c6b88079a13c8d93c9ccb7e0904f52b1c920c..4da3beebef75e290e218fca981c15aa8122a3e95 100644 (file)
@@ -143,8 +143,10 @@ static struct sk_buff *rtl8_4t_tag_xmit(struct sk_buff *skb,
        /* Calculate the checksum here if not done yet as trailing tags will
         * break either software or hardware based checksum
         */
-       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        rtl8_4_write_tag(skb, dev, skb_put(skb, RTL8_4_TAG_LEN));
 
@@ -201,11 +203,15 @@ static int rtl8_4_read_tag(struct sk_buff *skb, struct net_device *dev,
 static struct sk_buff *rtl8_4_tag_rcv(struct sk_buff *skb,
                                      struct net_device *dev)
 {
-       if (unlikely(!pskb_may_pull(skb, RTL8_4_TAG_LEN)))
+       if (unlikely(!pskb_may_pull(skb, RTL8_4_TAG_LEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
-       if (unlikely(rtl8_4_read_tag(skb, dev, dsa_etype_header_pos_rx(skb))))
+       if (unlikely(rtl8_4_read_tag(skb, dev, dsa_etype_header_pos_rx(skb)))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Remove tag and recalculate checksum */
        skb_pull_rcsum(skb, RTL8_4_TAG_LEN);
@@ -218,14 +224,20 @@ static struct sk_buff *rtl8_4_tag_rcv(struct sk_buff *skb,
 static struct sk_buff *rtl8_4t_tag_rcv(struct sk_buff *skb,
                                       struct net_device *dev)
 {
-       if (skb_linearize(skb))
+       if (skb_linearize(skb)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
-       if (unlikely(rtl8_4_read_tag(skb, dev, skb_tail_pointer(skb) - RTL8_4_TAG_LEN)))
+       if (unlikely(rtl8_4_read_tag(skb, dev, skb_tail_pointer(skb) - RTL8_4_TAG_LEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
-       if (pskb_trim_rcsum(skb, skb->len - RTL8_4_TAG_LEN))
+       if (pskb_trim_rcsum(skb, skb->len - RTL8_4_TAG_LEN)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        return skb;
 }
index 10994b3470f67a915d4c1ecc6879cc7fff7b1653..734910156dc333a401044dc9a20951873f118a79 100644 (file)
@@ -48,7 +48,7 @@ static struct sk_buff *a5psw_tag_xmit(struct sk_buff *skb, struct net_device *de
         * least 60 bytes otherwise they will be discarded when they enter the
         * switch port logic.
         */
-       if (__skb_put_padto(skb, ETH_ZLEN, false))
+       if (eth_skb_pad(skb))
                return NULL;
 
        /* provide 'A5PSW_TAG_LEN' bytes additional space */
@@ -77,6 +77,7 @@ static struct sk_buff *a5psw_tag_rcv(struct sk_buff *skb,
        if (unlikely(!pskb_may_pull(skb, A5PSW_TAG_LEN))) {
                dev_warn_ratelimited(&dev->dev,
                                     "Dropping packet, cannot pull\n");
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -84,14 +85,17 @@ static struct sk_buff *a5psw_tag_rcv(struct sk_buff *skb,
 
        if (tag->ctrl_tag != htons(ETH_P_DSA_A5PSW)) {
                dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid TAG marker\n");
+               kfree_skb(skb);
                return NULL;
        }
 
        port = FIELD_GET(A5PSW_CTRL_DATA_PORT, ntohs(tag->ctrl_data));
 
        skb->dev = dsa_conduit_find_user(dev, 0, port);
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        skb_pull_rcsum(skb, A5PSW_TAG_LEN);
        dsa_strip_etype_header(skb, A5PSW_TAG_LEN);
index de6d4ce8668be1afd562f333bf2712ca5c26e74a..bfe1f746f55be56164d382566d3b51fa98e59d72 100644 (file)
@@ -149,19 +149,20 @@ static struct sk_buff *sja1105_defer_xmit(struct dsa_port *dp,
        xmit_work_fn = tagger_data->xmit_work_fn;
        xmit_worker = priv->xmit_worker;
 
-       if (!xmit_work_fn || !xmit_worker)
+       if (!xmit_work_fn || !xmit_worker) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        xmit_work = kzalloc_obj(*xmit_work, GFP_ATOMIC);
-       if (!xmit_work)
+       if (!xmit_work) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        kthread_init_work(&xmit_work->work, xmit_work_fn);
-       /* Increase refcount so the kfree_skb in dsa_user_xmit
-        * won't really free the packet.
-        */
        xmit_work->dp = dp;
-       xmit_work->skb = skb_get(skb);
+       xmit_work->skb = skb;
 
        kthread_queue_work(xmit_worker, &xmit_work->work);
 
@@ -401,10 +402,7 @@ static struct sk_buff
                        kfree_skb(priv->stampable_skb);
                }
 
-               /* Hold a reference to avoid dsa_switch_rcv
-                * from freeing the skb.
-                */
-               priv->stampable_skb = skb_get(skb);
+               priv->stampable_skb = skb;
                spin_unlock(&priv->meta_lock);
 
                /* Tell DSA we got nothing */
@@ -436,6 +434,7 @@ static struct sk_buff
                        dev_err_ratelimited(ds->dev,
                                            "Unexpected meta frame\n");
                        spin_unlock(&priv->meta_lock);
+                       kfree_skb(skb);
                        return NULL;
                }
 
@@ -443,6 +442,7 @@ static struct sk_buff
                        dev_err_ratelimited(ds->dev,
                                            "Meta frame on wrong port\n");
                        spin_unlock(&priv->meta_lock);
+                       kfree_skb(skb);
                        return NULL;
                }
 
@@ -501,18 +501,21 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
        /* Normal data plane traffic and link-local frames are tagged with
         * a tag_8021q VLAN which we have to strip
         */
-       if (sja1105_skb_has_tag_8021q(skb))
+       if (sja1105_skb_has_tag_8021q(skb)) {
                dsa_8021q_rcv(skb, &source_port, &switch_id, &vbid, &vid);
-       else if (source_port == -1 && switch_id == -1)
+       } else if (source_port == -1 && switch_id == -1) {
                /* Packets with no source information have no chance of
                 * getting accepted, drop them straight away.
                 */
+               kfree_skb(skb);
                return NULL;
+       }
 
        skb->dev = dsa_tag_8021q_find_user(netdev, source_port, switch_id,
                                           vid, vbid);
        if (!skb->dev) {
                netdev_warn(netdev, "Couldn't decode source port\n");
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -539,12 +542,15 @@ static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header)
        if (!ds) {
                net_err_ratelimited("%s: cannot find switch id %d\n",
                                    conduit->name, switch_id);
+               kfree_skb(skb);
                return NULL;
        }
 
        tagger_data = sja1105_tagger_data(ds);
-       if (!tagger_data->meta_tstamp_handler)
+       if (!tagger_data->meta_tstamp_handler) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        for (i = 0; i <= n_ts; i++) {
                u8 ts_id, source_port, dir;
@@ -562,6 +568,7 @@ static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header)
        }
 
        /* Discard the meta frame, we've consumed the timestamps it contained */
+       kfree_skb(skb);
        return NULL;
 }
 
@@ -572,8 +579,10 @@ static struct sk_buff *sja1110_rcv_inband_control_extension(struct sk_buff *skb,
 {
        u16 rx_header;
 
-       if (unlikely(!pskb_may_pull(skb, SJA1110_HEADER_LEN)))
+       if (unlikely(!pskb_may_pull(skb, SJA1110_HEADER_LEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* skb->data points to skb_mac_header(skb) + ETH_HLEN, which is exactly
         * what we need because the caller has checked the EtherType (which is
@@ -609,8 +618,10 @@ static struct sk_buff *sja1110_rcv_inband_control_extension(struct sk_buff *skb,
                 * padding and trailer we need to account for the fact that
                 * skb->data points to skb_mac_header(skb) + ETH_HLEN.
                 */
-               if (pskb_trim_rcsum(skb, start_of_padding - ETH_HLEN))
+               if (pskb_trim_rcsum(skb, start_of_padding - ETH_HLEN)) {
+                       kfree_skb(skb);
                        return NULL;
+               }
        /* Trap-to-host frame, no timestamp trailer */
        } else {
                *source_port = SJA1110_RX_HEADER_SRC_PORT(rx_header);
@@ -653,6 +664,7 @@ static struct sk_buff *sja1110_rcv(struct sk_buff *skb,
 
        if (!skb->dev) {
                netdev_warn(netdev, "Couldn't decode source port\n");
+               kfree_skb(skb);
                return NULL;
        }
 
index 4dce24cfe6a7169dfed0a774a514a40d85168e9a..49c802c10ca63a3290ba51064ba2e3652f794cc7 100644 (file)
@@ -30,22 +30,30 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev)
        u8 *trailer;
        int source_port;
 
-       if (skb_linearize(skb))
+       if (skb_linearize(skb)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        trailer = skb_tail_pointer(skb) - 4;
        if (trailer[0] != 0x80 || (trailer[1] & 0xf8) != 0x00 ||
-           (trailer[2] & 0xef) != 0x00 || trailer[3] != 0x00)
+           (trailer[2] & 0xef) != 0x00 || trailer[3] != 0x00) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        source_port = trailer[1] & 7;
 
        skb->dev = dsa_conduit_find_user(dev, 0, source_port);
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
-       if (pskb_trim_rcsum(skb, skb->len - 4))
+       if (pskb_trim_rcsum(skb, skb->len - 4)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        return skb;
 }
index af121a9aff7fbdcd412a4e6ee84cbf53de5c0cf3..f4736a1a7a0f0f451dc55b0bc9ef21c7b9a9311a 100644 (file)
@@ -44,6 +44,7 @@ vsc73xx_rcv(struct sk_buff *skb, struct net_device *netdev)
        if (!skb->dev) {
                dev_warn_ratelimited(&netdev->dev,
                                     "Couldn't decode source port\n");
+               kfree_skb(skb);
                return NULL;
        }
 
index a05219f702c65a21739a7ef03c967615848163a6..bb268020ee865eba8232d2b8196b54e91f1bf3cf 100644 (file)
@@ -30,15 +30,21 @@ static struct sk_buff *xrs700x_rcv(struct sk_buff *skb, struct net_device *dev)
 
        source_port = ffs((int)trailer[0]) - 1;
 
-       if (source_port < 0)
+       if (source_port < 0) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        skb->dev = dsa_conduit_find_user(dev, 0, source_port);
-       if (!skb->dev)
+       if (!skb->dev) {
+               kfree_skb(skb);
                return NULL;
+       }
 
-       if (pskb_trim_rcsum(skb, skb->len - 1))
+       if (pskb_trim_rcsum(skb, skb->len - 1)) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        /* Frame is forwarded by hardware, don't forward in software. */
        dsa_default_offload_fwd_mark(skb);
index f3ced99b1c852eeff040b0422f0a82eef4283de9..294784ab6694b6567748516ec5d877cf5ca1f14e 100644 (file)
@@ -87,8 +87,10 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)
        __be16 *tag;
        u16 rx;
 
-       if (unlikely(!pskb_may_pull(skb, YT921X_TAG_LEN)))
+       if (unlikely(!pskb_may_pull(skb, YT921X_TAG_LEN))) {
+               kfree_skb(skb);
                return NULL;
+       }
 
        tag = dsa_etype_header_pos_rx(skb);
 
@@ -96,6 +98,7 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)
                dev_warn_ratelimited(&netdev->dev,
                                     "Unexpected EtherType 0x%04x\n",
                                     ntohs(tag[0]));
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -104,6 +107,7 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)
        if (unlikely((rx & YT921X_TAG_PORT_EN) == 0)) {
                dev_warn_ratelimited(&netdev->dev,
                                     "Unexpected rx tag 0x%04x\n", rx);
+               kfree_skb(skb);
                return NULL;
        }
 
@@ -112,6 +116,7 @@ yt921x_tag_rcv(struct sk_buff *skb, struct net_device *netdev)
        if (unlikely(!skb->dev)) {
                dev_warn_ratelimited(&netdev->dev,
                                     "Couldn't decode source port %u\n", port);
+               kfree_skb(skb);
                return NULL;
        }
 
index 8704c1a3a5b741a579b7697fa5c3bbd19ff376ae..072fa76972cc6501eacd4c44d13307e2a1822c00 100644 (file)
@@ -935,13 +935,12 @@ static netdev_tx_t dsa_user_xmit(struct sk_buff *skb, struct net_device *dev)
                eth_skb_pad(skb);
 
        /* Transmit function may have to reallocate the original SKB,
-        * in which case it must have freed it. Only free it here on error.
+        * in which case it must have freed it. Taggers will drop the
+        * passed skb on error.
         */
        nskb = p->xmit(skb, dev);
-       if (!nskb) {
-               kfree_skb(skb);
+       if (!nskb)
                return NETDEV_TX_OK;
-       }
 
        return dsa_enqueue_skb(nskb, dev);
 }