Skip to contentSkip to conversation

32 Memory Leaks on Error Paths

CHECKER New David Yu Chen 14 participants 39 messages Sep 16, 2003 – Sep 24, 2003

Subsystems (12)
lore
Share & tools
lore
#0 lore raw

Hi All,

I'm with the Stanford Meta-level Compilation research group, and I have a set of memory leaks on error paths for the 2.6.0-test5 kernel. (I also have error reports for 2.4.18 and a couple other kernels if anyone is interested).

There may be one or more "GOTO -->" markers showing the different paths of execution that can occur between where the memory is allocated and where the function returns.

My checker identifies error paths with a learning algorithm on features surrounding goto and return statements. I'd greatly appreciate any comments or confirmation on these bugs.

Thanks!

---
David Yu Chen
http://www.stanford.edu/~dychen/

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

Count = 32

# | File
1 | drivers/char/vt_ioctl.c
1 | drivers/media/video/bttv-risc.c
2 | drivers/mtd/chips/cfi_cmdset_0020.c
1 | drivers/mtd/mtdblock.c
1 | drivers/net/irda/ali-ircc.c
1 | drivers/net/irda/nsc-ircc.c
2 | drivers/pci/hotplug/ibmphp_ebda.c
1 | drivers/scsi/NCR_Q720.c
1 | drivers/scsi/scsi_debug.c
1 | drivers/telephony/ixj_pcmcia.c
2 | drivers/usb/class/usb-midi.c
1 | drivers/usb/input/hiddev.c
1 | fs/afs/cell.c
2 | fs/jffs2/scan.c
1 | fs/nfsd/nfsctl.c
2 | net/ipv4/igmp.c
1 | net/irda/irlmp.c
1 | net/sunrpc/auth_gss/gss_mech_switch.c
1 | net/sunrpc/auth_gss/gss_pseudoflavors.c
1 | security/selinux/selinuxfs.c
1 | security/selinux/ss/mls.c
4 | security/selinux/ss/policydb.c
1 | sound/oss/emu10k1/midi.c
1 | sound/oss/ymfpci.c

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

[FILE: 2.6.0-test5/drivers/char/vt_ioctl.c]
[FUNC: do_kdsk_ioctl]
[LINES: 133-150]
[VAR: key_map]
128:
129: if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
130: !capable(CAP_SYS_RESOURCE))
131: return -EPERM;
132:
START -->
133: key_map = (ushort *) kmalloc(sizeof(plain_map),
134: GFP_KERNEL);
135: if (!key_map)
136: return -ENOMEM;
137: key_maps[s] = key_map;

 138:			key_map[0] = U(K_ALLOCATED);
        ... DELETED 6 lines ...

145: break; /* nothing to do */
146: /*
147: * Attention Key.
148: */
149: if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
END -->
150: return -EPERM;
151: key_map[i] = U(v);
152: if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
153: compute_shiftstate();
154: break;
155: }
---------------------------------------------------------

[FILE: 2.6.0-test5/drivers/media/video/bttv-risc.c] [FUNC: bttv_risc_overlay]
[LINES: 214-223]
[VAR: skips]
209: struct btcx_skiplist *skips;
210: u32 *rp,ri,ra;
211: u32 addr;
212:
213: /* skip list for window clipping */
START -->
214: if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
215: return -ENOMEM;
216:
217: /* estimate risc mem: worst case is (clip+1) * lines instructions
218: + sync + jump (all 2 dwords) */
219: instructions = (ov->nclips + 1) *
220: ((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height);
221: instructions += 2;
222: if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)
END -->
223: return rc;
224:
225: /* sync instruction */
226: rp = risc->cpu;
227: *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
228: *(rp++) = cpu_to_le32(0);
---------------------------------------------------------

[FILE: 2.6.0-test5/drivers/mtd/chips/cfi_cmdset_0020.c] [FUNC: cfi_staa_setup]
[LINES: 191-211]
[VAR: mtd]
186: struct mtd_info *mtd;
187: unsigned long offset = 0;
188: int i,j;
189: unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
190:
START -->
191: mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
192: //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
193:
194: if (!mtd) {
195: printk(KERN_ERR "Failed to allocate memory for MTD device\n");

 196:		kfree(cfi->cmdset_priv);
        ... DELETED 9 lines ...

206: mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
207: * mtd->numeraseregions, GFP_KERNEL);
208: if (!mtd->eraseregions) {
209: printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
210: kfree(cfi->cmdset_priv);
END -->
211: return NULL;
212: }
213:
214: for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
215: unsigned long ernum, ersize;
216: ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
---------------------------------------------------------

[FILE: 2.6.0-test5/drivers/mtd/chips/cfi_cmdset_0020.c] [FUNC: cfi_staa_setup]
[LINES: 191-235]
[VAR: mtd]
186: struct mtd_info *mtd;
187: unsigned long offset = 0;
188: int i,j;
189: unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
190:
START -->
191: mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
192: //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
193:
194: if (!mtd) {
195: printk(KERN_ERR "Failed to allocate memory for MTD device\n");

 196:		kfree(cfi->cmdset_priv);
        ... DELETED 33 lines ...

230: if (offset != devsize) {
231: /* Argh */
232: printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
233: kfree(mtd->eraseregions);
234: kfree(cfi->cmdset_priv);
END -->
235: return NULL;
236: }
237:
238: for (i=0; i<mtd->numeraseregions;i++){
239: printk(KERN_DEBUG "%d: offset=0x%x,size=0x%x,blocks=%d\n",
240: i,mtd->eraseregions[i].offset,
---------------------------------------------------------

looks like checking for mtdblks instead of mtdblk
[FILE: 2.6.0-test5/drivers/mtd/mtdblock.c]
[FUNC: mtdblock_open]
[LINES: 277-279]
[VAR: mtdblk]
272: mtdblks[dev]->count++;
273: return 0;
274: }
275:
276: /* OK, it's not open. Create cache info for it */
START -->
277: mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
278: if (!mtdblks)
END -->
279: return -ENOMEM;
280:
281: memset(mtdblk, 0, sizeof(*mtdblk));
282: mtdblk->count = 1;
283: mtdblk->mtd = mtd;
284:
---------------------------------------------------------

[FILE: 2.6.0-test5/drivers/net/irda/ali-ircc.c]
[FUNC: ali_ircc_open]
[LINES: 259-337]
[VAR: self]
254: /* Set FIR FIFO and DMA Threshold */
255: if ((ali_ircc_setup(info)) == -1)
256: return -1;
257:
258: /* Allocate new instance of the driver */
START -->
259: self = kmalloc(sizeof(struct ali_ircc_cb), GFP_KERNEL);
260: if (self == NULL)
261: {
262: ERROR("%s(), can't allocate memory for control block!\n", __FUNCTION__);
263: return -ENOMEM;
264: }

        ... DELETED 67 lines ...

332: self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
333: self->tx_fifo.tail = self->tx_buff.head;
334:
335: if (!(dev = dev_alloc("irda%d", &err))) {
336: ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
END -->
337: return -ENOMEM;
338: }
339:
340: dev->priv = (void *) self;
341: self->netdev = dev;
342:
---------------------------------------------------------

[FILE: 2.6.0-test5/drivers/net/irda/nsc-ircc.c]
[FUNC: nsc_ircc_open]
[LINES: 265-341]
[VAR: self]
260: return -1;
261:
262: MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
263:
264: /* Allocate new instance of the driver */
START -->
265: self = kmalloc(sizeof(struct nsc_ircc_cb), GFP_KERNEL);
266: if (self == NULL) {
267: ERROR("%s(), can't allocate memory for "
268: "control block!\n", __FUNCTION__);
269: return -ENOMEM;
270: }

        ... DELETED 65 lines ...

336: self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
337: self->tx_fifo.tail = self->tx_buff.head;
338:
339: if (!(dev = dev_alloc("irda%d", &err))) {
340: ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
END -->
341: return -ENOMEM;
342: }
343:
344: dev->priv = (void *) self;
345: self->netdev = dev;
346:
---------------------------------------------------------

[FILE: 2.6.0-test5/drivers/pci/hotplug/ibmphp_ebda.c] [FUNC: ebda_rsrc_controller]
[LINES: 857-1064]
[VAR: bus_info_ptr1]
852:
853: // create bus_info lined list --- if only one slot per bus: slot_min = slot_max
854:
855: bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num);
856: if (!bus_info_ptr2) {
START -->
857: bus_info_ptr1 = (struct bus_info *) kmalloc (sizeof (struct bus_info), GFP_KERNEL);
858: if (!bus_info_ptr1) {
859: rc = -ENOMEM;
860: goto error_no_hp_slot;
861: }

 862:				memset (bus_info_ptr1, 0, sizeof (struct bus_info));
        ... DELETED 79 lines ...

942: hpc_ptr->irq = readb (io_mem + addr + 5);
943: addr += 6;
944: break;
945: default:
946: rc = -ENODEV;
GOTO -->
947: goto error_no_hp_slot;
948: }
949:
950: //reorganize chassis' linked list
951: combine_wpg_for_chassis ();

 952:		combine_wpg_for_expansion ();
        ... DELETED 106 lines ...

1059: kfree (hp_slot_ptr);
1060:error_no_hp_slot:
1061: free_ebda_hpc (hpc_ptr);
1062:error_no_hpc:
1063: iounmap (io_mem);
END -->
1064: return rc;
1065:}
1066:
1067:/*
1068: * map info (bus, devfun, start addr, end addr..) of i/o, memory, 1069: * pfm from the physical addr to a list of resource.
---------------------------------------------------------

[FILE: 2.6.0-test5/drivers/pci/hotplug/ibmphp_ebda.c] [FUNC: ebda_rsrc_controller]
[LINES: 981-1064]
[VAR: tmp_slot]
976: if (!hp_slot_ptr->name) {
977: rc = -ENOMEM;
978: goto error_no_hp_name;
979: }
980:
START -->
981: tmp_slot = kmalloc(sizeof(*tmp_slot), GFP_KERNEL);
982: if (!tmp_slot) {
983: rc = -ENOMEM;
984: goto error_no_slot;
985: }

 986:			memset(tmp_slot, 0, sizeof(*tmp_slot));
        ... DELETED 17 lines ...

1004: tmp_slot->bus = hpc_ptr->slots[index].slot_bus_num;
1005:
1006: bus_info_ptr1 = ibmphp_find_same_bus_num (hpc_ptr->slots[index].slot_bus_num);
1007: if (!bus_info_ptr1) {
1008: rc = -ENODEV;
GOTO -->
1009: goto error;
1010: }
1011: tmp_slot->bus_on = bus_info_ptr1;
1012: bus_info_ptr1 = NULL;
1013: tmp_slot->ctrl = hpc_ptr;
1014:

        ... DELETED 44 lines ...

1059: kfree (hp_slot_ptr);
1060:error_no_hp_slot:
1061: free_ebda_hpc (hpc_ptr);
1062:error_no_hpc:
1063: iounmap (io_mem);
END -->
1064: return rc;
1065:}
1066:
1067:/*
1068: * map info (bus, devfun, start addr, end addr..) of i/o, memory, 1069: * pfm from the physical addr to a list of resource.
---------------------------------------------------------

[FILE: 2.6.0-test5/drivers/scsi/NCR_Q720.c]
[FUNC: NCR_Q720_probe]
[LINES: 153-182]
[VAR: p]
148: __u8 pos2, pos4, asr2, asr9, asr10;
149: __u16 io_base;
150: __u32 base_addr, mem_size;
151: __u32 mem_base;
152:
START -->
153: p = kmalloc(sizeof(*p), GFP_KERNEL);
154: if (!p)
155: return -ENOMEM;
156:
157: memset(p, 0, sizeof(*p));

 158:	pos2 = mca_device_read_pos(mca_dev, 2);
        ... DELETED 18 lines ...

177:
178: /* sanity check I/O mapping */
179: i = inb(io_base) | (inb(io_base+1)<<8);
180: if(i != NCR_Q720_MCA_ID) {
181: printk(KERN_ERR "NCR_Q720, adapter failed to I/O map registers correctly at 0x%x(0x%x)\n", io_base, i);
END -->
182: return -ENODEV;
183: }
184:
185: /* Phase II, find the ram base and memory map the board register */
186: pos4 = inb(io_base + 4);
187: /* enable streaming data */
---------------------------------------------------------

