drivers/regulator/mt6359-regulator.c | 7 +++++++ 1 file changed, 7 insertions(+)
A shift-out-of-bounds will occur as caught by LTP fs:read_all_sys, if
modeset_mask has not been set for MT6359_LDO_LINEAR regulators.
Example command on MediaTek Genio 1200-EVK:
# cat /sys/devices/platform/soc/10024000.pwrap/10024000.pwrap\:pmic/regulator/regulator.28/opmode
This patch initializes the member modeset_reg to zero, and checks it
before any further actions.
The related log:
UBSAN: shift-out-of-bounds in ../drivers/regulator/mt6359-regulator.c:281:9
shift exponent -1 is negative
CPU: 1 UID: 0 PID: 4473 Comm: cat Not tainted 6.11.0-rc2-custom #1
Hardware name: Unknown Unknown Product/Unknown Product, BIOS 2022.10 10/01/2022
Call trace:
dump_backtrace+0xa0/0x148
show_stack+0x20/0x48
dump_stack_lvl+0x80/0x130
dump_stack+0x18/0x30
__ubsan_handle_shift_out_of_bounds+0x144/0x250
mt6359_regulator_get_mode+0x154/0x160 [mt6359_regulator]
opmode_show+0x84/0x150
dev_attr_show+0x28/0xa8
sysfs_kf_seq_show+0x90/0x180
kernfs_seq_show+0x34/0x60
seq_read_iter+0x1f0/0x518
kernfs_fop_read_iter+0x170/0x220
vfs_read+0x288/0x338
ksys_read+0x70/0x120
__arm64_sys_read+0x24/0x48
invoke_syscall+0x70/0x120
el0_svc_common.constprop.0+0x48/0x138
do_el0_svc+0x28/0x58
el0_svc+0x40/0x1a8
el0t_64_sync_handler+0x15c/0x178
el0t_64_sync+0x1a8/0x1b0
---[ end trace ]---
Fixes: d6208ba87066 ("regulator: mt6359: Remove shift fields from struct mt6359_regulator_info")
Suggested-by: Yu-wen Fang <yu-wen.fang@mediatek.com>
Signed-off-by: Jian Hui Lee <jianhui.lee@canonical.com>
---
drivers/regulator/mt6359-regulator.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/regulator/mt6359-regulator.c b/drivers/regulator/mt6359-regulator.c
index c8a788858824..24b1dcc5eee8 100644
--- a/drivers/regulator/mt6359-regulator.c
+++ b/drivers/regulator/mt6359-regulator.c
@@ -88,6 +88,7 @@ struct mt6359_regulator_info {
.enable_reg = _enable_reg, \
.enable_mask = BIT(0), \
}, \
+ .modeset_reg = 0, \
.status_reg = _status_reg, \
.qi = BIT(0), \
}
@@ -270,6 +271,9 @@ static unsigned int mt6359_regulator_get_mode(struct regulator_dev *rdev)
struct mt6359_regulator_info *info = rdev_get_drvdata(rdev);
int ret, regval;
+ if (!info->modeset_reg)
+ return REGULATOR_MODE_NORMAL;
+
ret = regmap_read(rdev->regmap, info->modeset_reg, ®val);
if (ret != 0) {
dev_err(&rdev->dev,
@@ -303,6 +307,9 @@ static int mt6359_regulator_set_mode(struct regulator_dev *rdev,
int ret = 0, val;
int curr_mode;
+ if (!info->modeset_reg)
+ return -EINVAL;
+
curr_mode = mt6359_regulator_get_mode(rdev);
switch (mode) {
case REGULATOR_MODE_FAST:
--
2.43.0
On Thu, Aug 29, 2024 at 10:58:07AM +0800, Jian Hui Lee wrote: > A shift-out-of-bounds will occur as caught by LTP fs:read_all_sys, if > modeset_mask has not been set for MT6359_LDO_LINEAR regulators. > > Example command on MediaTek Genio 1200-EVK: > # cat /sys/devices/platform/soc/10024000.pwrap/10024000.pwrap\:pmic/regulator/regulator.28/opmode > > This patch initializes the member modeset_reg to zero, and checks it > before any further actions. It would be better to fix this by not registering any mode operations for the relevant regulators, that will catch these and any other or future issues.
© 2016 - 2024 Red Hat, Inc.