regulator: max77802: Bounds check regulator id against opmode
[ Upstream commit 4fd8bcec5fd7c0d586206fa2f42bd67b06cdaa7e ] Explicitly bounds-check the id before accessing the opmode array. Seen with GCC 13: ../drivers/regulator/max77802-regulator.c: In function 'max77802_enable': ../drivers/regulator/max77802-regulator.c:217:29: warning: array subscript [0, 41] is outside array bounds of 'unsigned int[42]' [-Warray-bounds=] 217 | if (max77802->opmode[id] == MAX77802_OFF_PWRREQ) | ~~~~~~~~~~~~~~~~^~~~ ../drivers/regulator/max77802-regulator.c:62:22: note: while referencing 'opmode' 62 | unsigned int opmode[MAX77802_REG_MAX]; | ^~~~~~ Cc: Javier Martinez Canillas <javier@dowhile0.org> Cc: Liam Girdwood <lgirdwood@gmail.com> Cc: Mark Brown <broonie@kernel.org> Signed-off-by: Kees Cook <keescook@chromium.org> Acked-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://lore.kernel.org/r/20230127225203.never.864-kees@kernel.org Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
7fae534a30
commit
12527ae49d
@ -95,9 +95,11 @@ static int max77802_set_suspend_disable(struct regulator_dev *rdev)
|
|||||||
{
|
{
|
||||||
unsigned int val = MAX77802_OFF_PWRREQ;
|
unsigned int val = MAX77802_OFF_PWRREQ;
|
||||||
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
||||||
int id = rdev_get_id(rdev);
|
unsigned int id = rdev_get_id(rdev);
|
||||||
int shift = max77802_get_opmode_shift(id);
|
int shift = max77802_get_opmode_shift(id);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
|
||||||
|
return -EINVAL;
|
||||||
max77802->opmode[id] = val;
|
max77802->opmode[id] = val;
|
||||||
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
||||||
rdev->desc->enable_mask, val << shift);
|
rdev->desc->enable_mask, val << shift);
|
||||||
@ -111,7 +113,7 @@ static int max77802_set_suspend_disable(struct regulator_dev *rdev)
|
|||||||
static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||||
{
|
{
|
||||||
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
||||||
int id = rdev_get_id(rdev);
|
unsigned int id = rdev_get_id(rdev);
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
int shift = max77802_get_opmode_shift(id);
|
int shift = max77802_get_opmode_shift(id);
|
||||||
|
|
||||||
@ -128,6 +130,9 @@ static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
max77802->opmode[id] = val;
|
max77802->opmode[id] = val;
|
||||||
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
||||||
rdev->desc->enable_mask, val << shift);
|
rdev->desc->enable_mask, val << shift);
|
||||||
@ -136,8 +141,10 @@ static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
|||||||
static unsigned max77802_get_mode(struct regulator_dev *rdev)
|
static unsigned max77802_get_mode(struct regulator_dev *rdev)
|
||||||
{
|
{
|
||||||
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
||||||
int id = rdev_get_id(rdev);
|
unsigned int id = rdev_get_id(rdev);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
|
||||||
|
return -EINVAL;
|
||||||
return max77802_map_mode(max77802->opmode[id]);
|
return max77802_map_mode(max77802->opmode[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,10 +168,13 @@ static int max77802_set_suspend_mode(struct regulator_dev *rdev,
|
|||||||
unsigned int mode)
|
unsigned int mode)
|
||||||
{
|
{
|
||||||
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
||||||
int id = rdev_get_id(rdev);
|
unsigned int id = rdev_get_id(rdev);
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
int shift = max77802_get_opmode_shift(id);
|
int shift = max77802_get_opmode_shift(id);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the regulator has been disabled for suspend
|
* If the regulator has been disabled for suspend
|
||||||
* then is invalid to try setting a suspend mode.
|
* then is invalid to try setting a suspend mode.
|
||||||
@ -210,9 +220,11 @@ static int max77802_set_suspend_mode(struct regulator_dev *rdev,
|
|||||||
static int max77802_enable(struct regulator_dev *rdev)
|
static int max77802_enable(struct regulator_dev *rdev)
|
||||||
{
|
{
|
||||||
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
|
||||||
int id = rdev_get_id(rdev);
|
unsigned int id = rdev_get_id(rdev);
|
||||||
int shift = max77802_get_opmode_shift(id);
|
int shift = max77802_get_opmode_shift(id);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
|
||||||
|
return -EINVAL;
|
||||||
if (max77802->opmode[id] == MAX77802_OFF_PWRREQ)
|
if (max77802->opmode[id] == MAX77802_OFF_PWRREQ)
|
||||||
max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
|
max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
|
||||||
|
|
||||||
@ -541,7 +553,7 @@ static int max77802_pmic_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
for (i = 0; i < MAX77802_REG_MAX; i++) {
|
for (i = 0; i < MAX77802_REG_MAX; i++) {
|
||||||
struct regulator_dev *rdev;
|
struct regulator_dev *rdev;
|
||||||
int id = regulators[i].id;
|
unsigned int id = regulators[i].id;
|
||||||
int shift = max77802_get_opmode_shift(id);
|
int shift = max77802_get_opmode_shift(id);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -559,10 +571,12 @@ static int max77802_pmic_probe(struct platform_device *pdev)
|
|||||||
* the hardware reports OFF as the regulator operating mode.
|
* the hardware reports OFF as the regulator operating mode.
|
||||||
* Default to operating mode NORMAL in that case.
|
* Default to operating mode NORMAL in that case.
|
||||||
*/
|
*/
|
||||||
|
if (id < ARRAY_SIZE(max77802->opmode)) {
|
||||||
if (val == MAX77802_STATUS_OFF)
|
if (val == MAX77802_STATUS_OFF)
|
||||||
max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
|
max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
|
||||||
else
|
else
|
||||||
max77802->opmode[id] = val;
|
max77802->opmode[id] = val;
|
||||||
|
}
|
||||||
|
|
||||||
rdev = devm_regulator_register(&pdev->dev,
|
rdev = devm_regulator_register(&pdev->dev,
|
||||||
®ulators[i], &config);
|
®ulators[i], &config);
|
||||||
|
Loading…
Reference in New Issue
Block a user