Leaks memory if kmalloc fails between 0 .. devs_per_host [FILE: 2.6.0-test5/drivers/scsi/scsi_debug.c] [FUNC: sdebug_add_adapter]
[LINES: 1612-1652]
[VAR: sdbg_devinfo]
1607: memset(sdbg_host, 0, sizeof(*sdbg_host));
1608: INIT_LIST_HEAD(&sdbg_host->dev_info_list);
1609:
1610: devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
1611: for (k = 0; k < devs_per_host; k++) {
START -->
1612: sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL);
1613: if (NULL == sdbg_devinfo) {
1614: printk(KERN_ERR "%s: out of memory at line %d\n",
1615: __FUNCTION__, __LINE__);
1616: error = -ENOMEM;
GOTO -->

1617:			goto clean1;
        ... DELETED 29 lines ...

1647: kfree(sdbg_devinfo);
1648: }
1649:
1650:clean1:
1651: kfree(sdbg_host);
END -->
1652: return error;
1653:}
1654:
1655:static void sdebug_remove_adapter()
1656:{
1657: struct sdebug_host_info * sdbg_host = NULL;
---------------------------------------------------------

[FILE: 2.6.0-test5/drivers/telephony/ixj_pcmcia.c] [FUNC: ixj_attach]
[LINES: 53-64]
[VAR: link]
48: client_reg_t client_reg;
49: dev_link_t *link;
50: int ret;
51: DEBUG(0, "ixj_attach()\n");
52: /* Create new ixj device */
START -->
53: link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
54: if (!link)
55: return NULL;
56: memset(link, 0, sizeof(struct dev_link_t));
57: link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
58: link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
59: link->io.IOAddrLines = 3;
60: link->conf.Vcc = 50;
61: link->conf.IntType = INT_MEMORY_AND_IO;
62: link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
63: if (!link->priv)
END -->
64: return NULL;
65: memset(link->priv, 0, sizeof(struct ixj_info_t));
66: /* Register with Card Services */
67: link->next = dev_list;
68: dev_list = link;
69: client_reg.dev_info = &dev_info;
---------------------------------------------------------

Leaks if devices == 0 ? Error_end only frees mdevs if (devices > 0), but for mdevs=kmalloc(0), the slab allocator may still actually return memory [FILE: 2.6.0-test5/drivers/usb/class/usb-midi.c]
[FUNC: alloc_usb_midi_device]
[LINES: 1621-1772]
[VAR: mdevs]
1616: devices = inDevs > outDevs ? inDevs : outDevs;
1617: devices = maxdevices > devices ? devices : maxdevices;
1618:
1619: /* obtain space for device name (iProduct) if not known. */
1620: if ( ! u->deviceName ) {
START -->
1621: mdevs = (struct usb_mididev **)
1622: kmalloc(sizeof(struct usb_mididevs *)*devices
1623: + sizeof(char) * 256, GFP_KERNEL);
1624: } else {
1625: mdevs = (struct usb_mididev **)

1626:			kmalloc(sizeof(struct usb_mididevs *)*devices, GFP_KERNEL);
        ... DELETED 83 lines ...

1710: }
1711: mout = mouts[outEndpoint];
1712:
1713: mdevs[i] = allocMidiDev( s, min, mout, inCableId, outCableId );
1714: if ( mdevs[i] == NULL )
GOTO -->
1715: goto error_end;
1716:
1717: }
1718:
1719: /* Success! */

1720:	for ( i=0 ; i<devices ; i++ ) {
        ... DELETED 46 lines ...

1767: if ( mouts[i] != NULL ) {
1768: remove_midi_out_endpoint( mouts[i] );
1769: }
1770: }
1771:
END -->
1772: return -ENOMEM;
1773:}
1774:
1775:/* ------------------------------------------------------------------------- */ 1776:
1777:/** Attempt to scan YAMAHA's device descriptor and detect correct values of
---------------------------------------------------------

[FILE: 2.6.0-test5/drivers/usb/class/usb-midi.c]
[FUNC: alloc_usb_midi_device]
[LINES: 1625-1772]
[VAR: mdevs]
1620: if ( ! u->deviceName ) {
1621: mdevs = (struct usb_mididev **)
1622: kmalloc(sizeof(struct usb_mididevs *)*devices
1623: + sizeof(char) * 256, GFP_KERNEL);
1624: } else {
START -->
1625: mdevs = (struct usb_mididev **)
1626: kmalloc(sizeof(struct usb_mididevs *)*devices, GFP_KERNEL);
1627: }
1628:
1629: if ( !mdevs ) {
1630: /* devices = 0; */

        ... DELETED 79 lines ...

1710: }
1711: mout = mouts[outEndpoint];
1712:
1713: mdevs[i] = allocMidiDev( s, min, mout, inCableId, outCableId );
1714: if ( mdevs[i] == NULL )
GOTO -->
1715: goto error_end;
1716:
1717: }
1718:
1719: /* Success! */

1720:	for ( i=0 ; i<devices ; i++ ) {
        ... DELETED 46 lines ...

1767: if ( mouts[i] != NULL ) {
1768: remove_midi_out_endpoint( mouts[i] );
1769: }
1770: }
1771:
END -->
1772: return -ENOMEM;
1773:}
1774:
1775:/* ------------------------------------------------------------------------- */ 1776:
1777:/** Attempt to scan YAMAHA's device descriptor and detect correct values of
---------------------------------------------------------

[FILE: 2.6.0-test5/drivers/usb/input/hiddev.c]
[FUNC: hiddev_connect]
[LINES: 723-730]
[VAR: hiddev]
718: break;
719:
720: if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0)
721: return -1;
722:
START -->
723: if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL)))
724: return -1;
725: memset(hiddev, 0, sizeof(struct hiddev));
726:
727: retval = usb_register_dev(&hiddev->intf, &hiddev_class);
728: if (retval) {
729: err("Not able to get a minor for this device.");
END -->
730: return -1;
731: }
732:
733: init_waitqueue_head(&hiddev->wait);
734:
735: hiddev->minor = hiddev->intf.minor;
---------------------------------------------------------

[FILE: 2.6.0-test5/fs/afs/cell.c]
[FUNC: afs_cell_create]
[LINES: 58-129]
[VAR: cell]
53: if (!name) BUG(); /* TODO: want to look up "this cell" in the cache */
54:
55: down_write(&afs_cells_sem);
56:
57: /* allocate and initialise a cell record */
START -->
58: cell = kmalloc(sizeof(afs_cell_t) + strlen(name) + 1,GFP_KERNEL);
59: if (!cell) {
60: _leave(" = -ENOMEM");
61: return -ENOMEM;
62: }
63:

        ... DELETED 25 lines ...

89:
90: if (sscanf(vllist,"%u.%u.%u.%u",&a,&b,&c,&d)!=4)
91: goto badaddr;
92:
93: if (a>255 || b>255 || c>255 || d>255)
GOTO -->
94: goto badaddr;
95:
96: cell->vl_addrs[cell->vl_naddrs++].s_addr =
97: htonl((a<<24)|(b<<16)|(c<<8)|d);
98:
99: if (cell->vl_naddrs>=16)

        ... DELETED 24 lines ...

