ieee802154: 6lowpan: fix memory leak
Looking at current situation of memory management in 6lowpan receive function I detected some invalid handling. After calling lowpan_invoke_rx_handlers we will do a kfree_skb and then NET_RX_DROP on error handling. We don't do this before, also on skb_share_check/skb_unshare which might manipulate the reference counters. After running some 'grep -r "dev_add_pack" net/' to look how others packet-layer receive callbacks works I detected that every subsystem do a kfree_skb, then NET_RX_DROP without calling skb functions which might manipulate the skb reference counters. This is the reason why we should do the same here like all others subsystems. I didn't find any documentation how the packet-layer receive callbacks handle NET_RX_DROP return values either. This patch will add a kfree_skb, then NET_RX_DROP handling for the "trivial checks", in case of skb_share_check/skb_unshare the kfree_skb call will be done inside these functions. Signed-off-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
88d07feb09
commit
aeedebff69
1 changed files with 9 additions and 4 deletions
|
@ -284,16 +284,16 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
|
||||||
if (wdev->type != ARPHRD_IEEE802154 ||
|
if (wdev->type != ARPHRD_IEEE802154 ||
|
||||||
skb->pkt_type == PACKET_OTHERHOST ||
|
skb->pkt_type == PACKET_OTHERHOST ||
|
||||||
!lowpan_rx_h_check(skb))
|
!lowpan_rx_h_check(skb))
|
||||||
return NET_RX_DROP;
|
goto drop;
|
||||||
|
|
||||||
ldev = wdev->ieee802154_ptr->lowpan_dev;
|
ldev = wdev->ieee802154_ptr->lowpan_dev;
|
||||||
if (!ldev || !netif_running(ldev))
|
if (!ldev || !netif_running(ldev))
|
||||||
return NET_RX_DROP;
|
goto drop;
|
||||||
|
|
||||||
/* Replacing skb->dev and followed rx handlers will manipulate skb. */
|
/* Replacing skb->dev and followed rx handlers will manipulate skb. */
|
||||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return NET_RX_DROP;
|
goto out;
|
||||||
skb->dev = ldev;
|
skb->dev = ldev;
|
||||||
|
|
||||||
/* When receive frag1 it's likely that we manipulate the buffer.
|
/* When receive frag1 it's likely that we manipulate the buffer.
|
||||||
|
@ -304,10 +304,15 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
|
||||||
lowpan_is_iphc(*skb_network_header(skb))) {
|
lowpan_is_iphc(*skb_network_header(skb))) {
|
||||||
skb = skb_unshare(skb, GFP_ATOMIC);
|
skb = skb_unshare(skb, GFP_ATOMIC);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return NET_RX_DROP;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lowpan_invoke_rx_handlers(skb);
|
return lowpan_invoke_rx_handlers(skb);
|
||||||
|
|
||||||
|
drop:
|
||||||
|
kfree_skb(skb);
|
||||||
|
out:
|
||||||
|
return NET_RX_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct packet_type lowpan_packet_type = {
|
static struct packet_type lowpan_packet_type = {
|
||||||
|
|
Loading…
Reference in a new issue