diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-09-11 14:35:22 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-09-11 15:54:23 -0400 |
commit | ffcfb8db540ff879c2a85bf7e404954281443414 (patch) | |
tree | 9b0014cd056c4283e6df924a5fe28ab54542c1d3 /net | |
parent | 8ba69ba6a324b13e1190fc31e41954d190fd4f1d (diff) |
Subject: [PATCH] appletalk: Fix skb leak when ipddp interface is not loaded
And also do a better job of returning proper NET_{RX,XMIT}_ values.
Based on a patch and suggestions by Mark Smith.
This fixes CVE-2009-2903
Reported-by: Mark Smith <lk-netdev@lk-netdev.nosense.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/appletalk/aarp.c | 16 | ||||
-rw-r--r-- | net/appletalk/ddp.c | 47 |
2 files changed, 35 insertions, 28 deletions
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index 89f99d3beb60..9d4adfd22757 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c | |||
@@ -599,7 +599,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb, | |||
599 | 599 | ||
600 | /* Non ELAP we cannot do. */ | 600 | /* Non ELAP we cannot do. */ |
601 | if (dev->type != ARPHRD_ETHER) | 601 | if (dev->type != ARPHRD_ETHER) |
602 | return -1; | 602 | goto free_it; |
603 | 603 | ||
604 | skb->dev = dev; | 604 | skb->dev = dev; |
605 | skb->protocol = htons(ETH_P_ATALK); | 605 | skb->protocol = htons(ETH_P_ATALK); |
@@ -634,7 +634,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb, | |||
634 | if (!a) { | 634 | if (!a) { |
635 | /* Whoops slipped... good job it's an unreliable protocol 8) */ | 635 | /* Whoops slipped... good job it's an unreliable protocol 8) */ |
636 | write_unlock_bh(&aarp_lock); | 636 | write_unlock_bh(&aarp_lock); |
637 | return -1; | 637 | goto free_it; |
638 | } | 638 | } |
639 | 639 | ||
640 | /* Set up the queue */ | 640 | /* Set up the queue */ |
@@ -663,15 +663,21 @@ out_unlock: | |||
663 | write_unlock_bh(&aarp_lock); | 663 | write_unlock_bh(&aarp_lock); |
664 | 664 | ||
665 | /* Tell the ddp layer we have taken over for this frame. */ | 665 | /* Tell the ddp layer we have taken over for this frame. */ |
666 | return 0; | 666 | goto sent; |
667 | 667 | ||
668 | sendit: | 668 | sendit: |
669 | if (skb->sk) | 669 | if (skb->sk) |
670 | skb->priority = skb->sk->sk_priority; | 670 | skb->priority = skb->sk->sk_priority; |
671 | dev_queue_xmit(skb); | 671 | if (dev_queue_xmit(skb)) |
672 | goto drop; | ||
672 | sent: | 673 | sent: |
673 | return 1; | 674 | return NET_XMIT_SUCCESS; |
675 | free_it: | ||
676 | kfree_skb(skb); | ||
677 | drop: | ||
678 | return NET_XMIT_DROP; | ||
674 | } | 679 | } |
680 | EXPORT_SYMBOL(aarp_send_ddp); | ||
675 | 681 | ||
676 | /* | 682 | /* |
677 | * An entry in the aarp unresolved queue has become resolved. Send | 683 | * An entry in the aarp unresolved queue has become resolved. Send |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 0d42d5da50ad..4a6ff2ba4d07 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -1270,8 +1270,10 @@ static int handle_ip_over_ddp(struct sk_buff *skb) | |||
1270 | struct net_device_stats *stats; | 1270 | struct net_device_stats *stats; |
1271 | 1271 | ||
1272 | /* This needs to be able to handle ipddp"N" devices */ | 1272 | /* This needs to be able to handle ipddp"N" devices */ |
1273 | if (!dev) | 1273 | if (!dev) { |
1274 | return -ENODEV; | 1274 | kfree_skb(skb); |
1275 | return NET_RX_DROP; | ||
1276 | } | ||
1275 | 1277 | ||
1276 | skb->protocol = htons(ETH_P_IP); | 1278 | skb->protocol = htons(ETH_P_IP); |
1277 | skb_pull(skb, 13); | 1279 | skb_pull(skb, 13); |
@@ -1281,8 +1283,7 @@ static int handle_ip_over_ddp(struct sk_buff *skb) | |||
1281 | stats = netdev_priv(dev); | 1283 | stats = netdev_priv(dev); |
1282 | stats->rx_packets++; | 1284 | stats->rx_packets++; |
1283 | stats->rx_bytes += skb->len + 13; | 1285 | stats->rx_bytes += skb->len + 13; |
1284 | netif_rx(skb); /* Send the SKB up to a higher place. */ | 1286 | return netif_rx(skb); /* Send the SKB up to a higher place. */ |
1285 | return 0; | ||
1286 | } | 1287 | } |
1287 | #else | 1288 | #else |
1288 | /* make it easy for gcc to optimize this test out, i.e. kill the code */ | 1289 | /* make it easy for gcc to optimize this test out, i.e. kill the code */ |
@@ -1290,9 +1291,8 @@ static int handle_ip_over_ddp(struct sk_buff *skb) | |||
1290 | #define handle_ip_over_ddp(skb) 0 | 1291 | #define handle_ip_over_ddp(skb) 0 |
1291 | #endif | 1292 | #endif |
1292 | 1293 | ||
1293 | static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev, | 1294 | static int atalk_route_packet(struct sk_buff *skb, struct net_device *dev, |
1294 | struct ddpehdr *ddp, __u16 len_hops, | 1295 | struct ddpehdr *ddp, __u16 len_hops, int origlen) |
1295 | int origlen) | ||
1296 | { | 1296 | { |
1297 | struct atalk_route *rt; | 1297 | struct atalk_route *rt; |
1298 | struct atalk_addr ta; | 1298 | struct atalk_addr ta; |
@@ -1359,8 +1359,6 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev, | |||
1359 | /* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */ | 1359 | /* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */ |
1360 | struct sk_buff *nskb = skb_realloc_headroom(skb, 32); | 1360 | struct sk_buff *nskb = skb_realloc_headroom(skb, 32); |
1361 | kfree_skb(skb); | 1361 | kfree_skb(skb); |
1362 | if (!nskb) | ||
1363 | goto out; | ||
1364 | skb = nskb; | 1362 | skb = nskb; |
1365 | } else | 1363 | } else |
1366 | skb = skb_unshare(skb, GFP_ATOMIC); | 1364 | skb = skb_unshare(skb, GFP_ATOMIC); |
@@ -1369,12 +1367,16 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev, | |||
1369 | * If the buffer didn't vanish into the lack of space bitbucket we can | 1367 | * If the buffer didn't vanish into the lack of space bitbucket we can |
1370 | * send it. | 1368 | * send it. |
1371 | */ | 1369 | */ |
1372 | if (skb && aarp_send_ddp(rt->dev, skb, &ta, NULL) == -1) | 1370 | if (skb == NULL) |
1373 | goto free_it; | 1371 | goto drop; |
1374 | out: | 1372 | |
1375 | return; | 1373 | if (aarp_send_ddp(rt->dev, skb, &ta, NULL) == NET_XMIT_DROP) |
1374 | return NET_RX_DROP; | ||
1375 | return NET_XMIT_SUCCESS; | ||
1376 | free_it: | 1376 | free_it: |
1377 | kfree_skb(skb); | 1377 | kfree_skb(skb); |
1378 | drop: | ||
1379 | return NET_RX_DROP; | ||
1378 | } | 1380 | } |
1379 | 1381 | ||
1380 | /** | 1382 | /** |
@@ -1448,8 +1450,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, | |||
1448 | /* Not ours, so we route the packet via the correct | 1450 | /* Not ours, so we route the packet via the correct |
1449 | * AppleTalk iface | 1451 | * AppleTalk iface |
1450 | */ | 1452 | */ |
1451 | atalk_route_packet(skb, dev, ddp, len_hops, origlen); | 1453 | return atalk_route_packet(skb, dev, ddp, len_hops, origlen); |
1452 | return NET_RX_SUCCESS; | ||
1453 | } | 1454 | } |
1454 | 1455 | ||
1455 | /* if IP over DDP is not selected this code will be optimized out */ | 1456 | /* if IP over DDP is not selected this code will be optimized out */ |
@@ -1655,10 +1656,10 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1655 | if (skb2) { | 1656 | if (skb2) { |
1656 | loopback = 1; | 1657 | loopback = 1; |
1657 | SOCK_DEBUG(sk, "SK %p: send out(copy).\n", sk); | 1658 | SOCK_DEBUG(sk, "SK %p: send out(copy).\n", sk); |
1658 | if (aarp_send_ddp(dev, skb2, | 1659 | /* |
1659 | &usat->sat_addr, NULL) == -1) | 1660 | * If it fails it is queued/sent above in the aarp queue |
1660 | kfree_skb(skb2); | 1661 | */ |
1661 | /* else queued/sent above in the aarp queue */ | 1662 | aarp_send_ddp(dev, skb2, &usat->sat_addr, NULL); |
1662 | } | 1663 | } |
1663 | } | 1664 | } |
1664 | 1665 | ||
@@ -1688,9 +1689,10 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1688 | usat = &gsat; | 1689 | usat = &gsat; |
1689 | } | 1690 | } |
1690 | 1691 | ||
1691 | if (aarp_send_ddp(dev, skb, &usat->sat_addr, NULL) == -1) | 1692 | /* |
1692 | kfree_skb(skb); | 1693 | * If it fails it is queued/sent above in the aarp queue |
1693 | /* else queued/sent above in the aarp queue */ | 1694 | */ |
1695 | aarp_send_ddp(dev, skb, &usat->sat_addr, NULL); | ||
1694 | } | 1696 | } |
1695 | SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len); | 1697 | SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len); |
1696 | 1698 | ||
@@ -1868,7 +1870,6 @@ static struct packet_type ppptalk_packet_type __read_mostly = { | |||
1868 | static unsigned char ddp_snap_id[] = { 0x08, 0x00, 0x07, 0x80, 0x9B }; | 1870 | static unsigned char ddp_snap_id[] = { 0x08, 0x00, 0x07, 0x80, 0x9B }; |
1869 | 1871 | ||
1870 | /* Export symbols for use by drivers when AppleTalk is a module */ | 1872 | /* Export symbols for use by drivers when AppleTalk is a module */ |
1871 | EXPORT_SYMBOL(aarp_send_ddp); | ||
1872 | EXPORT_SYMBOL(atrtr_get_dev); | 1873 | EXPORT_SYMBOL(atrtr_get_dev); |
1873 | EXPORT_SYMBOL(atalk_find_dev_addr); | 1874 | EXPORT_SYMBOL(atalk_find_dev_addr); |
1874 | 1875 | ||