more fun with malloc/free

From: Dawson Engler (engler@csl.Stanford.EDU)
Date: Wed Aug 09 2000 - 19:42:47 EST


Hi All,

to save people trouble wading through false positives, here's another
batch of annotated errors caught by the tool. Seem to be divided 50/50
between "not checking for allocation failure" and "not freeing memory
on error paths."

If anyone goes through and verifies/disproves some of these, we'd
appreciate the feedback.

Dawson
--------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/net/wan/lmc/lmc_main.c:518:lmc_ioctl: ERROR: did not free data on error path

                    data = kmalloc(xc.len, GFP_KERNEL);
                    if(data == 0x0){
                            printk(KERN_WARNING "%s: Failed to allocate memory for copy\n", dev->name);
                            ret = -ENOMEM;
                            break;
                    }

                    LMC_COPY_FROM_USER(data, xc.data, xc.len);

where LMC_* returns with an error if copy fails:.

     #define LMC_COPY_FROM_USER(x, y, z)
                if(copy_from_user ((x), (y), (z))) return -EFAULT

--------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/net/wan/lmc/lmc_proto.c:106:lmc_proto_init: ERROR: Unchecked use of malloc'd var 'sc'

        sc->pd = kmalloc(sizeof(struct ppp_device), GFP_KERNEL);
        sc->pd->dev = sc->lmc_device;

