diff mbox series

regulator: mt6359: Fix UBSAN shift-out-of-bounds

Message ID 20240829025807.2455823-1-jianhui.lee@canonical.com (mailing list archive)
State New, archived
Headers show
Series regulator: mt6359: Fix UBSAN shift-out-of-bounds | expand

Commit Message

Jian Hui Lee Aug. 29, 2024, 2:58 a.m. UTC
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(+)

Comments

Mark Brown Aug. 29, 2024, 11:59 a.m. UTC | #1
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.
diff mbox series

Patch

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, &regval);
 	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: