net/core: Fix potential memory leak in dev_set_alias()
[pandora-kernel.git] / net / core / dev.c
index cd5050e..75da76d 100644 (file)
@@ -1059,6 +1059,8 @@ rollback:
  */
 int dev_set_alias(struct net_device *dev, const char *alias, size_t len)
 {
+       char *new_ifalias;
+
        ASSERT_RTNL();
 
        if (len >= IFALIASZ)
@@ -1072,9 +1074,10 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len)
                return 0;
        }
 
-       dev->ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL);
-       if (!dev->ifalias)
+       new_ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL);
+       if (!new_ifalias)
                return -ENOMEM;
+       dev->ifalias = new_ifalias;
 
        strlcpy(dev->ifalias, alias, len+1);
        return len;
@@ -1177,6 +1180,7 @@ static int __dev_open(struct net_device *dev)
                net_dmaengine_get();
                dev_set_rx_mode(dev);
                dev_activate(dev);
+               add_device_randomness(dev->dev_addr, dev->addr_len);
        }
 
        return ret;
@@ -1421,14 +1425,34 @@ EXPORT_SYMBOL(register_netdevice_notifier);
  *     register_netdevice_notifier(). The notifier is unlinked into the
  *     kernel structures and may then be reused. A negative errno code
  *     is returned on a failure.
+ *
+ *     After unregistering unregister and down device events are synthesized
+ *     for all devices on the device list to the removed notifier to remove
+ *     the need for special case cleanup code.
  */
 
 int unregister_netdevice_notifier(struct notifier_block *nb)
 {
+       struct net_device *dev;
+       struct net *net;
        int err;
 
        rtnl_lock();
        err = raw_notifier_chain_unregister(&netdev_chain, nb);
+       if (err)
+               goto unlock;
+
+       for_each_net(net) {
+               for_each_netdev(net, dev) {
+                       if (dev->flags & IFF_UP) {
+                               nb->notifier_call(nb, NETDEV_GOING_DOWN, dev);
+                               nb->notifier_call(nb, NETDEV_DOWN, dev);
+                       }
+                       nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
+                       nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev);
+               }
+       }
+unlock:
        rtnl_unlock();
        return err;
 }
@@ -1587,10 +1611,14 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
                kfree_skb(skb);
                return NET_RX_DROP;
        }
-       skb_set_dev(skb, dev);
+       skb->dev = dev;
+       skb_dst_drop(skb);
        skb->tstamp.tv64 = 0;
        skb->pkt_type = PACKET_HOST;
        skb->protocol = eth_type_trans(skb, dev);
+       skb->mark = 0;
+       secpath_reset(skb);
+       nf_reset(skb);
        return netif_rx(skb);
 }
 EXPORT_SYMBOL_GPL(dev_forward_skb);
@@ -1845,36 +1873,6 @@ void netif_device_attach(struct net_device *dev)
 }
 EXPORT_SYMBOL(netif_device_attach);
 
-/**
- * skb_dev_set -- assign a new device to a buffer
- * @skb: buffer for the new device
- * @dev: network device
- *
- * If an skb is owned by a device already, we have to reset
- * all data private to the namespace a device belongs to
- * before assigning it a new device.
- */
-#ifdef CONFIG_NET_NS
-void skb_set_dev(struct sk_buff *skb, struct net_device *dev)
-{
-       skb_dst_drop(skb);
-       if (skb->dev && !net_eq(dev_net(skb->dev), dev_net(dev))) {
-               secpath_reset(skb);
-               nf_reset(skb);
-               skb_init_secmark(skb);
-               skb->mark = 0;
-               skb->priority = 0;
-               skb->nf_trace = 0;
-               skb->ipvs_property = 0;
-#ifdef CONFIG_NET_SCHED
-               skb->tc_index = 0;
-#endif
-       }
-       skb->dev = dev;
-}
-EXPORT_SYMBOL(skb_set_dev);
-#endif /* CONFIG_NET_NS */
-
 /*
  * Invalidate hardware checksum when packet is to be mangled, and
  * complete checksum manually on outgoing path.
@@ -2085,25 +2083,6 @@ static int dev_gso_segment(struct sk_buff *skb, int features)
        return 0;
 }
 
-/*
- * Try to orphan skb early, right before transmission by the device.
- * We cannot orphan skb if tx timestamp is requested or the sk-reference
- * is needed on driver level for other reasons, e.g. see net/can/raw.c
- */
-static inline void skb_orphan_try(struct sk_buff *skb)
-{
-       struct sock *sk = skb->sk;
-
-       if (sk && !skb_shinfo(skb)->tx_flags) {
-               /* skb_tx_hash() wont be able to get sk.
-                * We copy sk_hash into skb->rxhash
-                */
-               if (!skb->rxhash)
-                       skb->rxhash = sk->sk_hash;
-               skb_orphan(skb);
-       }
-}
-
 static bool can_checksum_protocol(unsigned long features, __be16 protocol)
 {
        return ((features & NETIF_F_GEN_CSUM) ||
@@ -2132,6 +2111,9 @@ u32 netif_skb_features(struct sk_buff *skb)
        __be16 protocol = skb->protocol;
        u32 features = skb->dev->features;
 
+       if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
+               features &= ~NETIF_F_GSO_MASK;
+
        if (protocol == htons(ETH_P_8021Q)) {
                struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
                protocol = veh->h_vlan_encapsulated_proto;
@@ -2188,8 +2170,6 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                if (!list_empty(&ptype_all))
                        dev_queue_xmit_nit(skb, dev);
 
-               skb_orphan_try(skb);
-
                features = netif_skb_features(skb);
 
                if (vlan_tx_tag_present(skb) &&
@@ -2299,7 +2279,7 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb,
        if (skb->sk && skb->sk->sk_hash)
                hash = skb->sk->sk_hash;
        else
-               hash = (__force u16) skb->protocol ^ skb->rxhash;
+               hash = (__force u16) skb->protocol;
        hash = jhash_1word(hash, hashrnd);
 
        return (u16) (((u64) hash * qcount) >> 32) + qoffset;
@@ -4868,6 +4848,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
        err = ops->ndo_set_mac_address(dev, sa);
        if (!err)
                call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+       add_device_randomness(dev->dev_addr, dev->addr_len);
        return err;
 }
 EXPORT_SYMBOL(dev_set_mac_address);
@@ -5648,6 +5629,7 @@ int register_netdevice(struct net_device *dev)
        dev_init_scheduler(dev);
        dev_hold(dev);
        list_netdevice(dev);
+       add_device_randomness(dev->dev_addr, dev->addr_len);
 
        /* Notify protocols, that a new device appeared. */
        ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
@@ -6014,6 +5996,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
        dev_net_set(dev, &init_net);
 
        dev->gso_max_size = GSO_MAX_SIZE;
+       dev->gso_max_segs = GSO_MAX_SEGS;
 
        INIT_LIST_HEAD(&dev->napi_list);
        INIT_LIST_HEAD(&dev->unreg_list);