Commit e71cb9e0 authored by Vivien Didelot's avatar Vivien Didelot Committed by David S. Miller

net: dsa: ksz: fix skb freeing

The DSA layer frees the original skb when an xmit function returns NULL,
meaning an error occurred. But if the tagging code copied the original
skb, it is responsible of freeing the copy if an error occurs.

The ksz tagging code currently has two issues: if skb_put_padto fails,
the skb copy is not freed, and the original skb will be freed twice.

To fix that, move skb_put_padto inside both branches of the skb_tailroom
condition, before freeing the original skb, and free the copy on error.
Signed-off-by: default avatarVivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: default avatarWoojung Huh <woojung.huh@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 26273939
...@@ -42,6 +42,9 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -42,6 +42,9 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)
padlen = (skb->len >= ETH_ZLEN) ? 0 : ETH_ZLEN - skb->len; padlen = (skb->len >= ETH_ZLEN) ? 0 : ETH_ZLEN - skb->len;
if (skb_tailroom(skb) >= padlen + KSZ_INGRESS_TAG_LEN) { if (skb_tailroom(skb) >= padlen + KSZ_INGRESS_TAG_LEN) {
if (skb_put_padto(skb, skb->len + padlen))
return NULL;
nskb = skb; nskb = skb;
} else { } else {
nskb = alloc_skb(NET_IP_ALIGN + skb->len + nskb = alloc_skb(NET_IP_ALIGN + skb->len +
...@@ -56,13 +59,15 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -56,13 +59,15 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)
skb_set_transport_header(nskb, skb_set_transport_header(nskb,
skb_transport_header(skb) - skb->head); skb_transport_header(skb) - skb->head);
skb_copy_and_csum_dev(skb, skb_put(nskb, skb->len)); skb_copy_and_csum_dev(skb, skb_put(nskb, skb->len));
if (skb_put_padto(nskb, nskb->len + padlen)) {
kfree_skb(nskb);
return NULL;
}
kfree_skb(skb); kfree_skb(skb);
} }
/* skb is freed when it fails */
if (skb_put_padto(nskb, nskb->len + padlen))
return NULL;
tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN); tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN);
tag[0] = 0; tag[0] = 0;
tag[1] = 1 << p->dp->index; /* destination port */ tag[1] = 1 << p->dp->index; /* destination port */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment