aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2014-11-20 07:15:25 -0500
committerArnd Bergmann <arnd@arndb.de>2014-11-20 07:15:25 -0500
commit27bc375a9c50f70a9c600a6771cc50ffd5cf8c98 (patch)
tree362067cd5776615d8ee71bd14b5cf75b1506e932
parent22b7db80a9952d6af27b0cca71e369fdbc5b587f (diff)
parent148bb0439adeeae466dca31dd4c643e194bee023 (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.h8
-rw-r--r--drivers/soc/ti/knav_qmss_queue.c13
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
825err: 825err_unlock:
826 mutex_unlock(&knav_dev_lock); 826 mutex_unlock(&knav_dev_lock);
827err:
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)
1305static void knav_queue_free_regions(struct knav_device *kdev) 1306static 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, &region->pools, region_inst) 1316 list_for_each_entry_safe(pool, tmp, &region->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)