Message ID | 1424335255-7517-1-git-send-email-srinivas.kandagatla@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Feb 19, 2015 at 08:40:55AM +0000, Srinivas Kandagatla wrote: > regmap_bulk_write() ends up using the path that invokes _regmap_raw_write(), > however _regmap_raw_write() never checks if the registers that are accessed > are actually within the accessible range. This results in kernel crashes when > trying to access registers beyond max_registers. > > This patch just adds check before accessing the register range. > /* Check for unwritable registers before we start */ > - if (map->writeable_reg) > - for (i = 0; i < val_len / map->format.val_bytes; i++) > - if (!map->writeable_reg(map->dev, > - reg + (i * map->reg_stride))) > - return -EINVAL; > + for (i = 0; i < count; i++) > + if (!regmap_writeable(map, reg + (i * map->reg_stride))) > + return -EINVAL; Your changelog doesn't correspond to what the code is actually doing here... what you're actually doing here is replacing an open coding of regmap_writeable() with calls to the function. The same papering over the cracks concerns do apply here as well, it's not immediately obvious that this is a good fix for the issue you describe.
On 19/02/15 10:31, Mark Brown wrote: > On Thu, Feb 19, 2015 at 08:40:55AM +0000, Srinivas Kandagatla wrote: >> regmap_bulk_write() ends up using the path that invokes _regmap_raw_write(), >> however _regmap_raw_write() never checks if the registers that are accessed >> are actually within the accessible range. This results in kernel crashes when >> trying to access registers beyond max_registers. >> >> This patch just adds check before accessing the register range. > >> /* Check for unwritable registers before we start */ >> - if (map->writeable_reg) >> - for (i = 0; i < val_len / map->format.val_bytes; i++) >> - if (!map->writeable_reg(map->dev, >> - reg + (i * map->reg_stride))) >> - return -EINVAL; >> + for (i = 0; i < count; i++) >> + if (!regmap_writeable(map, reg + (i * map->reg_stride))) >> + return -EINVAL; > > Your changelog doesn't correspond to what the code is actually doing > here... what you're actually doing here is replacing an open coding of > regmap_writeable() with calls to the function. > > The same papering over the cracks concerns do apply here as well, it's > not immediately obvious that this is a good fix for the issue you > describe. Only reason for me to send this patch was that fact that _regmap_raw_write() also suffers from same issue as _regmap_raw_read(), which is "access beyond max_register". Should I drop this patch? Or Adding similar check of max_register before the writing makes sense? --srini
On Thu, Feb 19, 2015 at 11:11:58AM +0000, Srinivas Kandagatla wrote: > On 19/02/15 10:31, Mark Brown wrote: > >Your changelog doesn't correspond to what the code is actually doing > >here... what you're actually doing here is replacing an open coding of > >regmap_writeable() with calls to the function. > Only reason for me to send this patch was that fact that _regmap_raw_write() > also suffers from same issue as _regmap_raw_read(), which is "access beyond > max_register". > Should I drop this patch? > Or > Adding similar check of max_register before the writing makes sense? No, please go and reread your patch - neither your description above nor the changelog match up with what it's actually doing. It looks like a perfectly sensible patch, it just doesn't do what you're saying it does.
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index d480e49..32ce7b3 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1202,16 +1202,14 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, void *buf; int ret = -ENOTSUPP; size_t len; - int i; + int i, count = val_len/map->format.val_bytes; WARN_ON(!map->bus); /* Check for unwritable registers before we start */ - if (map->writeable_reg) - for (i = 0; i < val_len / map->format.val_bytes; i++) - if (!map->writeable_reg(map->dev, - reg + (i * map->reg_stride))) - return -EINVAL; + for (i = 0; i < count; i++) + if (!regmap_writeable(map, reg + (i * map->reg_stride))) + return -EINVAL; if (!map->cache_bypass && map->format.parse_val) { unsigned int ival;
regmap_bulk_write() ends up using the path that invokes _regmap_raw_write(), however _regmap_raw_write() never checks if the registers that are accessed are actually within the accessible range. This results in kernel crashes when trying to access registers beyond max_registers. This patch just adds check before accessing the register range. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> --- drivers/base/regmap/regmap.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)