diff options
author | Arnd Bergmann <arnd@arndb.de> | 2014-11-20 07:15:25 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2014-11-20 07:15:25 -0500 |
commit | 27bc375a9c50f70a9c600a6771cc50ffd5cf8c98 (patch) | |
tree | 362067cd5776615d8ee71bd14b5cf75b1506e932 | |
parent | 22b7db80a9952d6af27b0cca71e369fdbc5b587f (diff) | |
parent | 148bb0439adeeae466dca31dd4c643e194bee023 (diff) |
Merge tag 'keystone-driver-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone into next/drivers
Pull "Keystone SOC Navigator driver non critical fixes frm Alex for 3.19" from Santosh Shilimkar:
- Use list_for_each_entry_safe to prevent use after free
- Return proper error if devm_kzalloc fails
- Use list_first_entry_or_null() at appropriate places
* tag 'keystone-driver-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone:
soc: ti: knav_qmss_queue: Use list_for_each_entry_safe to prevent use after free
soc: ti: knav_qmss_queue: Return proper error if devm_kzalloc fails
soc: ti: knav_qmss_queue: Fix unbalanced locking ins knav_pool_create()
soc: ti: Use list_first_entry_or_null() at appropriate places
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | drivers/soc/ti/knav_qmss.h | 8 | ||||
-rw-r--r-- | drivers/soc/ti/knav_qmss_queue.c | 13 |
2 files changed, 11 insertions, 10 deletions
diff --git a/drivers/soc/ti/knav_qmss.h b/drivers/soc/ti/knav_qmss.h index bc9dcc8cc3ce..51da2341280d 100644 --- a/drivers/soc/ti/knav_qmss.h +++ b/drivers/soc/ti/knav_qmss.h | |||
@@ -348,15 +348,15 @@ struct knav_range_info { | |||
348 | list_for_each_entry(region, &kdev->regions, list) | 348 | list_for_each_entry(region, &kdev->regions, list) |
349 | 349 | ||
350 | #define first_region(kdev) \ | 350 | #define first_region(kdev) \ |
351 | list_first_entry(&kdev->regions, \ | 351 | list_first_entry_or_null(&kdev->regions, \ |
352 | struct knav_region, list) | 352 | struct knav_region, list) |
353 | 353 | ||
354 | #define for_each_queue_range(kdev, range) \ | 354 | #define for_each_queue_range(kdev, range) \ |
355 | list_for_each_entry(range, &kdev->queue_ranges, list) | 355 | list_for_each_entry(range, &kdev->queue_ranges, list) |
356 | 356 | ||
357 | #define first_queue_range(kdev) \ | 357 | #define first_queue_range(kdev) \ |
358 | list_first_entry(&kdev->queue_ranges, \ | 358 | list_first_entry_or_null(&kdev->queue_ranges, \ |
359 | struct knav_range_info, list) | 359 | struct knav_range_info, list) |
360 | 360 | ||
361 | #define for_each_pool(kdev, pool) \ | 361 | #define for_each_pool(kdev, pool) \ |
362 | list_for_each_entry(pool, &kdev->pools, list) | 362 | list_for_each_entry(pool, &kdev->pools, list) |
diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index 0a2c8634c48b..9b8dd6732681 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c | |||
@@ -785,7 +785,7 @@ void *knav_pool_create(const char *name, | |||
785 | dev_err(kdev->dev, "out of descs in region(%d) for pool(%s)\n", | 785 | dev_err(kdev->dev, "out of descs in region(%d) for pool(%s)\n", |
786 | region_id, name); | 786 | region_id, name); |
787 | ret = -ENOMEM; | 787 | ret = -ENOMEM; |
788 | goto err; | 788 | goto err_unlock; |
789 | } | 789 | } |
790 | 790 | ||
791 | /* Region maintains a sorted (by region offset) list of pools | 791 | /* Region maintains a sorted (by region offset) list of pools |
@@ -815,15 +815,16 @@ void *knav_pool_create(const char *name, | |||
815 | dev_err(kdev->dev, "pool(%s) create failed: fragmented desc pool in region(%d)\n", | 815 | dev_err(kdev->dev, "pool(%s) create failed: fragmented desc pool in region(%d)\n", |
816 | name, region_id); | 816 | name, region_id); |
817 | ret = -ENOMEM; | 817 | ret = -ENOMEM; |
818 | goto err; | 818 | goto err_unlock; |
819 | } | 819 | } |
820 | 820 | ||
821 | mutex_unlock(&knav_dev_lock); | 821 | mutex_unlock(&knav_dev_lock); |
822 | kdesc_fill_pool(pool); | 822 | kdesc_fill_pool(pool); |
823 | return pool; | 823 | return pool; |
824 | 824 | ||
825 | err: | 825 | err_unlock: |
826 | mutex_unlock(&knav_dev_lock); | 826 | mutex_unlock(&knav_dev_lock); |
827 | err: | ||
827 | kfree(pool->name); | 828 | kfree(pool->name); |
828 | devm_kfree(kdev->dev, pool); | 829 | devm_kfree(kdev->dev, pool); |
829 | return ERR_PTR(ret); | 830 | return ERR_PTR(ret); |
@@ -1305,14 +1306,14 @@ static void knav_free_queue_ranges(struct knav_device *kdev) | |||
1305 | static void knav_queue_free_regions(struct knav_device *kdev) | 1306 | static void knav_queue_free_regions(struct knav_device *kdev) |
1306 | { | 1307 | { |
1307 | struct knav_region *region; | 1308 | struct knav_region *region; |
1308 | struct knav_pool *pool; | 1309 | struct knav_pool *pool, *tmp; |
1309 | unsigned size; | 1310 | unsigned size; |
1310 | 1311 | ||
1311 | for (;;) { | 1312 | for (;;) { |
1312 | region = first_region(kdev); | 1313 | region = first_region(kdev); |
1313 | if (!region) | 1314 | if (!region) |
1314 | break; | 1315 | break; |
1315 | list_for_each_entry(pool, ®ion->pools, region_inst) | 1316 | list_for_each_entry_safe(pool, tmp, ®ion->pools, region_inst) |
1316 | knav_pool_destroy(pool); | 1317 | knav_pool_destroy(pool); |
1317 | 1318 | ||
1318 | size = region->virt_end - region->virt_start; | 1319 | size = region->virt_end - region->virt_start; |
@@ -1639,7 +1640,7 @@ static int knav_queue_init_queues(struct knav_device *kdev) | |||
1639 | size = (1 << kdev->inst_shift) * kdev->num_queues_in_use; | 1640 | size = (1 << kdev->inst_shift) * kdev->num_queues_in_use; |
1640 | kdev->instances = devm_kzalloc(kdev->dev, size, GFP_KERNEL); | 1641 | kdev->instances = devm_kzalloc(kdev->dev, size, GFP_KERNEL); |
1641 | if (!kdev->instances) | 1642 | if (!kdev->instances) |
1642 | return -1; | 1643 | return -ENOMEM; |
1643 | 1644 | ||
1644 | for_each_queue_range(kdev, range) { | 1645 | for_each_queue_range(kdev, range) { |
1645 | if (range->ops && range->ops->init_range) | 1646 | if (range->ops && range->ops->init_range) |