124: badaddr:
125: printk("kAFS: bad VL server IP address: '%s'\n",vllist);
126: error:
127: up_write(&afs_cells_sem);
128: kfree(afs_cell_root);
END -->
129: return ret;
130:} /* end afs_cell_create() */
131:
132:/*****************************************************************************/ 133:/*
134: * initialise the cell database from module parameters
---------------------------------------------------------

[FILE: 2.6.0-test5/fs/jffs2/scan.c]
[FUNC: jffs2_scan_medium]
[LINES: 98-109]
[VAR: flashbuf]
93: buf_size = c->sector_size;
94: else
95: buf_size = PAGE_SIZE;
96:
97: D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size));
START -->
98: flashbuf = kmalloc(buf_size, GFP_KERNEL);
99: if (!flashbuf)
100: return -ENOMEM;
101: }
102:
103: for (i=0; i<c->nr_blocks; i++) {
104: struct jffs2_eraseblock *jeb = &c->blocks[i];
105:
106: ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size);
107:
108: if (ret < 0)
END -->
109: return ret;
110:
111: ACCT_PARANOIA_CHECK(jeb);
112:
113: /* Now decide which list to put it on */
114: switch(ret) {
---------------------------------------------------------

[FILE: 2.6.0-test5/fs/jffs2/scan.c]
[FUNC: jffs2_scan_medium]
[LINES: 98-233]
[VAR: flashbuf]
93: buf_size = c->sector_size;
94: else
95: buf_size = PAGE_SIZE;
96:
97: D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size));
START -->
98: flashbuf = kmalloc(buf_size, GFP_KERNEL);
99: if (!flashbuf)
100: return -ENOMEM;
101: }
102:

 103:	for (i=0; i<c->nr_blocks; i++) {
        ... DELETED 124 lines ...

228: }
229: if (c->nr_erasing_blocks) {
230: if ( !c->used_size && ((empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) {
231: printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
232: printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",empty_blocks,bad_blocks,c->nr_blocks);
END -->
233: return -EIO;
234: }
235: jffs2_erase_pending_trigger(c);
236: }
237: if (buf_size)
238: kfree(flashbuf);
---------------------------------------------------------

[FILE: 2.6.0-test5/fs/nfsd/nfsctl.c]
[FUNC: TA_write]
[LINES: 105-120]
[VAR: ar]
100: if (file->private_data)
101: return -EINVAL; /* only one write allowed per open */
102: if (size > PAGE_SIZE - sizeof(struct argresp))
103: return -EFBIG;
104:
START -->
105: ar = kmalloc(PAGE_SIZE, GFP_KERNEL);
106: if (!ar)
107: return -ENOMEM;
108: ar->size = 0;
109: down(&file->f_dentry->d_inode->i_sem);
110: if (file->private_data)

        ... DELETED 4 lines ...

115: if (rv) {
116: kfree(ar);
117: return rv;
118: }
119: if (copy_from_user(ar->data, buf, size))
END -->
120: return -EFAULT;
121:
122: rv = write_op[ino](file, ar->data, size);
123: if (rv>0) {
124: ar->size = rv;
125: rv = size;
---------------------------------------------------------

[FILE: 2.6.0-test5/net/ipv4/igmp.c]
[FUNC: igmpv3_newpack]
[LINES: 274-284]
[VAR: skb]
269: struct sk_buff *skb;
270: struct rtable *rt;
271: struct iphdr *pip;
272: struct igmpv3_report *pig;
273:
START -->
274: skb = alloc_skb(size + dev->hard_header_len + 15, GFP_ATOMIC);
275: if (skb == NULL)
276: return 0;
277:
278: {
279: struct flowi fl = { .oif = dev->ifindex,

 280:				    .nl_u = { .ip4_u = {
 281:				    .daddr = IGMPV3_ALL_MCR } },
 282:				    .proto = IPPROTO_IGMP };

283: if (ip_route_output_key(&rt, &fl))
END -->
284: return 0;
285: }
286: if (rt->rt_src == 0) {
287: ip_rt_put(rt);
288: return 0;
289: }
---------------------------------------------------------

[FILE: 2.6.0-test5/net/ipv4/igmp.c]
[FUNC: igmpv3_newpack]
[LINES: 274-288]
[VAR: skb]
269: struct sk_buff *skb;
270: struct rtable *rt;
271: struct iphdr *pip;
272: struct igmpv3_report *pig;
273:
START -->
274: skb = alloc_skb(size + dev->hard_header_len + 15, GFP_ATOMIC);
275: if (skb == NULL)
276: return 0;
277:
278: {
279: struct flowi fl = { .oif = dev->ifindex,

        ... DELETED 3 lines ...

283: if (ip_route_output_key(&rt, &fl))
284: return 0;
285: }
286: if (rt->rt_src == 0) {
287: ip_rt_put(rt);
END -->
288: return 0;
289: }
290:
291: skb->dst = &rt->u.dst;
292: skb->dev = dev;
293:
---------------------------------------------------------

[FILE: 2.6.0-test5/net/irda/irlmp.c]
[FUNC: irlmp_open_lsap]
[LINES: 161-183]
[VAR: self]
156: return NULL;
157: } else if (irlmp_slsap_inuse(slsap_sel))
158: return NULL;
159:
160: /* Allocate new instance of a LSAP connection */
START -->
161: self = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
162: if (self == NULL) {
163: ERROR("%s: can't allocate memory", __FUNCTION__);
164: return NULL;
165: }

 166:	memset(self, 0, sizeof(struct lsap_cb));
        ... DELETED 11 lines ...

178: self->dlsap_sel = LSAP_ANY;
179: /* self->connected = FALSE; -> already NULL via memset() */
180:
181: init_timer(&self->watchdog_timer);
182:
END -->
183: ASSERT(notify->instance != NULL, return NULL;);
184: self->notify = *notify;
185:
186: self->lsap_state = LSAP_DISCONNECTED;
187:
188: /* Insert into queue of unconnected LSAPs */
---------------------------------------------------------

[FILE: 2.6.0-test5/net/sunrpc/auth_gss/gss_mech_switch.c]
[FUNC: gss_mech_register]
[LINES: 67-74]
[VAR: gm]
62:int
63:gss_mech_register(struct xdr_netobj * mech_type, struct gss_api_ops * ops) 64:{
65: struct gss_api_mech *gm;
66:
START -->
67: if (!(gm = kmalloc(sizeof(*gm), GFP_KERNEL))) {
68: printk("Failed to allocate memory in gss_mech_register");
69: return -1;
70: }
71: gm->gm_oid.len = mech_type->len;
72: if (!(gm->gm_oid.data = kmalloc(mech_type->len, GFP_KERNEL))) {
73: printk("Failed to allocate memory in gss_mech_register");
END -->
74: return -1;
75: }
76: memcpy(gm->gm_oid.data, mech_type->data, mech_type->len);
77: /* We're counting the reference in the registered_mechs list: */
78: atomic_set(&gm->gm_count, 1);
79: gm->gm_ops = ops;
---------------------------------------------------------

[FILE: 2.6.0-test5/net/sunrpc/auth_gss/gss_pseudoflavors.c] [FUNC: gss_register_triple]
[LINES: 74-97]
[VAR: triple]
69:gss_register_triple(u32 pseudoflavor, struct gss_api_mech *mech,
70: u32 qop, u32 service)
71:{
72: struct sup_sec_triple *triple;
73:
START -->
74: if (!(triple = kmalloc(sizeof(*triple), GFP_KERNEL))) {
75: printk("Alloc failed in gss_register_triple");
76: goto err;
77: }
78: triple->pseudoflavor = pseudoflavor;

  79:	triple->mech = gss_mech_get_by_OID(&mech->gm_oid);
        ... DELETED 1 lines ...

81: triple->service = service;
82:
83: spin_lock(&registered_triples_lock);
84: if (do_lookup_triple_by_pseudoflavor(pseudoflavor)) {
85: printk("Registered pseudoflavor %d again\n", pseudoflavor);
GOTO -->
86: goto err_unlock;
87: }
88: list_add(&triple->triples, &registered_triples);
89: spin_unlock(&registered_triples_lock);
90: dprintk("RPC: registered pseudoflavor %d\n", pseudoflavor);
91:
92: return 0;
93:
94:err_unlock:
95: spin_unlock(&registered_triples_lock);
96:err:
END -->
97: return -1;
98:}
99:
100:int
101:gss_unregister_triple(u32 pseudoflavor)
102:{
---------------------------------------------------------

[FILE: 2.6.0-test5/security/selinux/selinuxfs.c]
[FUNC: TA_write]
[LINES: 253-269]
[VAR: ar]
248: if (file->private_data)
249: return -EINVAL; /* only one write allowed per open */
250: if (size > PAYLOAD_SIZE - 1) /* allow one byte for null terminator */
251: return -EFBIG;
252:
START -->
253: ar = kmalloc(PAGE_SIZE, GFP_KERNEL);
254: if (!ar)
255: return -ENOMEM;
256: memset(ar, 0, PAGE_SIZE); /* clear buffer, particularly last byte */
257: ar->size = 0;

 258:	down(&file->f_dentry->d_inode->i_sem);
        ... DELETED 5 lines ...

264: if (rv) {
265: kfree(ar);
266: return rv;
267: }
268: if (copy_from_user(ar->data, buf, size))
END -->
269: return -EFAULT;
270:
271: rv = write_op[ino](file, ar->data, size);
272: if (rv>0) {
273: ar->size = rv;
274: rv = size;
---------------------------------------------------------

[FILE: 2.6.0-test5/security/selinux/ss/mls.c] [FUNC: mls_read_user]
[LINES: 543-561]
[VAR: r]
538: goto out;
539: }
540: nel = le32_to_cpu(buf[0]);
541: l = NULL;
542: for (i = 0; i < nel; i++) {
START -->
543: r = kmalloc(sizeof(*r), GFP_ATOMIC);
544: if (!r) {
545: rc = -ENOMEM;
546: goto out;
547: }
548: memset(r, 0, sizeof(*r));
549:
550: rc = mls_read_range_helper(&r->range, fp);
551: if (rc)
GOTO -->
552: goto out;
553:
554: if (l)
555: l->next = r;
556: else
557: usrdatum->ranges = r;
558: l = r;
559: }
560:out:
END -->
561: return rc;
562:}
563:
564:int mls_read_nlevels(struct policydb *p, void *fp) 565:{
566: u32 *buf;
---------------------------------------------------------

[FILE: 2.6.0-test5/security/selinux/ss/policydb.c] [FUNC: policydb_read]
[LINES: 1232-1427]
[VAR: c]
1227: goto bad;
1228: }
1229: nel = le32_to_cpu(buf[0]);
1230: l = NULL;
1231: for (j = 0; j < nel; j++) {
START -->
1232: c = kmalloc(sizeof(*c), GFP_KERNEL);
1233: if (!c) {
1234: rc = -ENOMEM;
1235: goto bad;
1236: }

1237:			memset(c, 0, sizeof(*c));
        ... DELETED 182 lines ...

1420: }
1421: }
1422:
1423: rc = mls_read_trusted(p, fp);
1424: if (rc)
GOTO -->
1425: goto bad;
1426:out:
END -->
1427: return rc;
1428:bad:
1429: policydb_destroy(p);
1430: goto out;
---------------------------------------------------------

[FILE: 2.6.0-test5/security/selinux/ss/policydb.c] [FUNC: policydb_read]
[LINES: 1334-1427]
[VAR: newgenfs]
1329: }
1330: nel = le32_to_cpu(buf[0]);
1331: genfs_p = NULL;
1332: rc = -EINVAL;
1333: for (i = 0; i < nel; i++) {
START -->
1334: newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL);
1335: if (!newgenfs) {
1336: rc = -ENOMEM;
1337: goto bad;
1338: }

1339:		memset(newgenfs, 0, sizeof(*newgenfs));
        ... DELETED 5 lines ...

1345: if (!buf)
1346: goto bad;
1347: newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL);
1348: if (!newgenfs->fstype) {
1349: rc = -ENOMEM;
GOTO -->
1350: goto bad;
1351: }
1352: memcpy(newgenfs->fstype, buf, len);
1353: newgenfs->fstype[len] = 0;
1354: for (genfs_p = NULL, genfs = p->genfs; genfs;
1355: genfs_p = genfs, genfs = genfs->next) {
1356: if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
1357: printk(KERN_ERR "security: dup genfs "
1358: "fstype %s\n", newgenfs->fstype);
GOTO -->
1359: goto bad;
1360: }
1361: if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
1362: break;
1363: }

1364:		newgenfs->next = genfs;
        ... DELETED 57 lines ...

1422:
1423: rc = mls_read_trusted(p, fp);
1424: if (rc)
1425: goto bad;
1426:out:
END -->
1427: return rc;
1428:bad:
1429: policydb_destroy(p);
1430: goto out;
---------------------------------------------------------

[FILE: 2.6.0-test5/security/selinux/ss/policydb.c] [FUNC: policydb_read]
[LINES: 1374-1427]
[VAR: newc]
1369: buf = next_entry(fp, sizeof(u32));
1370: if (!buf)
1371: goto bad;
1372: nel2 = le32_to_cpu(buf[0]);
1373: for (j = 0; j < nel2; j++) {
START -->
1374: newc = kmalloc(sizeof(*newc), GFP_KERNEL);
1375: if (!newc) {
1376: rc = -ENOMEM;
1377: goto bad;
1378: }

1379:			memset(newc, 0, sizeof(*newc));
        ... DELETED 14 lines ...

1394: buf = next_entry(fp, sizeof(u32));
1395: if (!buf)
1396: goto bad;
1397: newc->v.sclass = le32_to_cpu(buf[0]);
1398: if (context_read_and_validate(&newc->context[0], p, fp))
GOTO -->
1399: goto bad;
1400: for (l = NULL, c = newgenfs->head; c;
1401: l = c, c = c->next) {
1402: if (!strcmp(newc->u.name, c->u.name) &&
1403: (!c->v.sclass || !newc->v.sclass ||
1404: newc->v.sclass == c->v.sclass)) {
1405: printk(KERN_ERR "security: dup genfs "
1406: "entry (%s,%s)\n",
1407: newgenfs->fstype, c->u.name);
GOTO -->
1408: goto bad;
1409: }
1410: len = strlen(newc->u.name);
1411: len2 = strlen(c->u.name);
1412: if (len > len2)

1413:					break;
        ... DELETED 8 lines ...

1422:
1423: rc = mls_read_trusted(p, fp);
1424: if (rc)
1425: goto bad;
1426:out:
END -->
1427: return rc;
1428:bad:
1429: policydb_destroy(p);
1430: goto out;
---------------------------------------------------------

[FILE: 2.6.0-test5/security/selinux/ss/policydb.c] [FUNC: class_read]
[LINES: 759-851]
[VAR: c]
754: }
755:
756: lc = NULL;
757: rc = -EINVAL;
758: for (i = 0; i < ncons; i++) {
START -->
759: c = kmalloc(sizeof(*c), GFP_KERNEL);
760: if (!c) {
761: rc = -ENOMEM;
762: goto bad;
763: }

 764:		memset(c, 0, sizeof(*c));
        ... DELETED 64 lines ...

829: c->expr = e;
830: }
831: le = e;
832: }
833: if (depth != 0)
GOTO -->
834: goto bad;
835: if (lc) {
836: lc->next = c;
837: } else {
838: cladatum->constraints = c;
839: }

        ... DELETED 6 lines ...

846:
847: rc = hashtab_insert(h, key, cladatum);
848: if (rc)
849: goto bad;
850:out:
END -->
851: return rc;
852:bad:
853: class_destroy(key, cladatum, NULL);
854: goto out;
855:}
856:
---------------------------------------------------------

[FILE: 2.6.0-test5/sound/oss/emu10k1/midi.c]
[FUNC: emu10k1_seq_midi_open]
[LINES: 498-514]
[VAR: midi_dev]
493: if (card->open_mode) /* card is opened native */
494: return -EBUSY;
495:
496: DPF(2, "emu10k1_seq_midi_open()\n");
497:
START -->
498: if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
499: return -EINVAL;
500:
501: midi_dev->card = card;
502: midi_dev->mistate = MIDIIN_STATE_STOPPED;

 503:	init_waitqueue_head(&midi_dev->oWait);
        ... DELETED 5 lines ...

509:
510: dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
511:
512: if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) {
513: ERROR();
END -->
514: return -ENODEV;
515: }
516:
517: card->seq_mididev = midi_dev;
518:
519: return 0;
---------------------------------------------------------

[FILE: 2.6.0-test5/sound/oss/ymfpci.c]
[FUNC: ymf_probe_one]
[LINES: 2530-2641]
[VAR: codec]
2525: printk(KERN_ERR "ymfpci: pci_enable_device failed\n");
2526: return err;
2527: }
2528: base = pci_resource_start(pcidev, 0);
2529:
START -->
2530: if ((codec = kmalloc(sizeof(ymfpci_t), GFP_KERNEL)) == NULL) {
2531: printk(KERN_ERR "ymfpci: no core\n");
2532: return -ENOMEM;
2533: }
2534: memset(codec, 0, sizeof(*codec));
2535:

        ... DELETED 11 lines ...

