Blah. Puke. Ug. Not your changes, Bart... which are ok, but incomplete. Here is the complete bugfix. There are two places where error conditions are not fully handled, and 'out_spin' can kfree(image), saving some code. The worst bug of the list... if the firmware copy_from_user failed.... we still load firmware [ie. questionable data] into EEPROM. -- Jeff Garzik | Building 1024 | Would you like a Twinkie? MandrakeSoft |
Index: drivers/net/rrunner.c =================================================================== RCS file: /cvsroot/gkernel/linux_2_4/drivers/net/rrunner.c,v retrieving revision 1.1.1.4 diff -u -r1.1.1.4 rrunner.c --- drivers/net/rrunner.c 2000/11/10 02:09:10 1.1.1.4 +++ drivers/net/rrunner.c 2000/11/10 14:21:01 @@ -1550,36 +1550,29 @@ rrpriv = (struct rr_private *)dev->priv; - switch(cmd){ case SIOCRRGFW: - if (!capable(CAP_SYS_RAWIO)){ - error = -EPERM; - goto out; - } + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); if (!image){ printk(KERN_ERR "%s: Unable to allocate memory " "for EEPROM image\n", dev->name); - error = -ENOMEM; - goto out; + return -ENOMEM; } spin_lock(&rrpriv->lock); if (rrpriv->fw_running){ printk("%s: Firmware already running\n", dev->name); - kfree(image); error = -EPERM; goto out_spin; } i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES); if (i != EEPROM_BYTES){ - kfree(image); - printk(KERN_ERR "%s: Error reading EEPROM\n", - dev->name); + printk(KERN_ERR "%s: Error reading EEPROM\n", dev->name); error = -EFAULT; goto out_spin; } @@ -1591,9 +1584,8 @@ return error; case SIOCRRPFW: - if (!capable(CAP_SYS_RAWIO)){ + if (!capable(CAP_SYS_RAWIO)) return -EPERM; - } image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); if (!image){ @@ -1604,18 +1596,21 @@ oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); if (!oldimage){ + kfree(image); printk(KERN_ERR "%s: Unable to allocate memory " "for old EEPROM image\n", dev->name); return -ENOMEM; } error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES); - if (error) - error = -EFAULT; + if (error) { + kfree(image); + kfree(oldimage); + return -EFAULT; + } spin_lock(&rrpriv->lock); if (rrpriv->fw_running){ - kfree(image); kfree(oldimage); printk("%s: Firmware already running\n", dev->name); error = -EPERM; @@ -1652,6 +1647,7 @@ } out_spin: + kfree(image); spin_unlock(&rrpriv->lock); return error; }