diff options
| author | Florin Leotescu <florin.leotescu@nxp.com> | 2026-04-29 09:59:53 +0300 |
|---|---|---|
| committer | Guenter Roeck <linux@roeck-us.net> | 2026-06-09 08:22:52 -0700 |
| commit | ee672fef23722f71d7bfa7d5a7f5822b1ca6cfa3 (patch) | |
| tree | 4368a28784d652d6badf1eae1889de44c2de7e2c | |
| parent | d71d17d347deeb674115bf2f883a26c1920e7af6 (diff) | |
hwmon: (emc2305) Fix fan channel index handling
The fan channel index is used to access per-channel data structures.
Validate the index against the number of available channels
before use to prevent out-of-bounds access if an invalid
value is provided.
The thermal registration path currently uses a sequential child index,
which may not match the validated channel from DT. Use the DT "reg"
property when registering cooling devices to ensure consistent
channel handling
Signed-off-by: Florin Leotescu <florin.leotescu@nxp.com>
Link: https://lore.kernel.org/r/20260429065955.2113012-2-florin.leotescu@oss.nxp.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
| -rw-r--r-- | drivers/hwmon/emc2305.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c index 64b213e1451e..f71a0e265924 100644 --- a/drivers/hwmon/emc2305.c +++ b/drivers/hwmon/emc2305.c @@ -548,6 +548,12 @@ static int emc2305_of_parse_pwm_child(struct device *dev, return ret; } + if (ch >= data->pwm_num) { + dev_err(dev, "invalid reg %u for node %pOF (valid range 0-%u)\n", ch, child, + data->pwm_num - 1); + return -EINVAL; + } + ret = of_parse_phandle_with_args(child, "pwms", "#pwm-cells", 0, &args); if (ret) @@ -612,6 +618,7 @@ static int emc2305_probe(struct i2c_client *client) int ret; int i; int pwm_childs; + u32 ch; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) return -ENODEV; @@ -680,12 +687,18 @@ static int emc2305_probe(struct i2c_client *client) if (IS_REACHABLE(CONFIG_THERMAL)) { /* Parse and check for the available PWM child nodes */ if (pwm_childs > 0) { - i = 0; for_each_child_of_node_scoped(dev->of_node, child) { - ret = emc2305_set_single_tz(dev, child, i); + ret = of_property_read_u32(child, "reg", &ch); + if (ret || ch >= data->pwm_num) + continue; + + /* + * emc2305_set_single_tz() uses 0 for the common cooling + * device and 1..pwm_num for individual fan channels. + */ + ret = emc2305_set_single_tz(dev, child, ch + 1); if (ret != 0) return ret; - i++; } } else { ret = emc2305_set_tz(dev); |