2547: goto out_free;
2548: }
2549:
2550: if ((codec->reg_area_virt = ioremap(base, 0x8000)) == NULL) {
2551: printk(KERN_ERR "ymfpci: unable to map registers\n");
GOTO -->
2552: goto out_release_region;
2553: }
2554:
2555: pci_set_master(pcidev);
2556:
2557: printk(KERN_INFO "ymfpci: %s at 0x%lx IRQ %d\n",

        ... DELETED 78 lines ...

2636: out_release_region:
2637: release_mem_region(pci_resource_start(pcidev, 0), 0x8000);
2638: out_free:
2639: if (codec->ac97_codec[0])
2640: ac97_release_codec(codec->ac97_codec[0]);
END -->
2641: return -ENODEV;
2642:}
2643:
2644:static void __devexit ymf_remove_one(struct pci_dev *pcidev) 2645:{
2646: __u16 ctrl;
---------------------------------------------------------

#1 lore raw
Quoted 11 lines · On Monday September 15, [email protected] wrote:

Hi All,

I'm with the Stanford Meta-level Compilation research group, and I have a set of memory leaks on error paths for the 2.6.0-test5 kernel. (I also have error reports for 2.4.18 and a couple other kernels if anyone is interested).

There may be one or more "GOTO -->" markers showing the different paths of execution that can occur between where the memory is allocated and where the function returns.

Quoted 5 lines

My checker identifies error paths with a learning algorithm on features surrounding goto and return statements. I'd greatly appreciate any comments or confirmation on these bugs.

Thanks!

The nfsd/nfsctl.c one isn't actually a bug (though I had to think about it a bit to be sure).

One of the "... DETELED 4 lines ..." is

		file->private_data = ar;

which takes a copy of "ar" into a structure that has a lifetime greater than the function.
So when the "return -EFAULT" happends (at END -->), at is stored in file->private_data, and a subsequent call to TA_release will free that memory.

NeilBrown

Quoted 30 lines

[FILE: 2.6.0-test5/fs/nfsd/nfsctl.c]
[FUNC: TA_write]
[LINES: 105-120]
[VAR: ar]
100: if (file->private_data)
101: return -EINVAL; /* only one write allowed per open */
102: if (size > PAGE_SIZE - sizeof(struct argresp))
103: return -EFBIG;
104:
START -->
105: ar = kmalloc(PAGE_SIZE, GFP_KERNEL);
106: if (!ar)
107: return -ENOMEM;
108: ar->size = 0;
109: down(&file->f_dentry->d_inode->i_sem);
110: if (file->private_data)

        ... DELETED 4 lines ...

115: if (rv) {
116: kfree(ar);
117: return rv;
118: }
119: if (copy_from_user(ar->data, buf, size))
END -->
120: return -EFAULT;
121:
122: rv = write_op[ino](file, ar->data, size);
123: if (rv>0) {
124: ar->size = rv;
125: rv = size;

#2 lore raw
In reply to David Yu Chen
Quoted 18 lines · David Yu Chen

[FILE: 2.6.0-test5/drivers/mtd/chips/cfi_cmdset_0020.c] [FUNC: cfi_staa_setup]
[LINES: 191-211]
[VAR: mtd]
186: struct mtd_info *mtd;
187: unsigned long offset = 0;
188: int i,j;
189: unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
190:
START -->
191: mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
192: //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
193:
194: if (!mtd) {
195: printk(KERN_ERR "Failed to allocate memory for MTD device\n");

 196:		kfree(cfi->cmdset_priv);
        ... DELETED 9 lines ...
Quoted 12 lines

206: mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
207: * mtd->numeraseregions, GFP_KERNEL);
208: if (!mtd->eraseregions) {
209: printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
210: kfree(cfi->cmdset_priv);
END -->
211: return NULL;
212: }
213:
214: for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
215: unsigned long ernum, ersize;
216: ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;

Valid.

Quoted 17 lines

[FILE: 2.6.0-test5/drivers/mtd/chips/cfi_cmdset_0020.c] [FUNC: cfi_staa_setup]
[LINES: 191-235]
[VAR: mtd]
186: struct mtd_info *mtd;
187: unsigned long offset = 0;
188: int i,j;
189: unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
190:
START -->
191: mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
192: //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
193:
194: if (!mtd) {
195: printk(KERN_ERR "Failed to allocate memory for MTD device\n");

 196:		kfree(cfi->cmdset_priv);
        ... DELETED 33 lines ...
Quoted 12 lines

230: if (offset != devsize) {
231: /* Argh */
232: printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
233: kfree(mtd->eraseregions);
234: kfree(cfi->cmdset_priv);
END -->
235: return NULL;
236: }
237:
238: for (i=0; i<mtd->numeraseregions;i++){
239: printk(KERN_DEBUG "%d: offset=0x%x,size=0x%x,blocks=%d\n",
240: i,mtd->eraseregions[i].offset,

Also valid.

Quoted 12 lines

looks like checking for mtdblks instead of mtdblk
[FILE: 2.6.0-test5/drivers/mtd/mtdblock.c]
[FUNC: mtdblock_open]
[LINES: 277-279]
[VAR: mtdblk]
272: mtdblks[dev]->count++;
273: return 0;
274: }
275:
276: /* OK, it's not open. Create cache info for it */
START -->
277: mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);

Quoted 8 lines

278: if (!mtdblks)
END -->
279: return -ENOMEM;
280:
281: memset(mtdblk, 0, sizeof(*mtdblk));
282: mtdblk->count = 1;
283: mtdblk->mtd = mtd;
284:

Invalid. This is quite an obvious false positive, at least if your algorithm checks for possible value ranges.

Quoted 20 lines

[FILE: 2.6.0-test5/fs/jffs2/scan.c]
[FUNC: jffs2_scan_medium]
[LINES: 98-109]
[VAR: flashbuf]
93: buf_size = c->sector_size;
94: else
95: buf_size = PAGE_SIZE;
96:
97: D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size));
START -->
98: flashbuf = kmalloc(buf_size, GFP_KERNEL);
99: if (!flashbuf)
100: return -ENOMEM;
101: }
102:
103: for (i=0; i<c->nr_blocks; i++) {
104: struct jffs2_eraseblock *jeb = &c->blocks[i];
105:
106: ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size);
107:

Quoted 8 lines

108: if (ret < 0)
END -->
109: return ret;
110:
111: ACCT_PARANOIA_CHECK(jeb);
112:
113: /* Now decide which list to put it on */
114: switch(ret) {

Valid. And not trivial to fix.

Quoted 17 lines

[FILE: 2.6.0-test5/fs/jffs2/scan.c]
[FUNC: jffs2_scan_medium]
[LINES: 98-233]
[VAR: flashbuf]
93: buf_size = c->sector_size;
94: else
95: buf_size = PAGE_SIZE;
96:
97: D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size));
START -->
98: flashbuf = kmalloc(buf_size, GFP_KERNEL);
99: if (!flashbuf)
100: return -ENOMEM;
101: }
102:

 103:	for (i=0; i<c->nr_blocks; i++) {
        ... DELETED 124 lines ...
Quoted 12 lines

228: }
229: if (c->nr_erasing_blocks) {
230: if ( !c->used_size && ((empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) {
231: printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
232: printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",empty_blocks,bad_blocks,c->nr_blocks);
END -->
233: return -EIO;
234: }
235: jffs2_erase_pending_trigger(c);
236: }
237: if (buf_size)
238: kfree(flashbuf);

Same one, basically.

Jörn

Signature · 2 lines
Geld macht nicht glücklich.
Glück macht nicht satt.
#3 lore raw

PATCH 1/1 fix memleak in fs/jffs2/scan.c (was: re: [CHECKER] 32 Memory Leaks on Error Paths)

Quoted 30 lines · Jörn Engel
Quoted 21 lines

[FILE: 2.6.0-test5/fs/jffs2/scan.c]
[FUNC: jffs2_scan_medium]
[LINES: 98-109]
[VAR: flashbuf]
93: buf_size = c->sector_size;
94: else
95: buf_size = PAGE_SIZE;
96:
97: D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size));
START -->
98: flashbuf = kmalloc(buf_size, GFP_KERNEL);
99: if (!flashbuf)
100: return -ENOMEM;
101: }
102:
103: for (i=0; i<c->nr_blocks; i++) {
104: struct jffs2_eraseblock *jeb = &c->blocks[i];
105:
106: ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size);
107:

Quoted 8 lines

108: if (ret < 0)
END -->
109: return ret;
110:
111: ACCT_PARANOIA_CHECK(jeb);
112:
113: /* Now decide which list to put it on */
114: switch(ret) {

Quoted 1 line

Valid. And not trivial to fix.

But at least trivial to band-aid around it. This doesn't make the function any nicer, but it should get rid of the leaks.

David, consider this to be public domain. :)

Jörn

Signature · 36 lines
Mundie uses a textbook tactic of manipulation: start with some
reasonable talk, and lead the audience to an unreasonable conclusion.
-- Bruce Perens

--- linux-2.6.0-test3/fs/jffs2/scan.c~jffs2_memleak	2003-07-05 23:59:33.000000000 +0200
+++ linux-2.6.0-test3/fs/jffs2/scan.c	2003-09-16 09:16:30.000000000 +0200
@@ -106,7 +106,7 @@
 		ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size);
 
 		if (ret < 0)
-			return ret;
+			goto out;
 
 		ACCT_PARANOIA_CHECK(jeb);
 
@@ -230,7 +230,8 @@
 		if ( !c->used_size && ((empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) {
 			printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
 			printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",empty_blocks,bad_blocks,c->nr_blocks);
-			return -EIO;
+			ret = -EIO;
+			goto out;
 		}
 		jffs2_erase_pending_trigger(c);
 	}
@@ -241,6 +242,10 @@
 		c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size);
 #endif
 	return 0;
+out:
+	if (buf_size)
+		kfree(flashbuf);
+	return ret;
 }
 
 static int jffs2_fill_scan_buf (struct jffs2_sb_info *c, unsigned char *buf,
#4 lore raw
In reply to Jörn Engel
Quoted 32 lines · Jörn Engel
Quoted 18 lines · David Yu Chen

[FILE: 2.6.0-test5/drivers/mtd/chips/cfi_cmdset_0020.c] [FUNC: cfi_staa_setup]
[LINES: 191-211]
[VAR: mtd]
186: struct mtd_info *mtd;
187: unsigned long offset = 0;
188: int i,j;
189: unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
190:
START -->
191: mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
192: //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
193:
194: if (!mtd) {
195: printk(KERN_ERR "Failed to allocate memory for MTD device\n");

 196:		kfree(cfi->cmdset_priv);
        ... DELETED 9 lines ...
Quoted 12 lines

206: mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
207: * mtd->numeraseregions, GFP_KERNEL);
208: if (!mtd->eraseregions) {
209: printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
210: kfree(cfi->cmdset_priv);
END -->
211: return NULL;
212: }
213:
214: for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
215: unsigned long ernum, ersize;
216: ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;

Quoted 1 line

Valid.

This should be fixed by finally taking the time and merging the command sets 0001 and 0020. Maybe someone who cares will come up with a patch.

Jörn

Signature · 2 lines
Simplicity is prerequisite for reliability.
-- Edsger W. Dijkstra
#5 lore raw
In reply to Jörn Engel
Quoted 23 lines · Jörn Engel
Quoted 13 lines · David Yu Chen

looks like checking for mtdblks instead of mtdblk
[FILE: 2.6.0-test5/drivers/mtd/mtdblock.c]
[FUNC: mtdblock_open]
[LINES: 277-279]
[VAR: mtdblk]
272: mtdblks[dev]->count++;
273: return 0;
274: }
275:
276: /* OK, it's not open. Create cache info for it */
START -->
277: mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);

Quoted 8 lines

278: if (!mtdblks)
END -->
279: return -ENOMEM;
280:
281: memset(mtdblk, 0, sizeof(*mtdblk));
282: mtdblk->count = 1;
283: mtdblk->mtd = mtd;
284:

Quoted 2 lines

Invalid. This is quite an obvious false positive, at least if your algorithm checks for possible value ranges.

Actually, it *is* valid, as Wade pointed out to me.

David, please apply!

Jörn

