Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 4fd8bce

Browse files
keesbroonie
authored andcommitted
regulator: max77802: Bounds check regulator id against opmode
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>
1 parent fad8ddd commit 4fd8bce

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

drivers/regulator/max77802-regulator.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,11 @@ static int max77802_set_suspend_disable(struct regulator_dev *rdev)
9494
{
9595
unsigned int val = MAX77802_OFF_PWRREQ;
9696
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
97-
int id = rdev_get_id(rdev);
97+
unsigned int id = rdev_get_id(rdev);
9898
int shift = max77802_get_opmode_shift(id);
9999

100+
if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
101+
return -EINVAL;
100102
max77802->opmode[id] = val;
101103
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
102104
rdev->desc->enable_mask, val << shift);
@@ -110,7 +112,7 @@ static int max77802_set_suspend_disable(struct regulator_dev *rdev)
110112
static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
111113
{
112114
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
113-
int id = rdev_get_id(rdev);
115+
unsigned int id = rdev_get_id(rdev);
114116
unsigned int val;
115117
int shift = max77802_get_opmode_shift(id);
116118

@@ -127,6 +129,9 @@ static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
127129
return -EINVAL;
128130
}
129131

132+
if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
133+
return -EINVAL;
134+
130135
max77802->opmode[id] = val;
131136
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
132137
rdev->desc->enable_mask, val << shift);
@@ -135,8 +140,10 @@ static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
135140
static unsigned max77802_get_mode(struct regulator_dev *rdev)
136141
{
137142
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
138-
int id = rdev_get_id(rdev);
143+
unsigned int id = rdev_get_id(rdev);
139144

145+
if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
146+
return -EINVAL;
140147
return max77802_map_mode(max77802->opmode[id]);
141148
}
142149

@@ -160,10 +167,13 @@ static int max77802_set_suspend_mode(struct regulator_dev *rdev,
160167
unsigned int mode)
161168
{
162169
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
163-
int id = rdev_get_id(rdev);
170+
unsigned int id = rdev_get_id(rdev);
164171
unsigned int val;
165172
int shift = max77802_get_opmode_shift(id);
166173

174+
if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
175+
return -EINVAL;
176+
167177
/*
168178
* If the regulator has been disabled for suspend
169179
* then is invalid to try setting a suspend mode.
@@ -209,9 +219,11 @@ static int max77802_set_suspend_mode(struct regulator_dev *rdev,
209219
static int max77802_enable(struct regulator_dev *rdev)
210220
{
211221
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
212-
int id = rdev_get_id(rdev);
222+
unsigned int id = rdev_get_id(rdev);
213223
int shift = max77802_get_opmode_shift(id);
214224

225+
if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
226+
return -EINVAL;
215227
if (max77802->opmode[id] == MAX77802_OFF_PWRREQ)
216228
max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
217229

@@ -495,7 +507,7 @@ static int max77802_pmic_probe(struct platform_device *pdev)
495507

496508
for (i = 0; i < MAX77802_REG_MAX; i++) {
497509
struct regulator_dev *rdev;
498-
int id = regulators[i].id;
510+
unsigned int id = regulators[i].id;
499511
int shift = max77802_get_opmode_shift(id);
500512
int ret;
501513

@@ -513,10 +525,12 @@ static int max77802_pmic_probe(struct platform_device *pdev)
513525
* the hardware reports OFF as the regulator operating mode.
514526
* Default to operating mode NORMAL in that case.
515527
*/
516-
if (val == MAX77802_STATUS_OFF)
517-
max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
518-
else
519-
max77802->opmode[id] = val;
528+
if (id < ARRAY_SIZE(max77802->opmode)) {
529+
if (val == MAX77802_STATUS_OFF)
530+
max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
531+
else
532+
max77802->opmode[id] = val;
533+
}
520534

521535
rdev = devm_regulator_register(&pdev->dev,
522536
&regulators[i], &config);

0 commit comments

Comments
 (0)