aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/6lowpan.c
diff options
context:
space:
mode:
authorMartin Townsend <mtownsend1973@gmail.com>2014-11-06 14:15:13 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-11-06 16:09:48 -0500
commit56b2c3eea398c772dd895dc62c18cbdd1ba127b1 (patch)
treea4d6ab3f6bbf38f4c5b3cb66cc6f77d142397e32 /net/bluetooth/6lowpan.c
parent9645c76c7c233da82ff7aced0177c8a131a51e70 (diff)
6lowpan: move skb_free from error paths in decompression
Currently we ensure that the skb is freed on every error path in IPHC decompression which makes it easy to introduce skb leaks. By centralising the skb_free into the receive function it makes future decompression routines easier to maintain. It does come at the expense of ensuring that the skb passed into the decompression routine must not be copied. Signed-off-by: Martin Townsend <mtownsend1973@gmail.com> Acked-by: Jukka Rissanen <jukka.rissanen@linux.intel.com> Acked-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/6lowpan.c')
-rw-r--r--net/bluetooth/6lowpan.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index eef298d17452..dc23c55f1ab6 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -294,20 +294,20 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev,
294 peer = __peer_lookup_chan(dev, chan); 294 peer = __peer_lookup_chan(dev, chan);
295 rcu_read_unlock(); 295 rcu_read_unlock();
296 if (!peer) 296 if (!peer)
297 goto drop; 297 return -EINVAL;
298 298
299 saddr = peer->eui64_addr; 299 saddr = peer->eui64_addr;
300 daddr = dev->netdev->dev_addr; 300 daddr = dev->netdev->dev_addr;
301 301
302 /* at least two bytes will be used for the encoding */ 302 /* at least two bytes will be used for the encoding */
303 if (skb->len < 2) 303 if (skb->len < 2)
304 goto drop; 304 return -EINVAL;
305 305
306 if (lowpan_fetch_skb_u8(skb, &iphc0)) 306 if (lowpan_fetch_skb_u8(skb, &iphc0))
307 goto drop; 307 return -EINVAL;
308 308
309 if (lowpan_fetch_skb_u8(skb, &iphc1)) 309 if (lowpan_fetch_skb_u8(skb, &iphc1))
310 goto drop; 310 return -EINVAL;
311 311
312 return lowpan_header_decompress(skb, netdev, 312 return lowpan_header_decompress(skb, netdev,
313 saddr, IEEE802154_ADDR_LONG, 313 saddr, IEEE802154_ADDR_LONG,
@@ -315,9 +315,6 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev,
315 IEEE802154_ADDR_LONG, EUI64_ADDR_LEN, 315 IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
316 iphc0, iphc1); 316 iphc0, iphc1);
317 317
318drop:
319 kfree_skb(skb);
320 return -EINVAL;
321} 318}
322 319
323static int recv_pkt(struct sk_buff *skb, struct net_device *dev, 320static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
@@ -370,8 +367,10 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
370 goto drop; 367 goto drop;
371 368
372 ret = iphc_decompress(local_skb, dev, chan); 369 ret = iphc_decompress(local_skb, dev, chan);
373 if (ret < 0) 370 if (ret < 0) {
371 kfree_skb(local_skb);
374 goto drop; 372 goto drop;
373 }
375 374
376 local_skb->protocol = htons(ETH_P_IPV6); 375 local_skb->protocol = htons(ETH_P_IPV6);
377 local_skb->pkt_type = PACKET_HOST; 376 local_skb->pkt_type = PACKET_HOST;