Signature · 15 lines
Mundie uses a textbook tactic of manipulation: start with some
reasonable talk, and lead the audience to an unreasonable conclusion.
-- Bruce Perens

--- linux-2.6.0-test3/drivers/mtd/mtdblock.c~mtdblock_leak	2003-07-05 23:59:30.000000000 +0200
+++ linux-2.6.0-test3/drivers/mtd/mtdblock.c	2003-09-16 10:47:58.000000000 +0200
@@ -275,7 +275,7 @@
 	
 	/* OK, it's not open. Create cache info for it */
 	mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
-	if (!mtdblks)
+	if (!mtdblk)
 		return -ENOMEM;
 
 	memset(mtdblk, 0, sizeof(*mtdblk));
#6 lore raw
In reply to Jörn Engel
Quoted 11 lines
Quoted 7 lines

276: /* OK, it's not open. Create cache info for it */
START -->
277: mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
278: if (!mtdblks)
END -->
279: return -ENOMEM;

Invalid. This is quite an obvious false positive, at least if your algorithm checks for possible value ranges.

Wait... one is "mtdblk", and the other is "mtdblks". One has an extra 's' on it. Unless there is some kind of aliasing going on, they would appear to be different variables. Naturally, I didn't check the original code, so I could be full of it. :)

#7 lore raw
Quoted 10 lines · Timothy Miller
Quoted 10 lines
Quoted 7 lines

276: /* OK, it's not open. Create cache info for it */
START -->
277: mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
278: if (!mtdblks)
END -->
279: return -ENOMEM;

Quoted 6 lines
Quoted 2 lines

Invalid. This is quite an obvious false positive, at least if your algorithm checks for possible value ranges.

Wait... one is "mtdblk", and the other is "mtdblks". One has an extra 's' on it. Unless there is some kind of aliasing going on, they would appear to be different variables. Naturally, I didn't check the original code, so I could be full of it. :)

This has been resolved, see Jorn's other mail.

#8 lore raw
In reply to Timothy Miller
Quoted 10 lines · Timothy Miller
Quoted 10 lines
Quoted 7 lines

276: /* OK, it's not open. Create cache info for it */
START -->
277: mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
278: if (!mtdblks)
END -->
279: return -ENOMEM;

Quoted 5 lines
Quoted 2 lines

Invalid. This is quite an obvious false positive, at least if your algorithm checks for possible value ranges.

Wait... one is "mtdblk", and the other is "mtdblks". One has an extra 's' on it. Unless there is some kind of aliasing going on, they would appear to be different variables. Naturally, I didn't check the original code, so I could be full of it. :)

Yes its a bug from glancing at the source code.

#9 lore raw
In reply to Timothy Miller
Quoted 9 lines · Timothy Miller
Quoted 9 lines
Quoted 7 lines

276: /* OK, it's not open. Create cache info for it */
START -->
277: mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
278: if (!mtdblks)
END -->
279: return -ENOMEM;

Quoted 7 lines
Quoted 2 lines

Invalid. This is quite an obvious false positive, at least if your algorithm checks for possible value ranges.

Wait... one is "mtdblk", and the other is "mtdblks". One has an extra 's' on it. Unless there is some kind of aliasing going on, they would appear to be different variables. Naturally, I didn't check the original code, so I could be full of it. :)

On the other hand, even if the report was invalid (which another posting says isn't the case), this code is just *begging* for somebody to "fix the typo", due to how much the kernel uses

	foo = function(..)
	if (!foo)

Yeah, they're different variables - but we alloc mktblk and then return -ENOMEM if the OTHER variable is null?? ;)

#10 lore raw
In reply to David Yu Chen
Quoted 20 lines · David Yu Chen

Hi All,

I'm with the Stanford Meta-level Compilation research group, and I have a set of memory leaks on error paths for the 2.6.0-test5 kernel. (I also have error reports for 2.4.18 and a couple other kernels if anyone is interested).

There may be one or more "GOTO -->" markers showing the different paths of execution that can occur between where the memory is allocated and where the function returns.

My checker identifies error paths with a learning algorithm on features surrounding goto and return statements. I'd greatly appreciate any comments or confirmation on these bugs.

Thanks!

---
David Yu Chen
http://www.stanford.edu/~dychen/

[snip]

Quoted 18 lines

[FILE: 2.6.0-test5/drivers/char/vt_ioctl.c]
[FUNC: do_kdsk_ioctl]
[LINES: 133-150]
[VAR: key_map]
128:
129: if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
130: !capable(CAP_SYS_RESOURCE))
131: return -EPERM;
132:
START -->
133: key_map = (ushort *) kmalloc(sizeof(plain_map),
134: GFP_KERNEL);
135: if (!key_map)
136: return -ENOMEM;
137: key_maps[s] = key_map;

 138:			key_map[0] = U(K_ALLOCATED);
        ... DELETED 6 lines ...
Quoted 14 lines

145: break; /* nothing to do */
146: /*
147: * Attention Key.
148: */
149: if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
END -->
150: return -EPERM;
151: key_map[i] = U(v);
152: if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
153: compute_shiftstate();
154: break;
155: }
---------------------------------------------------------

Is the attached correct?

drivers/char/vt_ioctl.c +3 -1
@@ -146,8 +146,10 @@
 		/*
 		 * Attention Key.
 		 */
-		if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
+		if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) {
+			kfree(key_map);
 			return -EPERM;
+		}
 		key_map[i] = U(v);
 		if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
 			compute_shiftstate();
#11 lore raw
Quoted 17 lines · Wade
Quoted 16 lines · David Yu Chen

[FILE: 2.6.0-test5/drivers/char/vt_ioctl.c]
[FUNC: do_kdsk_ioctl]
[LINES: 133-150]
[VAR: key_map]
128:
129: if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
130: !capable(CAP_SYS_RESOURCE))
131: return -EPERM;
132:
START -->
133: key_map = (ushort *) kmalloc(sizeof(plain_map),
134: GFP_KERNEL);
135: if (!key_map)
136: return -ENOMEM;
137: key_maps[s] = key_map;

                                ^^^^^^^^^^^^^^^^^^^^^^
Quoted 17 lines
Quoted 16 lines
138:			key_map[0] = U(K_ALLOCATED);
       ... DELETED 6 lines ...

145: break; /* nothing to do */
146: /*
147: * Attention Key.
148: */
149: if (((ov == K_SAK) || (v == K_SAK)) &&
!capable(CAP_SYS_ADMIN))
END -->
150: return -EPERM;
151: key_map[i] = U(v);
152: if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
153: compute_shiftstate();
154: break;
155: }
---------------------------------------------------------

Quoted 1 line

Is the attached correct?

Looks like there is no leak after all, as long as key_maps is dealt with properly sometime. But I'm not familiar enough with the code to judge that.

Quoted 4 lines
drivers/char/vt_ioctl.c +0 -0
@@ -146,8 +146,10 @@
 		/*

drivers/char/vt_ioctl.c line 155

Quoted 10 lines
drivers/char/vt_ioctl.c +3 -1
 		 * Attention Key.
 		 */
-		if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
+		if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) {
+			kfree(key_map);
 			return -EPERM;
+		}
 		key_map[i] = U(v);
 		if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
 			compute_shiftstate();

Jörn

Signature · 4 lines
Data dominates. If you've chosen the right data structures and organized
things well, the algorithms will almost always be self-evident. Data
structures, not algorithms, are central to programming.
-- Rob Pike
#12 lore raw
In reply to Wade
Quoted 1 line · Wade

Is the attached correct?

No, it frees memory that is still in use, and will oops the kernel.

Quoted 1 line

--- linux-2.6.0-test5.old/drivers/char/vt_ioctl.c 2003-08-23 07:57:57.000000000 +0800

There was no bug to start with, so please do not fix anything.

#13 lore raw
In reply to David Yu Chen
Quoted 20 lines · David Yu Chen

[FILE: 2.6.0-test5/net/ipv4/igmp.c]
[FUNC: igmpv3_newpack]
[LINES: 274-284]
[VAR: skb]
269: struct sk_buff *skb;
270: struct rtable *rt;
271: struct iphdr *pip;
272: struct igmpv3_report *pig;
273:
START -->
274: skb = alloc_skb(size + dev->hard_header_len + 15, GFP_ATOMIC);
275: if (skb == NULL)
276: return 0;
277:
278: {
279: struct flowi fl = { .oif = dev->ifindex,

 280:				    .nl_u = { .ip4_u = {
 281:				    .daddr = IGMPV3_ALL_MCR } },
 282:				    .proto = IPPROTO_IGMP };
Quoted 8 lines

283: if (ip_route_output_key(&rt, &fl))
END -->
284: return 0;
285: }
286: if (rt->rt_src == 0) {
287: ip_rt_put(rt);
288: return 0;
289: }

Looks valid. And since skb isn't really needed until after these returns, moving four lines down a bit fixes the problem.

Davem, is this correct?

Jörn

Signature · 37 lines
Data dominates. If you've chosen the right data structures and organized
things well, the algorithms will almost always be self-evident. Data
structures, not algorithms, are central to programming.
-- Rob Pike

--- linux-2.6.0-test3/net/ipv4/igmp.c~igmp_memleak	2003-07-15 23:09:02.000000000 +0200
+++ linux-2.6.0-test3/net/ipv4/igmp.c	2003-09-16 10:29:47.000000000 +0200
@@ -70,6 +70,8 @@
  *		Alexey Kuznetsov:	Accordance to igmp-v2-06 draft.
  *		David L Stevens:	IGMPv3 support, with help from
  *					Vinay Kulkarni
+ *		Jörn Engel:		Fix memleak in igmpv3_newpack, reported
+ *					by David Yu Chen (stanford checker)
  */
 
 
@@ -271,10 +273,6 @@
 	struct iphdr *pip;
 	struct igmpv3_report *pig;
 
-	skb = alloc_skb(size + dev->hard_header_len + 15, GFP_ATOMIC);
-	if (skb == NULL)
-		return 0;
-
 	{
 		struct flowi fl = { .oif = dev->ifindex,
 				    .nl_u = { .ip4_u = {
@@ -288,6 +286,10 @@
 		return 0;
 	}
 
+	skb = alloc_skb(size + dev->hard_header_len + 15, GFP_ATOMIC);
+	if (skb == NULL)
+		return 0;
+
 	skb->dst = &rt->u.dst;
 	skb->dev = dev;
#14 lore raw
Quoted 4 lines · On Tue, 16 Sep 2003 11:07:48 +0200 Jörn Engel <[email protected]>…

Looks valid. And since skb isn't really needed until after these returns, moving four lines down a bit fixes the problem.

Davem, is this correct?

Nope, now you're leaking the route instead of the SKB :-)

I'll put the correct fix in.

#15 lore raw

PATCH 1/1 bttv-risc.c (was: Re: [CHECKER] 32 Memory Leaks on Error Paths)

In reply to David Yu Chen
Quoted 1 line · David Yu Chen

Hi All,

[snip]

Quoted 21 lines

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

[FILE: 2.6.0-test5/drivers/media/video/bttv-risc.c] [FUNC: bttv_risc_overlay]
[LINES: 214-223]
[VAR: skips]
209: struct btcx_skiplist *skips;
210: u32 *rp,ri,ra;
211: u32 addr;
212:
213: /* skip list for window clipping */
START -->
214: if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
215: return -ENOMEM;
216:
217: /* estimate risc mem: worst case is (clip+1) * lines instructions
218: + sync + jump (all 2 dwords) */
219: instructions = (ov->nclips + 1) *
220: ((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height);
221: instructions += 2;
222: if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)

Quoted 9 lines

END -->
223: return rc;
224:
225: /* sync instruction */
226: rp = risc->cpu;
227: *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
228: *(rp++) = cpu_to_le32(0);
---------------------------------------------------------

Correct?

drivers/media/video/bttv-risc.c +3 -1
@@ -219,8 +219,10 @@
 	instructions  = (ov->nclips + 1) *
 		((skip_even || skip_odd) ? ov->w.height>>1 :  ov->w.height);
 	instructions += 2;
-	if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)
+	if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0) {
+		kfree(skips);
 		return rc;
+	}
 
 	/* sync instruction */
 	rp = risc->cpu;
#16 lore raw

PATCH 1/1 fix memleak in emu10k1/midi.c (was: Re: [CHECKER] 32 Memory Leaks on Error Paths)

In reply to David Yu Chen
Quoted 2 lines · David Yu Chen

Hi All,

[snip]

Quoted 17 lines

[FILE: 2.6.0-test5/sound/oss/emu10k1/midi.c]
[FUNC: emu10k1_seq_midi_open]
[LINES: 498-514]
[VAR: midi_dev]
493: if (card->open_mode) /* card is opened native */
494: return -EBUSY;
495:
496: DPF(2, "emu10k1_seq_midi_open()\n");
497:
START -->
498: if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
499: return -EINVAL;
500:
501: midi_dev->card = card;
502: midi_dev->mistate = MIDIIN_STATE_STOPPED;

 503:	init_waitqueue_head(&midi_dev->oWait);
        ... DELETED 5 lines ...
Quoted 13 lines

509:
510: dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
511:
512: if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) {
513: ERROR();
END -->
514: return -ENODEV;
515: }
516:
517: card->seq_mididev = midi_dev;
518:
519: return 0;
---------------------------------------------------------

