X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fbridge%2Fbr_ioctl.c;h=4c61a7e0a86e1ae9e16867f9f8e4b0412b8edbaf;hb=38177f0d626d937b43898550494220fe2b044289;hp=17c7ee3b3aa6dc07e01cccce1d4c14c8ead71a99;hpb=bc77d24c47b89f1e0efed0b8e4be5f8aad102883;p=linux-2.6.git diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index 17c7ee3b3..4c61a7e0a 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -13,6 +13,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include @@ -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; }