aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap
diff options
context:
space:
mode:
authorXiubo Li <Li.Xiubo@freescale.com>2014-10-09 05:02:57 -0400
committerMark Brown <broonie@kernel.org>2014-10-20 07:25:02 -0400
commitfb70067e4a2cc45d273864f071fd6cf62143137a (patch)
tree853f7f6971a9d336adb2d32a6a9ac12feb4bc753 /drivers/base/regmap
parent06f9c24e55075e50ebc8b249a7853ad31bc1b3d1 (diff)
regmap: cache: Fix possible ZERO_SIZE_PTR pointer dereferencing error.
When all the registers are volatile(unlikely, but logically and mostly will happen for some 'device' who has very few registers), then the count will be euqal to 0, then kmalloc() will return ZERO_SIZE_PTR, which equals to ((void *)16). So this patch fix this with just doing the zero check before calling kmalloc(). If the count == 0, so we can make sure that all the registers are volatile, so no cache is need. Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r--drivers/base/regmap/regcache.c50
1 files changed, 29 insertions, 21 deletions
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 726d956f6a29..d815929ba745 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -36,6 +36,23 @@ static int regcache_hw_init(struct regmap *map)
36 if (!map->num_reg_defaults_raw) 36 if (!map->num_reg_defaults_raw)
37 return -EINVAL; 37 return -EINVAL;
38 38
39 /* calculate the size of reg_defaults */
40 for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++)
41 if (!regmap_volatile(map, i * map->reg_stride))
42 count++;
43
44 /* all registers are volatile, so just bypass */
45 if (!count) {
46 map->cache_bypass = true;
47 return 0;
48 }
49
50 map->num_reg_defaults = count;
51 map->reg_defaults = kmalloc_array(count, sizeof(struct reg_default),
52 GFP_KERNEL);
53 if (!map->reg_defaults)
54 return -ENOMEM;
55
39 if (!map->reg_defaults_raw) { 56 if (!map->reg_defaults_raw) {
40 u32 cache_bypass = map->cache_bypass; 57 u32 cache_bypass = map->cache_bypass;
41 dev_warn(map->dev, "No cache defaults, reading back from HW\n"); 58 dev_warn(map->dev, "No cache defaults, reading back from HW\n");
@@ -43,33 +60,21 @@ static int regcache_hw_init(struct regmap *map)
43 /* Bypass the cache access till data read from HW*/ 60 /* Bypass the cache access till data read from HW*/
44 map->cache_bypass = 1; 61 map->cache_bypass = 1;
45 tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL); 62 tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
46 if (!tmp_buf) 63 if (!tmp_buf) {
47 return -ENOMEM; 64 ret = -ENOMEM;
65 goto err_free;
66 }
48 ret = regmap_raw_read(map, 0, tmp_buf, 67 ret = regmap_raw_read(map, 0, tmp_buf,
49 map->num_reg_defaults_raw); 68 map->num_reg_defaults_raw);
50 map->cache_bypass = cache_bypass; 69 map->cache_bypass = cache_bypass;
51 if (ret < 0) { 70 if (ret < 0)
52 kfree(tmp_buf); 71 goto err_cache_free;
53 return ret; 72
54 }
55 map->reg_defaults_raw = tmp_buf; 73 map->reg_defaults_raw = tmp_buf;
56 map->cache_free = 1; 74 map->cache_free = 1;
57 } 75 }
58 76
59 /* calculate the size of reg_defaults */
60 for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++)
61 if (!regmap_volatile(map, i * map->reg_stride))
62 count++;
63
64 map->reg_defaults = kmalloc_array(count, sizeof(struct reg_default),
65 GFP_KERNEL);
66 if (!map->reg_defaults) {
67 ret = -ENOMEM;
68 goto err_free;
69 }
70
71 /* fill the reg_defaults */ 77 /* fill the reg_defaults */
72 map->num_reg_defaults = count;
73 for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { 78 for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
74 if (regmap_volatile(map, i * map->reg_stride)) 79 if (regmap_volatile(map, i * map->reg_stride))
75 continue; 80 continue;
@@ -81,9 +86,10 @@ static int regcache_hw_init(struct regmap *map)
81 86
82 return 0; 87 return 0;
83 88
89err_cache_free:
90 kfree(tmp_buf);
84err_free: 91err_free:
85 if (map->cache_free) 92 kfree(map->reg_defaults);
86 kfree(map->reg_defaults_raw);
87 93
88 return ret; 94 return ret;
89} 95}
@@ -147,6 +153,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
147 ret = regcache_hw_init(map); 153 ret = regcache_hw_init(map);
148 if (ret < 0) 154 if (ret < 0)
149 return ret; 155 return ret;
156 if (map->cache_bypass)
157 return 0;
150 } 158 }
151 159
152 if (!map->max_register) 160 if (!map->max_register)