Can I ask again why the Checker is not released? I know that you don't have to release the source since you are not distributing it, but why not? AFAICS this would be a great asset to Open Source projects in general, not just the kernel.

(Patch correct? looked obvious)

sound/oss/emu10k1/midi.c +1 -0
@@ -511,6 +511,7 @@
 
 	if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) {
 		ERROR();
+		kfree(midi_dev);
 		return -ENODEV;
 	}
 
#17 lore raw
In reply to David Yu Chen
Quoted 2 lines · David Yu Chen

I'm with the Stanford Meta-level Compilation research group, and I have a set of memory leaks on error paths for the 2.6.0-test5 kernel.

There is no memory leak in the below:

Quoted 19 lines

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

[FILE: 2.6.0-test5/drivers/char/vt_ioctl.c]
[FUNC: do_kdsk_ioctl]
[LINES: 133-150]
[VAR: key_map]
128:
129: if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
130: !capable(CAP_SYS_RESOURCE))
131: return -EPERM;
132:
START -->
133: key_map = (ushort *) kmalloc(sizeof(plain_map),
134: GFP_KERNEL);
135: if (!key_map)
136: return -ENOMEM;
137: key_maps[s] = key_map;

 138:			key_map[0] = U(K_ALLOCATED);
        ... DELETED 6 lines ...
Quoted 12 lines

145: break; /* nothing to do */
146: /*
147: * Attention Key.
148: */
149: if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
END -->
150: return -EPERM;
151: key_map[i] = U(v);
152: if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
153: compute_shiftstate();
154: break;
155: }

Explanation:
The user may have up to 256 keymaps, namely the plain map and various maps for (combinations of) modifier keys.
In order to save memory, most of these keymaps will not be allocated. If one sets an entry on a keymap, then first the keymap itself is allocated in case it did not exist yet. Then the entry is filled, assuming one has permission.
On the error path the memory is not lost: the pointer was stored in the array key_maps[], so also am automatic checker could see that. (And indeed, it is also possible to deallocate keymaps.)

Andries

#18 lore raw
In reply to David Yu Chen
Quoted 9 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/security/selinux/selinuxfs.c]
START -->
253: ar = kmalloc(PAGE_SIZE, GFP_KERNEL);
254: if (!ar)
255: return -ENOMEM;
256: memset(ar, 0, PAGE_SIZE); /* clear buffer, particularly last byte */
257: ar->size = 0;

 258:	down(&file->f_dentry->d_inode->i_sem);
        ... DELETED 5 lines ...

A reference to ar is stored away for kfree() on ->release():

		file->private_data = ar;
Quoted 3 lines

268: if (copy_from_user(ar->data, buf, size))
END -->
269: return -EFAULT;

So, this will be freed when the file is closed. I don't think it's a bug.

thanks,
-chris

Signature · 1 line
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net
#19 lore raw
In reply to David Yu Chen
Quoted 11 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/security/selinux/ss/mls.c]
[VAR: r]
538: goto out;
539: }
540: nel = le32_to_cpu(buf[0]);
541: l = NULL;
542: for (i = 0; i < nel; i++) {
START -->
543: r = kmalloc(sizeof(*r), GFP_ATOMIC);
544: if (!r) {
545: rc = -ENOMEM;

Quoted 8 lines

546: goto out;
547: }
548: memset(r, 0, sizeof(*r));
549:
550: rc = mls_read_range_helper(&r->range, fp);
551: if (rc)
GOTO -->
552: goto out;

Yes, this looks like a bug. Stephen, does this fix look ok? thanks
-chris

Signature · 18 lines
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net


===== security/selinux/ss/mls.c 1.1 vs edited =====
--- 1.1/security/selinux/ss/mls.c	Thu Jul 17 02:38:01 2003
+++ edited/security/selinux/ss/mls.c	Fri Sep 19 13:56:50 2003
@@ -548,8 +548,10 @@
 		memset(r, 0, sizeof(*r));
 
 		rc = mls_read_range_helper(&r->range, fp);
-		if (rc)
+		if (rc) {
+			kfree(r);
 			goto out;
+		}
 
 		if (l)
 			l->next = r;
#20 lore raw
In reply to David Yu Chen
Quoted 9 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/security/selinux/ss/policydb.c] START -->
1334: newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL);
1335: if (!newgenfs) {
1336: rc = -ENOMEM;
1337: goto bad;
1338: }

1339:		memset(newgenfs, 0, sizeof(*newgenfs));
        ... DELETED 5 lines ...

You missed one ;-)

1344 buf = next_entry(fp, len);
1345 if (!buf)
1346 goto bad;

Quoted 2 lines

GOTO -->
1350: goto bad;

Yes, this is a bug.

Quoted 4 lines

1357: printk(KERN_ERR "security: dup genfs "
1358: "fstype %s\n", newgenfs->fstype);
GOTO -->
1359: goto bad;

Yes, this is a bug. I'm not sure if CHECKER caught that it leaks two allocations here. Both newgenfs and newgenfs->fstype.

Quoted 8 lines

[FILE: 2.6.0-test5/security/selinux/ss/policydb.c] START -->
1374: newc = kmalloc(sizeof(*newc), GFP_KERNEL);
1375: if (!newc) {
1376: rc = -ENOMEM;
1377: goto bad;
1378: }
1379: memset(newc, 0, sizeof(*newc));

You missed some more. Not sure if this is meant to be comprensive or not...

1380 buf = next_entry(fp, sizeof(u32));
1381 if (!buf)
1382 goto bad;
*HERE*
1383 len = le32_to_cpu(buf[0]);
1384 buf = next_entry(fp, len);
1385 if (!buf)
1386 goto bad;
*HERE*
1387 newc->u.name = kmalloc(len + 1,GFP_KERNEL);
1388 if (!newc->u.name) {
1389 rc = -ENOMEM;
1390 goto bad;
*HERE*

Quoted 4 lines
        ... DELETED 14 lines ...

1394: buf = next_entry(fp, sizeof(u32));
1395: if (!buf)
1396: goto bad;

Again, not sure if you meant to capture both leakages here: newc and newc->u.name.

Quoted 4 lines

1397: newc->v.sclass = le32_to_cpu(buf[0]);
1398: if (context_read_and_validate(&newc->context[0], p, fp))
GOTO -->
1399: goto bad;

And both here.

Quoted 10 lines

1400: for (l = NULL, c = newgenfs->head; c;
1401: l = c, c = c->next) {
1402: if (!strcmp(newc->u.name, c->u.name) &&
1403: (!c->v.sclass || !newc->v.sclass ||
1404: newc->v.sclass == c->v.sclass)) {
1405: printk(KERN_ERR "security: dup genfs "
1406: "entry (%s,%s)\n",
1407: newgenfs->fstype, c->u.name);
GOTO -->
1408: goto bad;

And both here.

Patch below fixes the leaks in a brute force method. Stephen, look ok? I could see rearranging the code to ensure things are stored in the policydb earlier so they are all caught by policydb_destroy().

Quoted 8 lines

[FILE: 2.6.0-test5/security/selinux/ss/policydb.c] START -->
759: c = kmalloc(sizeof(*c), GFP_KERNEL);
760: if (!c) {
761: rc = -ENOMEM;
762: goto bad;
763: }
764: memset(c, 0, sizeof(*c));

You missed this one:
765 buf = next_entry(fp, sizeof(u32)*2);
766 if (!buf)
767 goto bad;
And this one:
774 if (!e) {
775 rc = -ENOMEM;
776 goto bad;
And this one:
780 if (!buf) {
781 kfree(e);
782 goto bad;
And this one:
790 if (depth < 0) {
791 kfree(e);
792 goto bad;
etc...

Quoted 7 lines
        ... DELETED 64 lines ...

829: c->expr = e;
830: }
831: le = e;
832: }
833: if (depth != 0)
GOTO -->

Yes, this is a bug. Stephen, the patch below fixes this, and adds a constraint_destroy() function to help cleanup when the constaint_node isn't yet attached to the class_datum but there may already be some constraint_expr's on the constraint_node.

thanks,
-chris

Signature · 210 lines
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net


===== security/selinux/ss/policydb.c 1.3 vs edited =====
--- 1.3/security/selinux/ss/policydb.c	Sun Aug 31 16:14:19 2003
+++ edited/security/selinux/ss/policydb.c	Fri Sep 19 15:59:02 2003
@@ -321,17 +321,11 @@
 	return 0;
 }
 
-static int class_destroy(void *key, void *datum, void *p)
+static void constraint_destroy(struct constraint_node *constraint)
 {
-	struct class_datum *cladatum;
-	struct constraint_node *constraint, *ctemp;
+	struct constraint_node *ctemp;
 	struct constraint_expr *e, *etmp;
 
-	kfree(key);
-	cladatum = datum;
-	hashtab_map(cladatum->permissions.table, perm_destroy, 0);
-	hashtab_destroy(cladatum->permissions.table);
-	constraint = cladatum->constraints;
 	while (constraint) {
 		e = constraint->expr;
 		while (e) {
@@ -344,6 +338,19 @@
 		constraint = constraint->next;
 		kfree(ctemp);
 	}
+}
+
+static int class_destroy(void *key, void *datum, void *p)
+{
+	struct class_datum *cladatum;
+	struct constraint_node *constraint;
+
+	kfree(key);
+	cladatum = datum;
+	hashtab_map(cladatum->permissions.table, perm_destroy, 0);
+	hashtab_destroy(cladatum->permissions.table);
+	constraint = cladatum->constraints;
+	constraint_destroy(constraint);
 	kfree(cladatum->comkey);
 	kfree(datum);
 	return 0;
@@ -763,8 +770,10 @@
 		}
 		memset(c, 0, sizeof(*c));
 		buf = next_entry(fp, sizeof(u32)*2);
-		if (!buf)
+		if (!buf) {
+			kfree(c);
 			goto bad;
+		}
 		c->permissions = le32_to_cpu(buf[0]);
 		nexpr = le32_to_cpu(buf[1]);
 		le = NULL;
@@ -773,11 +782,13 @@
 			e = kmalloc(sizeof(*e), GFP_KERNEL);
 			if (!e) {
 				rc = -ENOMEM;
+				constraint_destroy(c);
 				goto bad;
 			}
 			memset(e, 0, sizeof(*e));
 			buf = next_entry(fp, sizeof(u32)*3);
 			if (!buf) {
+				constraint_destroy(c);
 				kfree(e);
 				goto bad;
 			}
@@ -788,6 +799,7 @@
 			switch (e->expr_type) {
 			case CEXPR_NOT:
 				if (depth < 0) {
+					constraint_destroy(c);
 					kfree(e);
 					goto bad;
 				}
@@ -795,6 +807,7 @@
 			case CEXPR_AND:
 			case CEXPR_OR:
 				if (depth < 1) {
+					constraint_destroy(c);
 					kfree(e);
 					goto bad;
 				}
@@ -802,6 +815,7 @@
 				break;
 			case CEXPR_ATTR:
 				if (depth == (CEXPR_MAXDEPTH-1)) {
+					constraint_destroy(c);
 					kfree(e);
 					goto bad;
 				}
@@ -809,16 +823,19 @@
 				break;
 			case CEXPR_NAMES:
 				if (depth == (CEXPR_MAXDEPTH-1)) {
+					constraint_destroy(c);
 					kfree(e);
 					goto bad;
 				}
 				depth++;
 				if (ebitmap_read(&e->names, fp)) {
+					constraint_destroy(c);
 					kfree(e);
 					goto bad;
 				}
 				break;
 			default:
+				constraint_destroy(c);
 				kfree(e);
 				goto bad;
 				break;
@@ -830,8 +847,10 @@
 			}
 			le = e;
 		}
-		if (depth != 0)
+		if (depth != 0) {
+			constraint_destroy(c);
 			goto bad;
+		}
 		if (lc) {
 			lc->next = c;
 		} else {
@@ -1338,15 +1357,20 @@
 		}
 		memset(newgenfs, 0, sizeof(*newgenfs));
 		buf = next_entry(fp, sizeof(u32));
-		if (!buf)
+		if (!buf) {
+			kfree(newgenfs);
 			goto bad;
+		}
 		len = le32_to_cpu(buf[0]);
 		buf = next_entry(fp, len);
-		if (!buf)
+		if (!buf) {
+			kfree(newgenfs);
 			goto bad;
+		}
 		newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL);
 		if (!newgenfs->fstype) {
 			rc = -ENOMEM;
+			kfree(newgenfs);
 			goto bad;
 		}
 		memcpy(newgenfs->fstype, buf, len);
@@ -1356,6 +1380,8 @@
 			if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
 				printk(KERN_ERR "security:  dup genfs "
 				       "fstype %s\n", newgenfs->fstype);
+				kfree(newgenfs->fstype);
+				kfree(newgenfs);
 				goto bad;
 			}
 			if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
@@ -1378,25 +1404,36 @@
 			}
 			memset(newc, 0, sizeof(*newc));
 			buf = next_entry(fp, sizeof(u32));
