Merge to Fedora kernel-2.6.18-1.2257_FC5 patched with stable patch-2.6.18.5-vs2.0...
[linux-2.6.git] / net / bridge / br_ioctl.c
index 17c7ee3..4c61a7e 100644 (file)
@@ -13,6 +13,7 @@
  *     2 of the License, or (at your option) any later version.
  */
 
+#include <linux/capability.h>
 #include <linux/kernel.h>
 #include <linux/if_bridge.h>
 #include <linux/netdevice.h>
@@ -57,12 +58,13 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf,
 {
        int num;
        void *buf;
-       size_t size = maxnum * sizeof(struct __fdb_entry);
+       size_t size;
 
-       if (size > PAGE_SIZE) {
-               size = PAGE_SIZE;
+       /* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */
+       if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry))
                maxnum = PAGE_SIZE/sizeof(struct __fdb_entry);
-       }
+
+       size = maxnum * sizeof(struct __fdb_entry);
 
        buf = kmalloc(size, GFP_USER);
        if (!buf)
@@ -143,7 +145,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                b.gc_timer_value = br_timer_value(&br->gc_timer);
                rcu_read_unlock();
 
-               if (copy_to_user((void *)args[1], &b, sizeof(b)))
+               if (copy_to_user((void __user *)args[1], &b, sizeof(b)))
                        return -EFAULT;
 
                return 0;
@@ -161,14 +163,12 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                if (num > BR_MAX_PORTS)
                        num = BR_MAX_PORTS;
 
-               indices = kmalloc(num*sizeof(int), GFP_KERNEL);
+               indices = kcalloc(num, sizeof(int), GFP_KERNEL);
                if (indices == NULL)
                        return -ENOMEM;
 
-               memset(indices, 0, num*sizeof(int));
-
                get_port_ifindices(br, indices, num);
-               if (copy_to_user((void *)args[1], indices, num*sizeof(int)))
+               if (copy_to_user((void __user *)args[1], indices, num*sizeof(int)))
                        num =  -EFAULT;
                kfree(indices);
                return num;
@@ -241,7 +241,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
                rcu_read_unlock();
 
-               if (copy_to_user((void *)args[1], &p, sizeof(p)))
+               if (copy_to_user((void __user *)args[1], &p, sizeof(p)))
                        return -EFAULT;
 
                return 0;
@@ -308,11 +308,11 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        return -EOPNOTSUPP;
 }
 
-static int old_deviceless(unsigned long uarg)
+static int old_deviceless(void __user *uarg)
 {
        unsigned long args[3];
 
-       if (copy_from_user(args, (void *)uarg, sizeof(args)))
+       if (copy_from_user(args, uarg, sizeof(args)))
                return -EFAULT;
 
        switch (args[0]) {
@@ -324,14 +324,15 @@ static int old_deviceless(unsigned long uarg)
                int *indices;
                int ret = 0;
 
-               indices = kmalloc(args[2]*sizeof(int), GFP_KERNEL);
+               if (args[2] >= 2048)
+                       return -ENOMEM;
+               indices = kcalloc(args[2], sizeof(int), GFP_KERNEL);
                if (indices == NULL)
                        return -ENOMEM;
 
-               memset(indices, 0, args[2]*sizeof(int));
                args[2] = get_bridge_ifindices(indices, args[2]);
 
-               ret = copy_to_user((void *)args[1], indices, args[2]*sizeof(int))
+               ret = copy_to_user((void __user *)args[1], indices, args[2]*sizeof(int))
                        ? -EFAULT : args[2];
 
                kfree(indices);
@@ -346,7 +347,7 @@ static int old_deviceless(unsigned long uarg)
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
-               if (copy_from_user(buf, (void *)args[1], IFNAMSIZ))
+               if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ))
                        return -EFAULT;
 
                buf[IFNAMSIZ-1] = 0;
@@ -361,7 +362,7 @@ static int old_deviceless(unsigned long uarg)
        return -EOPNOTSUPP;
 }
 
-int br_ioctl_deviceless_stub(unsigned int cmd, unsigned long uarg)
+int br_ioctl_deviceless_stub(unsigned int cmd, void __user *uarg)
 {
        switch (cmd) {
        case SIOCGIFBR:
@@ -376,7 +377,7 @@ int br_ioctl_deviceless_stub(unsigned int cmd, unsigned long uarg)
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
-               if (copy_from_user(buf, (void __user *) uarg, IFNAMSIZ))
+               if (copy_from_user(buf, uarg, IFNAMSIZ))
                        return -EFAULT;
 
                buf[IFNAMSIZ-1] = 0;
@@ -403,6 +404,6 @@ int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
        }
 
-       printk(KERN_DEBUG "Bridge does not support ioctl 0x%x\n", cmd);
+       pr_debug("Bridge does not support ioctl 0x%x\n", cmd);
        return -EOPNOTSUPP;
 }