--------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx.c:508:comx_init_dev: ERROR: did not free ch on error path

        if ((ch = kmalloc(sizeof(struct comx_channel), GFP_KERNEL)) == NULL) {
                return -ENOMEM;
        }
        ...
        if ((ch->avg_bytes = kmalloc(ch->loadavg_size *
ch allocated
---> return -ENOMEM;
        }
--------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx.c:899:comx_mkdir: ERROR: did not free dev on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx.c:889:comx_mkdir: ERROR: did not free dev on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx.c:884:comx_mkdir: ERROR: did not free dev on error path

I *think*. If it comes through and retrys again its going to overwrite and
lose this memory. Also

        if ((dev = kmalloc(sizeof(struct net_device), GFP_KERNEL)) == NULL) {
                return -ENOMEM;
        }

        ...
[PLUS: could register dev but it might not be fully setup. Then you'll come
through and register again.]
---> if (register_netdevice(dev)) {

[dev is allocated but lost]
----> return -EIO;
        }

        ch=dev->priv;
        if((ch->if_ptr = (void *)kmalloc(sizeof(struct ppp_device),
                                 GFP_KERNEL)) == NULL) {
                return -ENOMEM;
        }
        memset(ch->if_ptr, 0, sizeof(struct ppp_device));
        ch->debug_file = debug_file;
        ch->procdir = new_dir;
        new_dir->data = dev;

        ch->debug_start = ch->debug_end = 0;
        if ((ch->debug_area = kmalloc(ch->debug_size = DEFAULT_DEBUG_SIZE,
            GFP_KERNEL)) == NULL) {
lost ch->if_ptr
--> return -ENOMEM;
        }

        ch->lineup_delay = DEFAULT_LINEUP_DELAY;

---------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-comx.c:1289:COMX_init: ERROR: did not free ch on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-comx.c:1278:COMX_init: ERROR: did not free ch on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-comx.c:1266:COMX_init: ERROR: did not free ch on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-comx.c:1254:COMX_init: ERROR: did not free ch on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-comx.c:1243:COMX_init: ERROR: did not free ch on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-comx.c:1232:COMX_init: ERROR: did not free ch on error path

this gets lost on a retry since you don't check if it already exists:

        if ((ch->HW_privdata = kmalloc(sizeof(struct comx_privdata),
            GFP_KERNEL)) == NULL) {
                return -ENOMEM;
        }
        ...

        if ((new_file = create_proc_entry(FILENAME_MEMADDR, S_IFREG | 0644,
            ch->procdir)) == NULL) {
ch->HW_privdata seems to get lost
----> return -EIO;
        }
--------------------------------------------------------------------

/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-locomx.c:403:LOCOMX_init: ERROR: did not free ch on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-locomx.c:393:LOCOMX_init: ERROR: did not free ch on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-mixcom.c:869:MIXCOM_init: ERROR: did not free ch on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-mixcom.c:859:MIXCOM_init: ERROR: did not free ch on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-mixcom.c:837:MIXCOM_init: ERROR: did not free ch on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/comx-hw-mixcom.c:827:MIXCOM_init: ERROR: did not free ch on error path

Seems like its going to lose:
        /* Alloc data for private structure */
        if ((ch->HW_privdata = kmalloc(sizeof(struct locomx_data),
           GFP_KERNEL)) == NULL) {
                return -ENOMEM;

on all of these since ch->HW_privdata does not get checked on retry.

-------------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/net/wan/lapbether.c:444:lapbeth_new_device: ERROR: Unchecked use of malloc'd var 'buf'
/u2/engler/ic/linux-2.3.99/drivers/net/wan/lapbether.c:434:lapbeth_new_device: ERROR: Unchecked use of malloc'd var 'buf'

        buf = kmalloc(14, GFP_KERNEL);

        for (k = 0; k < MAXLAPBDEV; k++) {
                struct net_device *odev;

used
---> sprintf(buf, "lapb%d", k);
                if ((odev = __dev_get_by_name(buf)) == NULL || lapbeth_check_devices(odev))
                        break;
        }

-----------------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/net/wan/sdla.c:1215:sdla_xfer: ERROR: did not free temp on error path
/u2/engler/ic/linux-2.3.99/drivers/net/wan/sdla.c:1206:sdla_xfer: ERROR: did not free temp on error path

        if (read)
        {
                temp = kmalloc(mem.len, GFP_KERNEL);
                if (!temp) return(-ENOMEM);
                sdla_read(dev, mem.addr, temp, mem.len);
                if(copy_to_user(mem.data, temp, mem.len))
lost temp
---> return -EFAULT;
                kfree(temp);
        }
        else
        {
                temp = kmalloc(mem.len, GFP_KERNEL);
                if (!temp)
                        return(-ENOMEM);
                if(copy_from_user(temp, mem.data, mem.len))
lost temp
----> return -EFAULT;
                sdla_write(dev, mem.addr, temp, mem.len);
                kfree(temp);
        }
-----------------------------------------------------------------------

/u2/engler/ic/linux-2.3.99/drivers/net/appletalk/ipddp.c:245:ipddp_create: ERROR: did not free rt on error path

        struct ipddp_route *rt =(struct ipddp_route*) kmalloc(sizeof(*rt), GFP_KERNEL); struct ipddp_route *test;

        if(rt == NULL)
                return -ENOMEM;

        rt->ip = new_rt->ip;
        rt->at = new_rt->at;
        rt->next = NULL;
        rt->dev = atrtr_get_dev(&rt->at); if(rt->dev == NULL) return (-ENETUNREACH);

-----------------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/net/skfp/skfddi.c:690:skfp_driver_init: ERROR: memset of unchecked var 'bp'!

alloc
---> bp->SharedMemAddr = kmalloc(bp->SharedMemSize, GFP_KERNEL);
                if (!bp->SharedMemSize) {
                        printk("could not allocate mem for ");
                        printk("hardware module: %ld byte\n",
                                       bp->SharedMemSize);
                        return (-1);
                }
                bp->SharedMemHeap = 0; // Nothing used yet.

        } else {
                bp->SharedMemAddr = NULL;
                bp->SharedMemHeap = 0;
        } // SharedMemSize > 0
use
---> memset(bp->SharedMemAddr, 0, bp->SharedMemS

-----------------------------------------------------------------------

/u2/engler/ic/linux-2.3.99/drivers/parport/daisy.c:50:add_dev: ERROR: allocated 7 bytes for 'newdev' need 16

swapped GFP_KERNEL and size:
        newdev = kmalloc (GFP_KERNEL, sizeof (struct daisydev));

----------------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/sound/softoss.c:1117:softsyn_load_patch: ERROR: did not free patch on error path

        patch = vmalloc(sizeof(*patch));

        if(copy_from_user(&((char *) patch)[offs], &(addr)[offs], sizeof_patch - offs))
lost patch
----> return -EFAULT;

----------------------------------------------------------------------

/u2/engler/ic/linux-2.3.99/drivers/sound/sonicvibes.c:2604:sv_probe: ERROR: did not free s on error path

        kfree_s(s, sizeof(struct sv_state));
        return -1;

------------------------------------------------------------------

/u2/engler/ic/linux-2.3.99/drivers/pcmcia/cs.c:337:register_ss_entry: ERROR: memset of unchecked var 's'!

        s = kmalloc(sizeof(struct socket_info_t), GFP_KERNEL);
        memset(s, 0, sizeof(socket_info_t));

------------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/pcmcia/cs.c:1411:pcmcia_register_client: ERROR: memset of unchecked var 's'!

        s->config = kmalloc(sizeof(config_t) * s->functions, GFP_KERNEL);
        memset(s->config, 0, sizeof(config_t) * s->functions);
------------------------------------------------------------------

/u2/engler/ic/linux-2.3.99/drivers/pcmcia/ds.c:414:bind_request: ERROR: Unchecked use of malloc'd var 'b'

    b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
    b->driver = driver;

------------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/pcmcia/ds.c:424:bind_request: ERROR: did not free driver on error path

    if (driver->attach) { b->instance = driver->attach();
        if (b->instance == NULL) {
            printk(KERN_NOTICE "ds: unable to create instance "
                "of '%s'!\n", (char *)bind_info->dev_info);
lost b
----> return -ENODEV;
        }
    }
------------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/pcmcia/bulkmem.c:232:setup_erase_request: ERROR: Unchecked use of malloc'd var 'busy'

            busy = kmalloc(sizeof(erase_busy_t), GFP_KERNEL);
            busy->erase = erase;

------------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/pcmcia/bulkmem.c:363:setup_regions: ERROR: Unchecked use of malloc'd var 'r'

            r = kmalloc(sizeof(*r), GFP_KERNEL);
            r->region_magic = REGION_MAGIC;

------------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/pcmcia/rsrc_mgr.c:193:do_io_probe: ERROR: memset of unchecked var 'b'!

    b = kmalloc(256, GFP_KERNEL);
    memset(b, 0, 256);

------------------------------------------------------------------
/u2/engler/ic/linux-2.3.99/drivers/video/matrox/matroxfb_crtc2.c:638:matroxfb_dh_regit: ERROR: memset of unchecked var 'd'!

        d = kmalloc(sizeof(*d), GFP_KERNEL);
        memset(d, 0, sizeof(*d));

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue Aug 15 2000 - 21:00:20 EST