[PATCH] regulator: mt6359: Fix UBSAN shift-out-of-bounds
Jian Hui Lee
jianhui.lee at canonical.com
Wed Aug 28 19:58:07 PDT 2024
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 at mediatek.com>
Signed-off-by: Jian Hui Lee <jianhui.lee at 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
More information about the Linux-mediatek
mailing list