-			if (!buf)
+			if (!buf) {
+				kfree(newc);
 				goto bad;
+			}
 			len = le32_to_cpu(buf[0]);
 			buf = next_entry(fp, len);
-			if (!buf)
+			if (!buf) {
+				kfree(newc);
 				goto bad;
+			}
 			newc->u.name = kmalloc(len + 1,GFP_KERNEL);
 			if (!newc->u.name) {
 				rc = -ENOMEM;
+				kfree(newc);
 				goto bad;
 			}
 			memcpy(newc->u.name, buf, len);
 			newc->u.name[len] = 0;
 			buf = next_entry(fp, sizeof(u32));
-			if (!buf)
+			if (!buf) {
+				kfree(newc->u.name);
+				kfree(newc);
 				goto bad;
+			}
 			newc->v.sclass = le32_to_cpu(buf[0]);
-			if (context_read_and_validate(&newc->context[0], p, fp))
+			if (context_read_and_validate(&newc->context[0], p, fp)){ 
+				kfree(newc->u.name);
+				kfree(newc);
 				goto bad;
+			}
 			for (l = NULL, c = newgenfs->head; c;
 			     l = c, c = c->next) {
 				if (!strcmp(newc->u.name, c->u.name) &&
@@ -1405,6 +1442,8 @@
 					printk(KERN_ERR "security:  dup genfs "
 					       "entry (%s,%s)\n",
 					       newgenfs->fstype, c->u.name);
+					kfree(newc->u.name);
+					kfree(newc);
 					goto bad;
 				}
 				len = strlen(newc->u.name);
#21 lore raw
Quoted 4 lines · Chris Wright

Yes, this is a bug. Stephen, the patch below fixes this, and adds a constraint_destroy() function to help cleanup when the constaint_node isn't yet attached to the class_datum but there may already be some constraint_expr's on the constraint_node.

Hi Chris,

Sorry for the duplicated effort, but I had already written up a patch prior to the hurricane, but didn't get it sent out. I believe that the patch below fixes the legitimate leaks in the SELinux code. In some cases, it rearranges the code (moving the allocation later to reduce the need for further cleanup or linking the object into a containing structure earlier so that the policydb_destroy will handle it upon any subsequent errors).

 security/selinux/ss/mls.c      |   13 ++++
 security/selinux/ss/policydb.c |  112 ++++++++++++++++++++---------------------
 2 files changed, 68 insertions(+), 57 deletions(-)

Index: linux-2.6/security/selinux/ss/mls.c
===================================================================
RCS file: /nfshome/pal/CVS/linux-2.6/security/selinux/ss/mls.c,v retrieving revision 1.16

security/selinux/ss/mls.c +11 -2
diff -u -r1.16 mls.c
@@ -548,8 +548,10 @@
 		memset(r, 0, sizeof(*r));
 
 		rc = mls_read_range_helper(&r->range, fp);
-		if (rc)
+		if (rc) {
+			kfree(r);
 			goto out;
+		}
 
 		if (l)
 			l->next = r;
@@ -581,10 +583,17 @@
 		goto out;
 	rc = ebitmap_read(&p->trustedwriters, fp);
 	if (rc)
-		goto out;
+		goto bad;
 	rc = ebitmap_read(&p->trustedobjects, fp);
+	if (rc)
+		goto bad2;
 out:
 	return rc;
+bad2:
+	ebitmap_destroy(&p->trustedwriters);
+bad:
+	ebitmap_destroy(&p->trustedreaders);
+	goto out;
 }
 
 int sens_index(void *key, void *datum, void *datap)

Index: linux-2.6/security/selinux/ss/policydb.c
===================================================================
RCS file: /nfshome/pal/CVS/linux-2.6/security/selinux/ss/policydb.c,v retrieving revision 1.24

security/selinux/ss/policydb.c +57 -55

234 lines not on this page · raw message

Signature · 2 lines
Stephen Smalley <[email protected]>
National Security Agency
#22 lore raw
Quoted 7 lines · * Stephen Smalley ([email protected]) wrote:

Sorry for the duplicated effort, but I had already written up a patch prior to the hurricane, but didn't get it sent out. I believe that the patch below fixes the legitimate leaks in the SELinux code. In some cases, it rearranges the code (moving the allocation later to reduce the need for further cleanup or linking the object into a containing structure earlier so that the policydb_destroy will handle it upon any subsequent errors).

No problem, your patch looks better anyway ;-)
-chris

Signature · 1 line
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net
#23 lore raw
In reply to David Yu Chen
Quoted 9 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/security/selinux/ss/policydb.c] START -->
1232: c = kmalloc(sizeof(*c), GFP_KERNEL);
1233: if (!c) {
1234: rc = -ENOMEM;
1235: goto bad;
1236: }

1237:			memset(c, 0, sizeof(*c));
        ... DELETED 182 lines ...

You missed a reference to the context is stored in the policydb:

			p->ocontexts[i] = c;
Quoted 4 lines

END -->
1427: return rc;
1428:bad:
1429: policydb_destroy(p);

The policydb is destroyed on error, which will free the context. I don't think this is a bug.

thanks,
-chris

Signature · 1 line
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net
#24 lore raw
In reply to David Yu Chen
Quoted 18 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/drivers/scsi/scsi_debug.c]
[FUNC: sdebug_add_adapter]
[LINES: 1612-1652]
[VAR: sdbg_devinfo]
1607: memset(sdbg_host, 0, sizeof(*sdbg_host));
1608: INIT_LIST_HEAD(&sdbg_host->dev_info_list);
1609:
1610: devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
1611: for (k = 0; k < devs_per_host; k++) {
START -->
1612: sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL);
1613: if (NULL == sdbg_devinfo) {
1614: printk(KERN_ERR "%s: out of memory at line %d\n",
1615: __FUNCTION__, __LINE__);
1616: error = -ENOMEM;
GOTO -->

1617:			goto clean1;
        ... DELETED 29 lines ...
Quoted 7 lines

1647: kfree(sdbg_devinfo);
1648: }
1649:
1650:clean1:
1651: kfree(sdbg_host);
END -->
1652: return error;

Yes, this could leak sdbg_devinfo structs. Patch below. James, look ok?

thanks,
-chris

===== drivers/scsi/scsi_debug.c 1.44 vs edited =====

drivers/scsi/scsi_debug.c +3 -4
@@ -1614,7 +1614,7 @@
                         printk(KERN_ERR "%s: out of memory at line %d\n",
                                __FUNCTION__, __LINE__);
                         error = -ENOMEM;
-			goto clean1;
+			goto clean;
                 }
                 memset(sdbg_devinfo, 0, sizeof(*sdbg_devinfo));
                 sdbg_devinfo->sdbg_host = sdbg_host;
@@ -1634,12 +1634,12 @@
         error = device_register(&sdbg_host->dev);
 
         if (error)
-		goto clean2;
+		goto clean;
 
 	++scsi_debug_add_host;
         return error;
 
-clean2:
+clean:
 	list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
 		sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
 					  dev_list);
@@ -1647,7 +1647,6 @@
 		kfree(sdbg_devinfo);
 	}
 
-clean1:
 	kfree(sdbg_host);
         return error;
 }
#25 lore raw
In reply to David Yu Chen
Quoted 5 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/drivers/scsi/NCR_Q720.c]
START -->
153: p = kmalloc(sizeof(*p), GFP_KERNEL);
154: if (!p)
155: return -ENOMEM;

<snip>

Quoted 4 lines

180: if(i != NCR_Q720_MCA_ID) {
181: printk(KERN_ERR "NCR_Q720, adapter failed to I/O map registers correctly at 0x%x(0x%x)\n", io_base, i);
END -->
182: return -ENODEV;

Yes, looks like a valid bug. Patch below. James, look ok? thanks,
-chris

===== drivers/scsi/NCR_Q720.c 1.4 vs edited =====

drivers/scsi/NCR_Q720.c +1 -1
@@ -179,7 +179,7 @@
 	i = inb(io_base) | (inb(io_base+1)<<8);
 	if(i != NCR_Q720_MCA_ID) {
 		printk(KERN_ERR "NCR_Q720, adapter failed to I/O map registers correctly at 0x%x(0x%x)\n", io_base, i);
-		return -ENODEV;
+		goto out_free;
 	}
 
 	/* Phase II, find the ram base and memory map the board register */
#26 lore raw
In reply to David Yu Chen
Quoted 15 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/drivers/telephony/ixj_pcmcia.c] [FUNC: ixj_attach]
[LINES: 53-64]
[VAR: link]
48: client_reg_t client_reg;
49: dev_link_t *link;
50: int ret;
51: DEBUG(0, "ixj_attach()\n");
52: /* Create new ixj device */
START -->
53: link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
54: if (!link)
55: return NULL;
56: memset(link, 0, sizeof(struct dev_link_t));
57: link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;

Quoted 8 lines

58: link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
59: link->io.IOAddrLines = 3;
60: link->conf.Vcc = 50;
61: link->conf.IntType = INT_MEMORY_AND_IO;
62: link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
63: if (!link->priv)
END -->
64: return NULL;

Yes, this is a bug. Patch below.

thanks,
-chris

===== drivers/telephony/ixj_pcmcia.c 1.6 vs edited =====

drivers/telephony/ixj_pcmcia.c +3 -1
@@ -60,8 +60,10 @@
 	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
-	if (!link->priv)
+	if (!link->priv) {
+		kfree(link);
 		return NULL;
+	}
 	memset(link->priv, 0, sizeof(struct ixj_info_t));
 	/* Register with Card Services */
 	link->next = dev_list;
#27 lore raw
In reply to David Yu Chen
Quoted 15 lines · * David Yu Chen ([email protected]) wrote:

