]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
appletalk: Fix skb leak when ipddp interface is not loaded (CVE-2009-2903)
authorArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 26 Oct 2009 18:36:45 +0000 (14:36 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 10 Nov 2009 00:52:22 +0000 (16:52 -0800)
commit ffcfb8db540ff879c2a85bf7e404954281443414 upstream

appletalk: Fix skb leak when ipddp interface is not loaded

[ backport to 2.6.27 : Chuck Ebbert <cebbert@redhat.com ]

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>
Cc: Chuck Ebbert <cebbert@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/net/appletalk/ipddp.c
net/appletalk/aarp.c
net/appletalk/ddp.c

index 1071144edd66fbdf0f594ec0104c065fdee06e82..6d0107cb7a2efffc55266ff78f1fcf9a6afcaa92 100644 (file)
@@ -173,8 +173,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
        ((struct net_device_stats *) dev->priv)->tx_packets++;
         ((struct net_device_stats *) dev->priv)->tx_bytes+=skb->len;
 
-        if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0)
-                dev_kfree_skb(skb);
+       aarp_send_ddp(rt->dev, skb, &rt->at, NULL);
 
         return 0;
 }
index b25c1e909d14fdabadf150693dd80252345f4f26..dd076ead83bf54ba1fecf946e3ba3f2cd7ca6a68 100644 (file)
@@ -598,7 +598,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb,
 
        /* Non ELAP we cannot do. */
        if (dev->type != ARPHRD_ETHER)
-               return -1;
+               goto free_it;
 
        skb->dev = dev;
        skb->protocol = htons(ETH_P_ATALK);
@@ -633,7 +633,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb,
        if (!a) {
                /* Whoops slipped... good job it's an unreliable protocol 8) */
                write_unlock_bh(&aarp_lock);
-               return -1;
+               goto free_it;
        }
 
        /* Set up the queue */
@@ -662,15 +662,21 @@ out_unlock:
        write_unlock_bh(&aarp_lock);
 
        /* Tell the ddp layer we have taken over for this frame. */
-       return 0;
+       goto sent;
 
 sendit:
        if (skb->sk)
                skb->priority = skb->sk->sk_priority;
-       dev_queue_xmit(skb);
+       if (dev_queue_xmit(skb))
+               goto drop;
 sent:
-       return 1;
+       return NET_XMIT_SUCCESS;
+free_it:
+       kfree_skb(skb);
+drop:
+       return NET_XMIT_DROP;
 }
+EXPORT_SYMBOL(aarp_send_ddp);
 
 /*
  *     An entry in the aarp unresolved queue has become resolved. Send
index 8067dc75904be3e361576f49905c75965d89c18c..e99d33766ca99a7b7f0918fd2233f0296424505c 100644 (file)
@@ -1277,8 +1277,10 @@ static int handle_ip_over_ddp(struct sk_buff *skb)
        struct net_device_stats *stats;
 
        /* This needs to be able to handle ipddp"N" devices */
-       if (!dev)
-               return -ENODEV;
+       if (!dev) {
+               kfree_skb(skb);
+               return NET_RX_DROP;
+       }
 
        skb->protocol = htons(ETH_P_IP);
        skb_pull(skb, 13);
@@ -1288,8 +1290,7 @@ static int handle_ip_over_ddp(struct sk_buff *skb)
        stats = dev->priv;
        stats->rx_packets++;
        stats->rx_bytes += skb->len + 13;
-       netif_rx(skb);  /* Send the SKB up to a higher place. */
-       return 0;
+       return netif_rx(skb);  /* Send the SKB up to a higher place. */
 }
 #else
 /* make it easy for gcc to optimize this test out, i.e. kill the code */
@@ -1297,9 +1298,8 @@ static int handle_ip_over_ddp(struct sk_buff *skb)
 #define handle_ip_over_ddp(skb) 0
 #endif
 
-static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
-                              struct ddpehdr *ddp, __u16 len_hops,
-                              int origlen)
+static int atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
+                             struct ddpehdr *ddp, __u16 len_hops, int origlen)
 {
        struct atalk_route *rt;
        struct atalk_addr ta;
@@ -1366,8 +1366,6 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
                /* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */
                struct sk_buff *nskb = skb_realloc_headroom(skb, 32);
                kfree_skb(skb);
-               if (!nskb)
-                       goto out;
                skb = nskb;
        } else
                skb = skb_unshare(skb, GFP_ATOMIC);
@@ -1376,12 +1374,16 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
         * If the buffer didn't vanish into the lack of space bitbucket we can
         * send it.
         */
-       if (skb && aarp_send_ddp(rt->dev, skb, &ta, NULL) == -1)
-               goto free_it;
-out:
-       return;
+       if (skb == NULL)
+               goto drop;
+
+       if (aarp_send_ddp(rt->dev, skb, &ta, NULL) == NET_XMIT_DROP)
+               return NET_RX_DROP;
+       return NET_XMIT_SUCCESS;
 free_it:
        kfree_skb(skb);
+drop:
+       return NET_RX_DROP;
 }
 
 /**
@@ -1455,8 +1457,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
                /* Not ours, so we route the packet via the correct
                 * AppleTalk iface
                 */
-               atalk_route_packet(skb, dev, ddp, len_hops, origlen);
-               goto out;
+               return atalk_route_packet(skb, dev, ddp, len_hops, origlen);
        }
 
        /* if IP over DDP is not selected this code will be optimized out */
@@ -1663,10 +1664,10 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
                if (skb2) {
                        loopback = 1;
                        SOCK_DEBUG(sk, "SK %p: send out(copy).\n", sk);
-                       if (aarp_send_ddp(dev, skb2,
-                                         &usat->sat_addr, NULL) == -1)
-                               kfree_skb(skb2);
-                               /* else queued/sent above in the aarp queue */
+                       /*
+                        * If it fails it is queued/sent above in the aarp queue
+                        */
+                       aarp_send_ddp(dev, skb2, &usat->sat_addr, NULL);
                }
        }
 
@@ -1696,9 +1697,10 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
                    usat = &gsat;
                }
 
-               if (aarp_send_ddp(dev, skb, &usat->sat_addr, NULL) == -1)
-                       kfree_skb(skb);
-               /* else queued/sent above in the aarp queue */
+               /*
+                * If it fails it is queued/sent above in the aarp queue
+                */
+               aarp_send_ddp(dev, skb, &usat->sat_addr, NULL);
        }
        SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len);
 
@@ -1877,7 +1879,6 @@ static struct packet_type ppptalk_packet_type = {
 static unsigned char ddp_snap_id[] = { 0x08, 0x00, 0x07, 0x80, 0x9B };
 
 /* Export symbols for use by drivers when AppleTalk is a module */
-EXPORT_SYMBOL(aarp_send_ddp);
 EXPORT_SYMBOL(atrtr_get_dev);
 EXPORT_SYMBOL(atalk_find_dev_addr);