]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/ipv4/devinet.c
Merge tag 'sound-fix-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[karo-tx-linux.git] / net / ipv4 / devinet.c
index e9449376b58e4293b7735362912e1ea1191a8815..214882e7d6deea0114531124689027dfdde83df6 100644 (file)
@@ -180,11 +180,12 @@ static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
 static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
                         int destroy);
 #ifdef CONFIG_SYSCTL
-static void devinet_sysctl_register(struct in_device *idev);
+static int devinet_sysctl_register(struct in_device *idev);
 static void devinet_sysctl_unregister(struct in_device *idev);
 #else
-static void devinet_sysctl_register(struct in_device *idev)
+static int devinet_sysctl_register(struct in_device *idev)
 {
+       return 0;
 }
 static void devinet_sysctl_unregister(struct in_device *idev)
 {
@@ -232,6 +233,7 @@ EXPORT_SYMBOL(in_dev_finish_destroy);
 static struct in_device *inetdev_init(struct net_device *dev)
 {
        struct in_device *in_dev;
+       int err = -ENOMEM;
 
        ASSERT_RTNL();
 
@@ -252,7 +254,13 @@ static struct in_device *inetdev_init(struct net_device *dev)
        /* Account for reference dev->ip_ptr (below) */
        in_dev_hold(in_dev);
 
-       devinet_sysctl_register(in_dev);
+       err = devinet_sysctl_register(in_dev);
+       if (err) {
+               in_dev->dead = 1;
+               in_dev_put(in_dev);
+               in_dev = NULL;
+               goto out;
+       }
        ip_mc_init_dev(in_dev);
        if (dev->flags & IFF_UP)
                ip_mc_up(in_dev);
@@ -260,7 +268,7 @@ static struct in_device *inetdev_init(struct net_device *dev)
        /* we can receive as soon as ip_ptr is set -- do this last */
        rcu_assign_pointer(dev->ip_ptr, in_dev);
 out:
-       return in_dev;
+       return in_dev ?: ERR_PTR(err);
 out_kfree:
        kfree(in_dev);
        in_dev = NULL;
@@ -1347,8 +1355,8 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
        if (!in_dev) {
                if (event == NETDEV_REGISTER) {
                        in_dev = inetdev_init(dev);
-                       if (!in_dev)
-                               return notifier_from_errno(-ENOMEM);
+                       if (IS_ERR(in_dev))
+                               return notifier_from_errno(PTR_ERR(in_dev));
                        if (dev->flags & IFF_LOOPBACK) {
                                IN_DEV_CONF_SET(in_dev, NOXFRM, 1);
                                IN_DEV_CONF_SET(in_dev, NOPOLICY, 1);
@@ -2182,11 +2190,21 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf)
        kfree(t);
 }
 
-static void devinet_sysctl_register(struct in_device *idev)
+static int devinet_sysctl_register(struct in_device *idev)
 {
-       neigh_sysctl_register(idev->dev, idev->arp_parms, NULL);
-       __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name,
+       int err;
+
+       if (!sysctl_dev_name_is_allowed(idev->dev->name))
+               return -EINVAL;
+
+       err = neigh_sysctl_register(idev->dev, idev->arp_parms, NULL);
+       if (err)
+               return err;
+       err = __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name,
                                        &idev->cnf);
+       if (err)
+               neigh_sysctl_unregister(idev->arp_parms);
+       return err;
 }
 
 static void devinet_sysctl_unregister(struct in_device *idev)