atm: dereference of he_dev->rbps_virt in he_init_group()
Subsystems (3)
PATCH 1/1 atm: dereference of he_dev->rbps_virt in he_init_group()
he_dev->rbps_virt allocation may fail.
---
drivers/atm/he.c +2 -0
@@ -795,6 +795,8 @@ he_init_group(struct he_dev *he_dev, int group) }memset (he_dev->rbps_base,0 ,CONFIG_RBPS_SIZE *sizeof (struct he_rbp )); he_dev->rbps_virt =kmalloc (CONFIG_RBPS_SIZE *sizeof (struct he_virt ),GFP_KERNEL ); +if (he_dev->rbps_virt ==NULL ) +return -ENOMEM ;for (i =0 ; i <CONFIG_RBPS_SIZE ; ++i) {dma_addr_t dma_handle;
he_dev->rbps_virt or he_dev->rbpl_virt allocation may fail.
---
There was another in the same function.
drivers/atm/he.c +4 -0
@@ -795,6 +795,8 @@ he_init_group(struct he_dev *he_dev, int group) }memset (he_dev->rbps_base,0 ,CONFIG_RBPS_SIZE *sizeof (struct he_rbp )); he_dev->rbps_virt =kmalloc (CONFIG_RBPS_SIZE *sizeof (struct he_virt ),GFP_KERNEL ); +if (he_dev->rbps_virt ==NULL ) +return -ENOMEM ;for (i =0 ; i <CONFIG_RBPS_SIZE ; ++i) {dma_addr_t dma_handle;
@@ -838,6 +840,8 @@ he_init_group(struct he_dev *he_dev, int group) }memset (he_dev->rbpl_base,0 ,CONFIG_RBPL_SIZE *sizeof (struct he_rbp )); he_dev->rbpl_virt =kmalloc (CONFIG_RBPL_SIZE *sizeof (struct he_virt ),GFP_KERNEL ); +if (he_dev->rbpl_virt ==NULL ) +return -ENOMEM ;for (i =0 ; i <CONFIG_RBPL_SIZE ; ++i) {dma_addr_t dma_handle;
David Miller
maintainerFrom: Roel Kluin <[email protected]>
Date: Sat, 29 Aug 2009 20:59:04 +0200
Quoted 5 lines
he_dev->rbps_virtorhe_dev->rbpl_virtallocation may fail.Signed-off-by Roel Kluin <[email protected]>---
There was another in the same function.
These new return statements will both leak resources allocated earlier.
All the caller is going to do is return -ENOMEM as well and it does not cleanup actions at all.
Please fix this up.
he_dev->rbps_virt or he_dev->rbpl_virt allocation may fail, so check them. Make sure that he_init_group() cleans up after errors.
---
Quoted 7 lines
These new return statements will both leak resources allocated earlier.
All the caller is going to do is return
-ENOMEMas well and it does not cleanup actions at all.Please fix this up.
I am new to this api, so please review.
drivers/atm/he.c +59 -12
@@ -777,7 +777,7 @@ he_init_cs_block_rcm(struct he_dev *he_dev)static int __devinit he_init_group (struct he_dev *he_dev,int group) { -int i; +int i, ret;/* small buffer pool */ he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
@@ -790,19 +790,27 @@ he_init_group(struct he_dev *he_dev, int group) he_dev->rbps_base =pci_alloc_consistent (he_dev->pci_dev,CONFIG_RBPS_SIZE *sizeof (struct he_rbp ), &he_dev->rbps_phys);if (he_dev->rbps_base ==NULL ) { -hprintk ("failed to alloc rbps\n" ); -return -ENOMEM ; +hprintk ("failed to alloc rbps_base\n" ); + ret = -ENOMEM ; + goto out_destroy_rbps_pool; }memset (he_dev->rbps_base,0 ,CONFIG_RBPS_SIZE *sizeof (struct he_rbp )); he_dev->rbps_virt =kmalloc (CONFIG_RBPS_SIZE *sizeof (struct he_virt ),GFP_KERNEL ); +if (he_dev->rbps_virt ==NULL ) { +hprintk ("failed to alloc rbps_virt\n" ); + ret = -ENOMEM ; + goto out_free_rbps_base; + }for (i =0 ; i <CONFIG_RBPS_SIZE ; ++i) {dma_addr_t dma_handle;void *cpuaddr; cpuaddr =pci_pool_alloc (he_dev->rbps_pool,GFP_KERNEL |GFP_DMA , &dma_handle); -if (cpuaddr ==NULL ) -return -ENOMEM ; +if (cpuaddr ==NULL ) { + ret = -ENOMEM ; + goto out_free_rbps_virt; + } he_dev->rbps_virt[i].virt = cpuaddr; he_dev->rbps_base[i].status =RBP_LOANED |RBP_SMALLBUF | (i <<RBP_INDEX_OFF );
@@ -827,25 +835,34 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_RBPL_BUFSIZE, 8, 0);if (he_dev->rbpl_pool ==NULL ) {hprintk ("unable to create rbpl pool\n" ); -return -ENOMEM ; + ret = -ENOMEM ; + goto out_free_rbps_virt; } he_dev->rbpl_base =pci_alloc_consistent (he_dev->pci_dev,CONFIG_RBPL_SIZE *sizeof (struct he_rbp ), &he_dev->rbpl_phys);if (he_dev->rbpl_base ==NULL ) { -hprintk ("failed to alloc rbpl\n" ); -return -ENOMEM ; +hprintk ("failed to alloc rbpl_base\n" ); + ret = -ENOMEM ; + goto out_destroy_rbpl_pool; }memset (he_dev->rbpl_base,0 ,CONFIG_RBPL_SIZE *sizeof (struct he_rbp )); he_dev->rbpl_virt =kmalloc (CONFIG_RBPL_SIZE *sizeof (struct he_virt ),GFP_KERNEL ); +if (he_dev->rbpl_virt ==NULL ) { +hprintk ("failed to alloc rbpl_virt\n" ); + ret = -ENOMEM ; + goto out_free_rbpl_base; + }for (i =0 ; i <CONFIG_RBPL_SIZE ; ++i) {dma_addr_t dma_handle;void *cpuaddr; cpuaddr =pci_pool_alloc (he_dev->rbpl_pool,GFP_KERNEL |GFP_DMA , &dma_handle); -if (cpuaddr ==NULL ) -return -ENOMEM ; +if (cpuaddr ==NULL ) { + ret = -ENOMEM ; + goto out_free_rbpl_virt; + } he_dev->rbpl_virt[i].virt = cpuaddr; he_dev->rbpl_base[i].status =RBP_LOANED | (i <<RBP_INDEX_OFF );
@@ -870,7 +887,8 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);if (he_dev->rbrq_base ==NULL ) {hprintk ("failed to allocate rbrq\n" ); -return -ENOMEM ; + ret = -ENOMEM ; + goto out_free_rbpl_virt; }memset (he_dev->rbrq_base,0 ,CONFIG_RBRQ_SIZE *sizeof (struct he_rbrq ));
@@ -894,7 +912,8 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);if (he_dev->tbrq_base ==NULL ) {hprintk ("failed to allocate tbrq\n" ); -return -ENOMEM ; + ret = -ENOMEM ; + goto out_free_rbpq_base; }memset (he_dev->tbrq_base,0 ,CONFIG_TBRQ_SIZE *sizeof (struct he_tbrq ));
@@ -906,6 +925,34 @@ he_init_group(struct he_dev *he_dev, int group)he_writel (he_dev,CONFIG_TBRQ_THRESH ,G0_TBRQ_THRESH + (group *16 ));return 0 ; + +out_free_rbpq_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBRQ_SIZE *sizeof (struct he_rbrq ), + he_dev->rbrq_base, he_dev->rbrq_phys); + i =CONFIG_RBPL_SIZE ; +out_free_rbpl_virt: +while (--i) +pci_pool_free (he_dev->rbpl_virt[i].virt); +kfree (he_dev->rbpl_virt); + +out_free_rbpl_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBPL_SIZE *sizeof (struct he_rbp ), + he_dev->rbpl_base, he_dev->rbpl_phys); +out_destroy_rbpl_pool: +pci_pool_destroy (he_dev->rbpl_pool); + + i =CONFIG_RBPL_SIZE ; +out_free_rbps_virt: +while (--i) +pci_pool_free (he_dev->rbps_virt[i].virt); +kfree (he_dev->rbps_virt); + +out_free_rbps_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBPS_SIZE *sizeof (struct he_rbp ), + he_dev->rbps_base, he_dev->rbps_phys); +out_destroy_rbps_pool: +pci_pool_destroy (he_dev->rbps_pool); +return ret; } static int __devinit
David Miller
maintainerFrom: Roel Kluin <[email protected]>
Date: Sat, 05 Sep 2009 14:35:18 +0200
Quoted 8 lines
he_dev->rbps_virtorhe_dev->rbpl_virtallocation may fail, so check them. Make sure thathe_init_group()cleans up after errors.Signed-off-by Roel Kluin <[email protected]>---
Quoted 3 lines
These new return statements will both leak resources allocated earlier.
Quoted 6 lines
Quoted 4 lines
All the caller is going to do is return
-ENOMEMas well and it does not cleanup actions at all.Please fix this up.
I am new to this api, so please review.
Looks ok, applied, thanks.
David Miller
maintainerFrom: David Miller <[email protected]>
Date: Fri, 11 Sep 2009 12:37:25 -0700 (PDT)
Quoted 11 lines
From: Roel Kluin <[email protected]>
Date: Sat, 05 Sep 2009 14:35:18 +0200Quoted 8 lines
he_dev->rbps_virtorhe_dev->rbpl_virtallocation may fail, so check them. Make sure thathe_init_group()cleans up after errors.Signed-off-by Roel Kluin <[email protected]>---
Quoted 3 lines
These new return statements will both leak resources allocated earlier.
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
All the caller is going to do is return
-ENOMEMas well and it does not cleanup actions at all.Please fix this up.
I am new to this api, so please review.
Looks ok, applied, thanks.
Sorry I have to revert, you didn't even build test this.
Roel, I know you want me to take your changes serious, but I absolutely cannot when you do stuff like this.
PATCH 1/1 atm: dereference of he_dev->rbps_virt in he_init_group()
he_dev->rbps_virt or he_dev->rbpl_virt allocation may fail, s them. Make sure that he_init_group() cleans up after errors.
---
Found with sed: http://kernelnewbies.org/roelkluin
This version was build, sparse and checkpatch tested.
drivers/atm/he.c +64 -12
@@ -777,7 +777,7 @@ he_init_cs_block_rcm(struct he_dev *he_dev)static int __devinit he_init_group (struct he_dev *he_dev,int group) { -int i; +int i, ret;/* small buffer pool */ he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
@@ -790,19 +790,27 @@ he_init_group(struct he_dev *he_dev, int group) he_dev->rbps_base =pci_alloc_consistent (he_dev->pci_dev,CONFIG_RBPS_SIZE *sizeof (struct he_rbp ), &he_dev->rbps_phys);if (he_dev->rbps_base ==NULL ) { -hprintk ("failed to alloc rbps\n" ); -return -ENOMEM ; +hprintk ("failed to alloc rbps_base\n" ); + ret = -ENOMEM ; + goto out_destroy_rbps_pool; }memset (he_dev->rbps_base,0 ,CONFIG_RBPS_SIZE *sizeof (struct he_rbp )); he_dev->rbps_virt =kmalloc (CONFIG_RBPS_SIZE *sizeof (struct he_virt ),GFP_KERNEL ); +if (he_dev->rbps_virt ==NULL ) { +hprintk ("failed to alloc rbps_virt\n" ); + ret = -ENOMEM ; + goto out_free_rbps_base; + }for (i =0 ; i <CONFIG_RBPS_SIZE ; ++i) {dma_addr_t dma_handle;void *cpuaddr; cpuaddr =pci_pool_alloc (he_dev->rbps_pool,GFP_KERNEL |GFP_DMA , &dma_handle); -if (cpuaddr ==NULL ) -return -ENOMEM ; +if (cpuaddr ==NULL ) { + ret = -ENOMEM ; + goto out_free_rbps_virt; + } he_dev->rbps_virt[i].virt = cpuaddr; he_dev->rbps_base[i].status =RBP_LOANED |RBP_SMALLBUF | (i <<RBP_INDEX_OFF );
@@ -827,25 +835,34 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_RBPL_BUFSIZE, 8, 0);if (he_dev->rbpl_pool ==NULL ) {hprintk ("unable to create rbpl pool\n" ); -return -ENOMEM ; + ret = -ENOMEM ; + goto out_free_rbps_virt; } he_dev->rbpl_base =pci_alloc_consistent (he_dev->pci_dev,CONFIG_RBPL_SIZE *sizeof (struct he_rbp ), &he_dev->rbpl_phys);if (he_dev->rbpl_base ==NULL ) { -hprintk ("failed to alloc rbpl\n" ); -return -ENOMEM ; +hprintk ("failed to alloc rbpl_base\n" ); + ret = -ENOMEM ; + goto out_destroy_rbpl_pool; }memset (he_dev->rbpl_base,0 ,CONFIG_RBPL_SIZE *sizeof (struct he_rbp )); he_dev->rbpl_virt =kmalloc (CONFIG_RBPL_SIZE *sizeof (struct he_virt ),GFP_KERNEL ); +if (he_dev->rbpl_virt ==NULL ) { +hprintk ("failed to alloc rbpl_virt\n" ); + ret = -ENOMEM ; + goto out_free_rbpl_base; + }for (i =0 ; i <CONFIG_RBPL_SIZE ; ++i) {dma_addr_t dma_handle;void *cpuaddr; cpuaddr =pci_pool_alloc (he_dev->rbpl_pool,GFP_KERNEL |GFP_DMA , &dma_handle); -if (cpuaddr ==NULL ) -return -ENOMEM ; +if (cpuaddr ==NULL ) { + ret = -ENOMEM ; + goto out_free_rbpl_virt; + } he_dev->rbpl_virt[i].virt = cpuaddr; he_dev->rbpl_base[i].status =RBP_LOANED | (i <<RBP_INDEX_OFF );
@@ -870,7 +887,8 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);if (he_dev->rbrq_base ==NULL ) {hprintk ("failed to allocate rbrq\n" ); -return -ENOMEM ; + ret = -ENOMEM ; + goto out_free_rbpl_virt; }memset (he_dev->rbrq_base,0 ,CONFIG_RBRQ_SIZE *sizeof (struct he_rbrq ));
@@ -894,7 +912,8 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);if (he_dev->tbrq_base ==NULL ) {hprintk ("failed to allocate tbrq\n" ); -return -ENOMEM ; + ret = -ENOMEM ; + goto out_free_rbpq_base; }memset (he_dev->tbrq_base,0 ,CONFIG_TBRQ_SIZE *sizeof (struct he_tbrq ));
@@ -906,6 +925,39 @@ he_init_group(struct he_dev *he_dev, int group)he_writel (he_dev,CONFIG_TBRQ_THRESH ,G0_TBRQ_THRESH + (group *16 ));return 0 ; + +out_free_rbpq_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBRQ_SIZE * +sizeof (struct he_rbrq ), he_dev->rbrq_base, + he_dev->rbrq_phys); + i =CONFIG_RBPL_SIZE ; +out_free_rbpl_virt: +while (--i) +pci_pool_free (he_dev->rbps_pool, he_dev->rbpl_virt[i].virt, + he_dev->rbps_base[i].phys); +kfree (he_dev->rbpl_virt); + +out_free_rbpl_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBPL_SIZE * +sizeof (struct he_rbp ), he_dev->rbpl_base, + he_dev->rbpl_phys); +out_destroy_rbpl_pool: +pci_pool_destroy (he_dev->rbpl_pool); + + i =CONFIG_RBPL_SIZE ; +out_free_rbps_virt: +while (--i) +pci_pool_free (he_dev->rbpl_pool, he_dev->rbps_virt[i].virt, + he_dev->rbpl_base[i].phys); +kfree (he_dev->rbps_virt); + +out_free_rbps_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBPS_SIZE * +sizeof (struct he_rbp ), he_dev->rbps_base, + he_dev->rbps_phys); +out_destroy_rbps_pool: +pci_pool_destroy (he_dev->rbps_pool); +return ret; } static int __devinit
Review
Quoted 12 lines · Roel Kluin
(quoted diff) +12
-0+ int i, ret; + ret = -ENOMEM; + ret = -ENOMEM; + ret = -ENOMEM; + ret = -ENOMEM; + ret = -ENOMEM; + ret = -ENOMEM; + ret = -ENOMEM; + ret = -ENOMEM; +out_destroy_rbps_pool: + pci_pool_destroy(he_dev->rbps_pool); + return ret;
It looks as if it'd be clearer to not use variable ret and simply return -ENOMEM after the out_destroy_rbps_pool label.
he_dev->rbps_virt or he_dev->rbpl_virt allocation may fail, s them. Make sure that he_init_group() cleans up after errors.
---
Quoted 2 lines
It looks as if it'd be clearer to not use variable ret and simply return
-ENOMEMafter theout_destroy_rbps_poollabel.
Ok, thanks.
Again build, sparse and checkpatch tested.
drivers/atm/he.c +50 -9
@@ -790,11 +790,15 @@ he_init_group(struct he_dev *he_dev, int group) he_dev->rbps_base =pci_alloc_consistent (he_dev->pci_dev,CONFIG_RBPS_SIZE *sizeof (struct he_rbp ), &he_dev->rbps_phys);if (he_dev->rbps_base ==NULL ) { -hprintk ("failed to alloc rbps\n" ); -return -ENOMEM ; +hprintk ("failed to alloc rbps_base\n" ); + goto out_destroy_rbps_pool; }memset (he_dev->rbps_base,0 ,CONFIG_RBPS_SIZE *sizeof (struct he_rbp )); he_dev->rbps_virt =kmalloc (CONFIG_RBPS_SIZE *sizeof (struct he_virt ),GFP_KERNEL ); +if (he_dev->rbps_virt ==NULL ) { +hprintk ("failed to alloc rbps_virt\n" ); + goto out_free_rbps_base; + }for (i =0 ; i <CONFIG_RBPS_SIZE ; ++i) {dma_addr_t dma_handle;
@@ -802,7 +806,7 @@ he_init_group(struct he_dev *he_dev, int group) cpuaddr =pci_pool_alloc (he_dev->rbps_pool,GFP_KERNEL |GFP_DMA , &dma_handle);if (cpuaddr ==NULL ) -return -ENOMEM ; + goto out_free_rbps_virt; he_dev->rbps_virt[i].virt = cpuaddr; he_dev->rbps_base[i].status =RBP_LOANED |RBP_SMALLBUF | (i <<RBP_INDEX_OFF );
@@ -827,17 +831,21 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_RBPL_BUFSIZE, 8, 0);if (he_dev->rbpl_pool ==NULL ) {hprintk ("unable to create rbpl pool\n" ); -return -ENOMEM ; + goto out_free_rbps_virt; } he_dev->rbpl_base =pci_alloc_consistent (he_dev->pci_dev,CONFIG_RBPL_SIZE *sizeof (struct he_rbp ), &he_dev->rbpl_phys);if (he_dev->rbpl_base ==NULL ) { -hprintk ("failed to alloc rbpl\n" ); -return -ENOMEM ; +hprintk ("failed to alloc rbpl_base\n" ); + goto out_destroy_rbpl_pool; }memset (he_dev->rbpl_base,0 ,CONFIG_RBPL_SIZE *sizeof (struct he_rbp )); he_dev->rbpl_virt =kmalloc (CONFIG_RBPL_SIZE *sizeof (struct he_virt ),GFP_KERNEL ); +if (he_dev->rbpl_virt ==NULL ) { +hprintk ("failed to alloc rbpl_virt\n" ); + goto out_free_rbpl_base; + }for (i =0 ; i <CONFIG_RBPL_SIZE ; ++i) {dma_addr_t dma_handle;
@@ -845,7 +853,7 @@ he_init_group(struct he_dev *he_dev, int group) cpuaddr =pci_pool_alloc (he_dev->rbpl_pool,GFP_KERNEL |GFP_DMA , &dma_handle);if (cpuaddr ==NULL ) -return -ENOMEM ; + goto out_free_rbpl_virt; he_dev->rbpl_virt[i].virt = cpuaddr; he_dev->rbpl_base[i].status =RBP_LOANED | (i <<RBP_INDEX_OFF );
@@ -870,7 +878,7 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);if (he_dev->rbrq_base ==NULL ) {hprintk ("failed to allocate rbrq\n" ); -return -ENOMEM ; + goto out_free_rbpl_virt; }memset (he_dev->rbrq_base,0 ,CONFIG_RBRQ_SIZE *sizeof (struct he_rbrq ));
@@ -894,7 +902,7 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);if (he_dev->tbrq_base ==NULL ) {hprintk ("failed to allocate tbrq\n" ); -return -ENOMEM ; + goto out_free_rbpq_base; }memset (he_dev->tbrq_base,0 ,CONFIG_TBRQ_SIZE *sizeof (struct he_tbrq ));
@@ -906,6 +914,39 @@ he_init_group(struct he_dev *he_dev, int group)he_writel (he_dev,CONFIG_TBRQ_THRESH ,G0_TBRQ_THRESH + (group *16 ));return 0 ; + +out_free_rbpq_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBRQ_SIZE * +sizeof (struct he_rbrq ), he_dev->rbrq_base, + he_dev->rbrq_phys); + i =CONFIG_RBPL_SIZE ; +out_free_rbpl_virt: +while (--i) +pci_pool_free (he_dev->rbps_pool, he_dev->rbpl_virt[i].virt, + he_dev->rbps_base[i].phys); +kfree (he_dev->rbpl_virt); + +out_free_rbpl_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBPL_SIZE * +sizeof (struct he_rbp ), he_dev->rbpl_base, + he_dev->rbpl_phys); +out_destroy_rbpl_pool: +pci_pool_destroy (he_dev->rbpl_pool); + + i =CONFIG_RBPL_SIZE ; +out_free_rbps_virt: +while (--i) +pci_pool_free (he_dev->rbpl_pool, he_dev->rbps_virt[i].virt, + he_dev->rbpl_base[i].phys); +kfree (he_dev->rbps_virt); + +out_free_rbps_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBPS_SIZE * +sizeof (struct he_rbp ), he_dev->rbps_base, + he_dev->rbps_phys); +out_destroy_rbps_pool: +pci_pool_destroy (he_dev->rbps_pool); +return -ENOMEM ; } static int __devinit
From: Roel Kluin <[email protected]>
Date: Sun, 20 Sep 2009 19:11:28 +0200
Quoted 4 lines
he_dev->rbps_virtorhe_dev->rbpl_virtallocation may fail, s them. Make sure thathe_init_group()cleans up after errors.Signed-off-by Roel Kluin <[email protected]>
Applied.
he_dev->rbps_virt or he_dev->rbpl_virt allocation may fail, so check them. Make sure that he_init_group() cleans up after errors.
---
David, I swapped rbps and rbpl arguments in my last patch, and there were some other problems. This was pointed out by Juha Leppanen. Can you please replace the former patch by this one?
This was version was build, sparse and checkpatch tested.
Sorry for the mess.
Roel
drivers/atm/he.c +64 -12
@@ -777,7 +777,7 @@ he_init_cs_block_rcm(struct he_dev *he_dev)static int __devinit he_init_group (struct he_dev *he_dev,int group) { -int i; +int i, ret;/* small buffer pool */ he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
@@ -790,19 +790,27 @@ he_init_group(struct he_dev *he_dev, int group) he_dev->rbps_base =pci_alloc_consistent (he_dev->pci_dev,CONFIG_RBPS_SIZE *sizeof (struct he_rbp ), &he_dev->rbps_phys);if (he_dev->rbps_base ==NULL ) { -hprintk ("failed to alloc rbps\n" ); -return -ENOMEM ; +hprintk ("failed to alloc rbps_base\n" ); + ret = -ENOMEM ; + goto out_destroy_rbps_pool; }memset (he_dev->rbps_base,0 ,CONFIG_RBPS_SIZE *sizeof (struct he_rbp )); he_dev->rbps_virt =kmalloc (CONFIG_RBPS_SIZE *sizeof (struct he_virt ),GFP_KERNEL ); +if (he_dev->rbps_virt ==NULL ) { +hprintk ("failed to alloc rbps_virt\n" ); + ret = -ENOMEM ; + goto out_free_rbps_base; + }for (i =0 ; i <CONFIG_RBPS_SIZE ; ++i) {dma_addr_t dma_handle;void *cpuaddr; cpuaddr =pci_pool_alloc (he_dev->rbps_pool,GFP_KERNEL |GFP_DMA , &dma_handle); -if (cpuaddr ==NULL ) -return -ENOMEM ; +if (cpuaddr ==NULL ) { + ret = -ENOMEM ; + goto out_free_rbps_virt; + } he_dev->rbps_virt[i].virt = cpuaddr; he_dev->rbps_base[i].status =RBP_LOANED |RBP_SMALLBUF | (i <<RBP_INDEX_OFF );
@@ -827,25 +835,34 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_RBPL_BUFSIZE, 8, 0);if (he_dev->rbpl_pool ==NULL ) {hprintk ("unable to create rbpl pool\n" ); -return -ENOMEM ; + ret = -ENOMEM ; + goto out_free_rbps_virt; } he_dev->rbpl_base =pci_alloc_consistent (he_dev->pci_dev,CONFIG_RBPL_SIZE *sizeof (struct he_rbp ), &he_dev->rbpl_phys);if (he_dev->rbpl_base ==NULL ) { -hprintk ("failed to alloc rbpl\n" ); -return -ENOMEM ; +hprintk ("failed to alloc rbpl_base\n" ); + ret = -ENOMEM ; + goto out_destroy_rbpl_pool; }memset (he_dev->rbpl_base,0 ,CONFIG_RBPL_SIZE *sizeof (struct he_rbp )); he_dev->rbpl_virt =kmalloc (CONFIG_RBPL_SIZE *sizeof (struct he_virt ),GFP_KERNEL ); +if (he_dev->rbpl_virt ==NULL ) { +hprintk ("failed to alloc rbpl_virt\n" ); + ret = -ENOMEM ; + goto out_free_rbpl_base; + }for (i =0 ; i <CONFIG_RBPL_SIZE ; ++i) {dma_addr_t dma_handle;void *cpuaddr; cpuaddr =pci_pool_alloc (he_dev->rbpl_pool,GFP_KERNEL |GFP_DMA , &dma_handle); -if (cpuaddr ==NULL ) -return -ENOMEM ; +if (cpuaddr ==NULL ) { + ret = -ENOMEM ; + goto out_free_rbpl_virt; + } he_dev->rbpl_virt[i].virt = cpuaddr; he_dev->rbpl_base[i].status =RBP_LOANED | (i <<RBP_INDEX_OFF );
@@ -870,7 +887,8 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);if (he_dev->rbrq_base ==NULL ) {hprintk ("failed to allocate rbrq\n" ); -return -ENOMEM ; + ret = -ENOMEM ; + goto out_free_rbpl_virt; }memset (he_dev->rbrq_base,0 ,CONFIG_RBRQ_SIZE *sizeof (struct he_rbrq ));
@@ -894,7 +912,8 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);if (he_dev->tbrq_base ==NULL ) {hprintk ("failed to allocate tbrq\n" ); -return -ENOMEM ; + ret = -ENOMEM ; + goto out_free_rbpq_base; }memset (he_dev->tbrq_base,0 ,CONFIG_TBRQ_SIZE *sizeof (struct he_tbrq ));
@@ -906,6 +925,39 @@ he_init_group(struct he_dev *he_dev, int group)he_writel (he_dev,CONFIG_TBRQ_THRESH ,G0_TBRQ_THRESH + (group *16 ));return 0 ; + +out_free_rbpq_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBRQ_SIZE * +sizeof (struct he_rbrq ), he_dev->rbrq_base, + he_dev->rbrq_phys); + i =CONFIG_RBPL_SIZE ; +out_free_rbpl_virt: +while (i--) +pci_pool_free (he_dev->rbpl_pool, he_dev->rbpl_virt[i].virt, + he_dev->rbpl_base[i].phys); +kfree (he_dev->rbpl_virt); + +out_free_rbpl_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBPL_SIZE * +sizeof (struct he_rbp ), he_dev->rbpl_base, + he_dev->rbpl_phys); +out_destroy_rbpl_pool: +pci_pool_destroy (he_dev->rbpl_pool); + + i =CONFIG_RBPS_SIZE ; +out_free_rbps_virt: +while (i--) +pci_pool_free (he_dev->rbps_pool, he_dev->rbps_virt[i].virt, + he_dev->rbps_base[i].phys); +kfree (he_dev->rbps_virt); + +out_free_rbps_base: +pci_free_consistent (he_dev->pci_dev,CONFIG_RBPS_SIZE * +sizeof (struct he_rbp ), he_dev->rbps_base, + he_dev->rbps_phys); +out_destroy_rbps_pool: +pci_pool_destroy (he_dev->rbps_pool); +return ret; } static int __devinit
David Miller
maintainerFrom: Roel Kluin <[email protected]>
Date: Sat, 26 Sep 2009 15:20:47 +0200
Quoted 6 lines
he_dev->rbps_virtorhe_dev->rbpl_virtallocation may fail, so check them. Make sure thathe_init_group()cleans up after errors.Signed-off-by Roel Kluin <[email protected]>Signed-off-by "Juha Leppanen" <[email protected]>
Quoted 8 lines
---
David, I swapped rbps and rbpl arguments in my last patch, and there were some other problems. This was pointed out by Juha Leppanen. Can you please replace the former patch by this one?This was version was build, sparse and checkpatch tested.
Sorry for the mess.
I can't just "replace" it, especially since your change is even already in Linus's tree.
Please send me a relative fixup rather than a new patch.
From: Juha Leppanen <[email protected]>
Date: Sat, Sep 26, 2009 at 12:34 AM
Subject: atm: he: memleak/negative indexing of arrays in he_init_group()
The prefix decrement causes a very long loop if pci_pool_alloc() failed in the first iteration. Also I swapped rbps and rbpl arguments.
drivers/atm/he.c +7 -7
@@ -921,9 +921,9 @@ out_free_rbpq_base: he_dev->rbrq_phys); i =CONFIG_RBPL_SIZE ; out_free_rbpl_virt: -while (--i) -pci_pool_free (he_dev->rbps_pool, he_dev->rbpl_virt[i].virt, - he_dev->rbps_base[i].phys); +while (i--) +pci_pool_free (he_dev->rbpl_pool, he_dev->rbpl_virt[i].virt, + he_dev->rbpl_base[i].phys);kfree (he_dev->rbpl_virt); out_free_rbpl_base:
@@ -933,11 +933,11 @@ out_free_rbpl_base: out_destroy_rbpl_pool:pci_pool_destroy (he_dev->rbpl_pool); - i =CONFIG_RBPL_SIZE ; + i =CONFIG_RBPS_SIZE ; out_free_rbps_virt: -while (--i) -pci_pool_free (he_dev->rbpl_pool, he_dev->rbps_virt[i].virt, - he_dev->rbpl_base[i].phys); +while (i--) +pci_pool_free (he_dev->rbps_pool, he_dev->rbps_virt[i].virt, + he_dev->rbps_base[i].phys);kfree (he_dev->rbps_virt); out_free_rbps_base:
From: Roel Kluin <[email protected]>
Date: Mon, 28 Sep 2009 10:58:43 +0200
Quoted 9 lines
From: Juha Leppanen <[email protected]>
Date: Sat, Sep 26, 2009 at 12:34 AM
Subject: atm: he: memleak/negative indexing of arrays inhe_init_group()The prefix decrement causes a very long loop if
pci_pool_alloc()failed in the first iteration. Also I swapped rbps and rbpl arguments.Reported-by Juha Leppanen <[email protected]>Signed-off-by Roel Kluin <[email protected]>
Applied, thanks.
Note that, by putting that From: line with Juha's info in it, I assume that you want this person to be listed as the author of the patch instead of you.