3.16.62-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Guenter Roeck <[email protected]>

commit c793279c77035053e67937f5743c6ebfc303e7c5 upstream.

Not all fans have a fan pulse register. This can result in reading
beyond the end of REG_FAN_PULSES and FAN_PULSE_SHIFT arrays,
and was reported by smatch as possible error.

1672          for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
                              ^^^^^^^^^^^^^^^^^^^^^^^^
                              This is a 7 element array.
...
1685                  data->fan_pulses[i] =
1686                    (nct6775_read_value(data, data->REG_FAN_PULSES[i])
1687                          >> data->FAN_PULSE_SHIFT[i]) & 0x03;
                                 ^^^^^^^^^^^^^^^^^^^^^^^^
                                 FAN_PULSE_SHIFT is either 5 or 6
                                 elements.

To fix the problem, we have to ensure that all REG_FAN_PULSES and
FAN_PULSE_SHIFT have the appropriate length, and that REG_FAN_PULSES
is only read if the register actually exists.

Fixes: 6c009501ff200 ("hwmon: (nct6775) Add support for NCT6102D/6106D")
Reported-by: Dan Carpenter <[email protected]>
Signed-off-by: Guenter Roeck <[email protected]>
[bwh: Backported to 3.16:
 - NCT6776_REG_FAN_PULSES covers only 3 fans
 - Adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
---
 drivers/hwmon/nct6775.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -269,8 +269,9 @@ static const u16 NCT6775_REG_PWM_READ[]
 
 static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
 static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
-static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
-static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0, 0 };
+static const u16 NCT6775_REG_FAN_PULSES[NUM_FAN] = {
+       0x641, 0x642, 0x643, 0x644 };
+static const u16 NCT6775_FAN_PULSE_SHIFT[NUM_FAN] = { };
 
 static const u16 NCT6775_REG_TEMP[] = {
        0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
@@ -382,7 +383,8 @@ static const u8 NCT6776_REG_PWM_MODE[] =
 static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
 
 static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
-static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
+static const u16 NCT6776_REG_FAN_PULSES[NUM_FAN] = {
+       0x644, 0x645, 0x646 };
 
 static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
        0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e };
@@ -451,7 +453,7 @@ static const s8 NCT6779_BEEP_BITS[] = {
 
 static const u16 NCT6779_REG_FAN[] = {
        0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba };
-static const u16 NCT6779_REG_FAN_PULSES[] = {
+static const u16 NCT6779_REG_FAN_PULSES[NUM_FAN] = {
        0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
 
 static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
@@ -564,8 +566,8 @@ static const u16 NCT6106_REG_TEMP_CONFIG
 
 static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
 static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
-static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 };
-static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 };
+static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6 };
+static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4 };
 
 static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
 static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
@@ -1451,9 +1453,13 @@ static struct nct6775_data *nct6775_upda
                        if (data->has_fan_min & (1 << i))
                                data->fan_min[i] = nct6775_read_value(data,
                                           data->REG_FAN_MIN[i]);
-                       data->fan_pulses[i] =
-                         (nct6775_read_value(data, data->REG_FAN_PULSES[i])
-                               >> data->FAN_PULSE_SHIFT[i]) & 0x03;
+
+                       if (data->REG_FAN_PULSES[i]) {
+                               data->fan_pulses[i] =
+                                 (nct6775_read_value(data,
+                                                     data->REG_FAN_PULSES[i])
+                                  >> data->FAN_PULSE_SHIFT[i]) & 0x03;
+                       }
 
                        nct6775_select_fan_div(dev, data, i, reg);
                }

Reply via email to