Leaks if devices == 0 ? Error_end only frees mdevs if (devices > 0), but for mdevs=kmalloc(0), the slab allocator may still actually return memory [FILE: 2.6.0-test5/drivers/usb/class/usb-midi.c]
[FUNC: alloc_usb_midi_device]
[LINES: 1621-1772]
[VAR: mdevs]
1616: devices = inDevs > outDevs ? inDevs : outDevs;
1617: devices = maxdevices > devices ? devices : maxdevices;
1618:
1619: /* obtain space for device name (iProduct) if not known. */
1620: if ( ! u->deviceName ) {
START -->
1621: mdevs = (struct usb_mididev **)
1622: kmalloc(sizeof(struct usb_mididevs *)*devices
1623: + sizeof(char) * 256, GFP_KERNEL);

<snip>

Quoted 2 lines

GOTO -->
1715: goto error_end;

<snip>

Quoted 6 lines

END -->
1772: return -ENOMEM;
[FILE: 2.6.0-test5/drivers/usb/class/usb-midi.c]
START -->
1625: mdevs = (struct usb_mididev **)
1626: kmalloc(sizeof(struct usb_mididevs *)*devices, GFP_KERNEL);

<snip>

Quoted 2 lines

GOTO -->
1715: goto error_end;

<snip>

Quoted 2 lines

END -->
1772: return -ENOMEM;

Yes, these are bugs. Patch below. Greg, this look ok?

thanks,
-chris

===== drivers/usb/class/usb-midi.c 1.22 vs edited =====

drivers/usb/class/usb-midi.c +1 -1
@@ -1750,7 +1750,7 @@
 	return 0;
 
  error_end:
-	if ( mdevs != NULL && devices > 0 ) {
+	if ( mdevs != NULL ) {
 		for ( i=0 ; i<devices ; i++ ) {
 			if ( mdevs[i] != NULL ) {
 				unregister_sound_midi( mdevs[i]->dev_midi );
#28 lore raw
Quoted 26 lines · Chris Wright
Quoted 15 lines · * David Yu Chen ([email protected]) wrote:

Leaks if devices == 0 ? Error_end only frees mdevs if (devices > 0), but for mdevs=kmalloc(0), the slab allocator may still actually return memory [FILE: 2.6.0-test5/drivers/usb/class/usb-midi.c]
[FUNC: alloc_usb_midi_device]
[LINES: 1621-1772]
[VAR: mdevs]
1616: devices = inDevs > outDevs ? inDevs : outDevs;
1617: devices = maxdevices > devices ? devices : maxdevices;
1618:
1619: /* obtain space for device name (iProduct) if not known. */
1620: if ( ! u->deviceName ) {
START -->
1621: mdevs = (struct usb_mididev **)
1622: kmalloc(sizeof(struct usb_mididevs *)*devices
1623: + sizeof(char) * 256, GFP_KERNEL);

<snip>

Quoted 2 lines

GOTO -->
1715: goto error_end;

<snip>

Quoted 6 lines

END -->
1772: return -ENOMEM;
[FILE: 2.6.0-test5/drivers/usb/class/usb-midi.c]
START -->
1625: mdevs = (struct usb_mididev **)
1626: kmalloc(sizeof(struct usb_mididevs *)*devices, GFP_KERNEL);

Quoted 8 lines

<snip>

Quoted 2 lines

GOTO -->
1715: goto error_end;

<snip>

Quoted 2 lines

END -->
1772: return -ENOMEM;

Yes, these are bugs. Patch below. Greg, this look ok?

Don't know, Vojtech said he would fix these up already. Try asking him :)

thanks,

greg k-h

#29 lore raw
Quoted 3 lines · * Greg KH ([email protected]) wrote:

Don't know, Vojtech said he would fix these up already. Try asking him :)

Ah, I missed that. Will do.
thanks,
-chris

Signature · 1 line
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net
#30 lore raw
In reply to Greg KH
Quoted 2 lines · * Greg KH ([email protected]) wrote:

Don't know, Vojtech said he would fix these up already. Try asking him :)

I checked with Vojtech, he said the patch looked OK. Can you apply?

thanks,
-chris

===== drivers/usb/class/usb-midi.c 1.22 vs edited =====

drivers/usb/class/usb-midi.c +1 -1
@@ -1750,7 +1750,7 @@
 	return 0;
 
  error_end:
-	if ( mdevs != NULL && devices > 0 ) {
+	if ( mdevs != NULL ) {
 		for ( i=0 ; i<devices ; i++ ) {
 			if ( mdevs[i] != NULL ) {
 				unregister_sound_midi( mdevs[i]->dev_midi );
Applied
#31 lore raw
Quoted 5 lines · Chris Wright
Quoted 2 lines · * Greg KH ([email protected]) wrote:

Don't know, Vojtech said he would fix these up already. Try asking him :)

I checked with Vojtech, he said the patch looked OK. Can you apply?

Applied, thanks.

greg k-h

#32 lore raw
In reply to David Yu Chen
Quoted 4 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/fs/afs/cell.c]
START -->
58: cell = kmalloc(sizeof(afs_cell_t) + strlen(name) + 1,GFP_KERNEL);
59: if (!cell) {

<snip>

Quoted 4 lines

126: error:
127: up_write(&afs_cells_sem);
128: kfree(afs_cell_root);
END -->

Yes, this looks like a bug/typo. Patch below. David, this look ok?

thanks,
-chris

===== fs/afs/cell.c 1.2 vs edited =====

fs/afs/cell.c +1 -1
@@ -145,7 +145,7 @@
 	printk("kAFS: bad VL server IP address: '%s'\n",vllist);
  error:
 	up_write(&afs_cells_sem);
-	kfree(afs_cell_root);
+	kfree(cell);
 	return ret;
 } /* end afs_cell_create() */
 
maintainer
#33 lore raw
Quoted 6 lines · * David Yu Chen ([email protected]) wrote:
Quoted 4 lines

[FILE: 2.6.0-test5/fs/afs/cell.c]
START -->
58: cell = kmalloc(sizeof(afs_cell_t) + strlen(name) + 1,GFP_KERNEL);
59: if (!cell) {

Quoted 7 lines

<snip>

Quoted 4 lines

126: error:
127: up_write(&afs_cells_sem);
128: kfree(afs_cell_root);
END -->

Yes, this looks like a bug/typo. Patch below. David, this look ok?

Yes. I've applied it to my local development version.

Thanks,
David

#34 lore raw
In reply to David Yu Chen
Quoted 11 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/net/sunrpc/auth_gss/gss_mech_switch.c] START -->
67: if (!(gm = kmalloc(sizeof(*gm), GFP_KERNEL))) {
68: printk("Failed to allocate memory in gss_mech_register");
69: return -1;
70: }
71: gm->gm_oid.len = mech_type->len;
72: if (!(gm->gm_oid.data = kmalloc(mech_type->len, GFP_KERNEL))) {
73: printk("Failed to allocate memory in gss_mech_register");
END -->
74: return -1;

<snip>

Quoted 9 lines

[FILE: 2.6.0-test5/net/sunrpc/auth_gss/gss_pseudoflavors.c] [FUNC: gss_register_triple]
START -->
74: if (!(triple = kmalloc(sizeof(*triple), GFP_KERNEL))) {
75: printk("Alloc failed in gss_register_triple");
GOTO -->
86: goto err_unlock;
END -->
97: return -1;

Yes, these are both bugs. Patch below. Trond, this look ok?

thanks,
-chris

===== net/sunrpc/auth_gss/gss_mech_switch.c 1.2 vs edited =====

net/sunrpc/auth_gss/gss_mech_switch.c +1 -0
@@ -71,6 +71,7 @@
 	gm->gm_oid.len = mech_type->len;
 	if (!(gm->gm_oid.data = kmalloc(mech_type->len, GFP_KERNEL))) {
 		printk("Failed to allocate memory in gss_mech_register");
+		kfree(gm);
 		return -1;
 	}
 	memcpy(gm->gm_oid.data, mech_type->data, mech_type->len);

===== net/sunrpc/auth_gss/gss_pseudoflavors.c 1.1 vs edited =====

net/sunrpc/auth_gss/gss_pseudoflavors.c +1 -0
@@ -93,6 +93,7 @@
 
 err_unlock:
 	spin_unlock(&registered_triples_lock);
+	kfree(triple);
 err:
 	return -1;
 }
#35 lore raw
In reply to David Yu Chen
Quoted 11 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/net/irda/irlmp.c]
[FUNC: irlmp_open_lsap]
[LINES: 161-183]
[VAR: self]
START -->
161: self = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
162: if (self == NULL) {
163: ERROR("%s: can't allocate memory", __FUNCTION__);
164: return NULL;
END -->
183: ASSERT(notify->instance != NULL, return NULL;);

Yes, this is a bug. Patch below. Jean, look ok?

thanks,
-chris

===== net/irda/irlmp.c 1.29 vs edited =====

net/irda/irlmp.c +4 -1
@@ -178,7 +178,7 @@
 
 	init_timer(&self->watchdog_timer);
 
-	ASSERT(notify->instance != NULL, return NULL;);
+	ASSERT(notify->instance != NULL, goto error;);
 	self->notify = *notify;
 
 	self->lsap_state = LSAP_DISCONNECTED;
@@ -188,6 +188,9 @@
 		       (long) self, NULL);
 
 	return self;
+error:
+	kfree(self);
+	return NULL;
 }
 
 /*
#36 lore raw
Quoted 13 lines · Chris Wright
Quoted 11 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/net/irda/irlmp.c]
[FUNC: irlmp_open_lsap]
[LINES: 161-183]
[VAR: self]
START -->
161: self = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
162: if (self == NULL) {
163: ERROR("%s: can't allocate memory", __FUNCTION__);
164: return NULL;
END -->
183: ASSERT(notify->instance != NULL, return NULL;);

Quoted 4 lines

Yes, this is a bug. Patch below. Jean, look ok?

thanks,
-chris

Yep, looks like the right thing. But, I would prefer a slighly
different fix. Would you mind moving the assert at the top of the function ?
Just like this :
--------------------------------------------------------------------

net/irda/irlmp.c Tue Sep 23 13:19:56 2003 renamed from net/irda/irlmp.d1.c Tue Sep 23 13:19:37 2003 +1 -1
@@ -146,6 +146,7 @@ struct lsap_cb *irlmp_open_lsap(__u8 sls
        ASSERT(notify != NULL, return NULL;);
        ASSERT(irlmp != NULL, return NULL;);
        ASSERT(irlmp->magic == LMP_MAGIC, return NULL;);
+       ASSERT(notify->instance != NULL, return NULL;);
 
        /*  Does the client care which Source LSAP selector it gets?  */
        if (slsap_sel == LSAP_ANY) {
@@ -178,7 +179,6 @@ struct lsap_cb *irlmp_open_lsap(__u8 sls
 
        init_timer(&self->watchdog_timer);
 
-       ASSERT(notify->instance != NULL, return NULL;);
        self->notify = *notify;
 
        self->lsap_state = LSAP_DISCONNECTED;

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

	This is simpler and more efficient ;-)

	Thanks...

	Jean
#37 lore raw
Quoted 2 lines · * Jean Tourrilhes ([email protected]) wrote:

This is simpler and more efficient ;-)

Yes, I agree, your patch is better.

-thanks,
-chris

Signature · 1 line
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net
#38 lore raw
In reply to David Yu Chen
Quoted 21 lines · * David Yu Chen ([email protected]) wrote:

[FILE: 2.6.0-test5/sound/oss/ymfpci.c]
START -->
2530: if ((codec = kmalloc(sizeof(ymfpci_t), GFP_KERNEL)) == NULL) {
2531: printk(KERN_ERR "ymfpci: no core\n");
2532: return -ENOMEM;
2533: }
2534: memset(codec, 0, sizeof(*codec));
2535:

        ... DELETED 11 lines ...

2547: goto out_free;
2548: }
2549:
2550: if ((codec->reg_area_virt = ioremap(base, 0x8000)) == NULL) {
2551: printk(KERN_ERR "ymfpci: unable to map registers\n");
GOTO -->
2552: goto out_release_region;
2553: }
2554:
2555: pci_set_master(pcidev);
2556:
2557: printk(KERN_INFO "ymfpci: %s at 0x%lx IRQ %d\n",

Quoted 8 lines
        ... DELETED 78 lines ...

2636: out_release_region:
2637: release_mem_region(pci_resource_start(pcidev, 0), 0x8000);
2638: out_free:
2639: if (codec->ac97_codec[0])
2640: ac97_release_codec(codec->ac97_codec[0]);
END -->
2641: return -ENODEV;

Yes, this looks like a bug. Patch below. Alan, this look ok?

thanks,
-chris

===== sound/oss/ymfpci.c 1.38 vs edited =====

sound/oss/ymfpci.c +1 -0
@@ -2638,6 +2638,7 @@
  out_free:
 	if (codec->ac97_codec[0])
 		ac97_release_codec(codec->ac97_codec[0]);
+	kfree(codec);
 	return -ENODEV;
 }