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/appletalk/ddp.c | |
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/appletalk/ddp.c')
-rw-r--r-- | net/appletalk/ddp.c | 47 |
1 files changed, 24 insertions, 23 deletions
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 | ||