hwmon: (aspeed-pwm-tacho) Fix -Wstringop-overflow warning in aspeed_create_fan_tach_channel()
Subsystems (2)
PATCH 1/1 hwmon: (aspeed-pwm-tacho) Fix -Wstringop-overflow warning in aspeed_create_fan_tach_channel()
Based on the documentation below, the maximum number of Fan tach channels is 16:
Documentation/devicetree/bindings/hwmon/aspeed-pwm-tacho.txt:45:
45 - aspeed,fan-tach-ch : should specify the Fan tach input channel.
46 integer value in the range 0 through 15, with 0 indicating 47 Fan tach channel 0 and 15 indicating Fan tach channel 15. 48 At least one Fan tach input channel is required.
However, the compiler doesn't know that, and legitimaly warns about a potential overwrite in array u8 fan_tach_ch_source[16] in struct aspeed_pwm_tacho_data, in case index takes a value outside the boundaries of the array:
drivers/hwmon/aspeed-pwm-tacho.c:
179 struct aspeed_pwm_tacho_data {
...
184 bool fan_tach_present[16];
...
193 u8 fan_tach_ch_source[16];
...
196 };
In function ?aspeed_create_fan_tach_channel?,
inlined from ?aspeed_create_fan? at drivers/hwmon/aspeed-pwm-tacho.c:877:2,
inlined from ?aspeed_pwm_tacho_probe? at drivers/hwmon/aspeed-pwm-tacho.c:936:9:drivers/hwmon/aspeed-pwm-tacho.c:751:49: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
751 | priv->fan_tach_ch_source[index] = pwm_source;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
drivers/hwmon/aspeed-pwm-tacho.c: In function ?aspeed_pwm_tacho_probe?:
drivers/hwmon/aspeed-pwm-tacho.c:193:12: note: at offset [48, 255] into destination object ?fan_tach_ch_source? of size 16
193 | u8 fan_tach_ch_source[16];
| ^~~~~~~~~~~~~~~~~~Fix this by sanity checking index before using it to index arrays of size 16 elements in struct aspeed_pwm_tacho_data. Also, and just for completeness, add a pr_err() message to display in the unlikely case 0 > index >= 16.
This is probably the last remaining -Wstringop-overflow issue in the kernel, and this patch helps with the ongoing efforts to enable such compiler option globally.
--- drivers/hwmon/aspeed-pwm-tacho.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
drivers/hwmon/aspeed-pwm-tacho.c +12 -6
@@ -166,6 +166,8 @@#define MAX_CDEV_NAME_LEN 16 +#define MAX_ASPEED_FAN_TACH_CHANNELS 16 +struct aspeed_cooling_device {char name[16 ];struct aspeed_pwm_tacho_data *priv;
@@ -181,7 +183,7 @@ struct aspeed_pwm_tacho_data {struct reset_control *rst;unsigned long clk_freq;bool pwm_present[8 ]; -bool fan_tach_present[16 ]; +bool fan_tach_present[MAX_ASPEED_FAN_TACH_CHANNELS ];u8 type_pwm_clock_unit[3 ];u8 type_pwm_clock_division_h[3 ];u8 type_pwm_clock_division_l[3 ];
@@ -190,7 +192,7 @@ struct aspeed_pwm_tacho_data {u16 type_fan_tach_unit[3 ];u8 pwm_port_type[8 ];u8 pwm_port_fan_ctrl[8 ]; -u8 fan_tach_ch_source[16 ]; +u8 fan_tach_ch_source[MAX_ASPEED_FAN_TACH_CHANNELS ];struct aspeed_cooling_device *cdev[8 ];const struct attribute_group *groups[3 ]; };
@@ -746,10 +748,14 @@ static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tacho_data *priv,for (val =0 ; val < count; val++) { index = fan_tach_ch[val]; -aspeed_set_fan_tach_ch_enable (priv->regmap, index, true); - priv->fan_tach_present[index] = true; - priv->fan_tach_ch_source[index] = pwm_source; -aspeed_set_fan_tach_ch_source (priv->regmap, index, pwm_source); +if (index <MAX_ASPEED_FAN_TACH_CHANNELS ) { +aspeed_set_fan_tach_ch_enable (priv->regmap, index, true); + priv->fan_tach_present[index] = true; + priv->fan_tach_ch_source[index] = pwm_source; +aspeed_set_fan_tach_ch_source (priv->regmap, index, pwm_source); + }else { +pr_err ("Invalid Fan Tach input channel %u\n." , index); + } } }
Signature · 1 line
2.34.1
Guenter Roeck
maintainerQuoted 5 lines · Gustavo A. R. Silva
Based on the documentation below, the maximum number of Fan tach channels is 16:
Documentation/devicetree/bindings/hwmon/aspeed-pwm-tacho.txt:45:
45 - aspeed,fan-tach-ch : should specify the Fan tach input channel.
Quoted 8 lines
46 integer value in the range 0 through 15, with 0 indicating 47 Fan tach channel 0 and 15 indicating Fan tach channel 15. 48 At least one Fan tach input channel is required.However, the compiler doesn't know that, and legitimaly warns about a potential overwrite in array
u8 fan_tach_ch_source[16]instruct aspeed_pwm_tacho_data, in caseindextakes a value outside the boundaries of the array:
All that doesn't warrant introducing checkpatch warnings.
Quoted 20 lines
drivers/hwmon/aspeed-pwm-tacho.c:
179 structaspeed_pwm_tacho_data{
...
184 bool fan_tach_present[16];
...
193 u8 fan_tach_ch_source[16];
...
196 };In function ?aspeed_create_fan_tach_channel?,
inlined from ?aspeed_create_fan? atdrivers/hwmon/aspeed-pwm-tacho.c:877:2,
inlined from ?aspeed_pwm_tacho_probe? atdrivers/hwmon/aspeed-pwm-tacho.c:936:9:drivers/hwmon/aspeed-pwm-tacho.c:751:49: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]751 | priv->fan_tach_ch_source[index] = pwm_source; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~ drivers/hwmon/aspeed-pwm-tacho.c: In function ?aspeed_pwm_tacho_probe?: drivers/hwmon/aspeed-pwm-tacho.c:193:12: note: at offset [48, 255] into destination object ?fan_tach_ch_source? of size 16 193 | u8 fan_tach_ch_source[16]; | ^~~~~~~~~~~~~~~~~~
Quoted 9 lines
Fix this by sanity checking
indexbefore using it to index arrays of size 16 elements instruct aspeed_pwm_tacho_data. Also, and just for completeness, add apr_err()message to display in the unlikely case0 > index >= 16.This is probably the last remaining -Wstringop-overflow issue in the kernel, and this patch helps with the ongoing efforts to enable such compiler option globally.
I am sorry, but this description almost completely misses the point. The real issue is that the values in aspeed,fan-tach-ch are not range checked, which can cause real problems if is elements are set to values larger than 15. This is a real problem and has nothing to do with string overflows.
Quoted 41 lines
Signed-off-by Gustavo A. R. Silva <[email protected]>--- drivers/hwmon/aspeed-pwm-tacho.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)drivers/hwmon/aspeed-pwm-tacho.c +4
-3@@ -166,6 +166,8 @@#define MAX_CDEV_NAME_LEN 16 +#define MAX_ASPEED_FAN_TACH_CHANNELS 16 +struct aspeed_cooling_device {char name[16 ];struct aspeed_pwm_tacho_data *priv;@@ -181,7 +183,7 @@ struct aspeed_pwm_tacho_data {struct reset_control *rst;unsigned long clk_freq;bool pwm_present[8 ]; -bool fan_tach_present[16 ]; +bool fan_tach_present[MAX_ASPEED_FAN_TACH_CHANNELS ];u8 type_pwm_clock_unit[3 ];u8 type_pwm_clock_division_h[3 ];u8 type_pwm_clock_division_l[3 ];@@ -190,7 +192,7 @@ struct aspeed_pwm_tacho_data {u16 type_fan_tach_unit[3 ];u8 pwm_port_type[8 ];u8 pwm_port_fan_ctrl[8 ]; -u8 fan_tach_ch_source[16 ]; +u8 fan_tach_ch_source[MAX_ASPEED_FAN_TACH_CHANNELS ];struct aspeed_cooling_device *cdev[8 ];const struct attribute_group *groups[3 ]; };@@ -746,10 +748,14 @@ static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tacho_data *priv,for (val =0 ; val < count; val++) { index = fan_tach_ch[val]; -aspeed_set_fan_tach_ch_enable (priv->regmap, index, true);
drivers/hwmon/aspeed-pwm-tacho.c static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tacho_data *priv, · line 757
Quoted 10 lines
drivers/hwmon/aspeed-pwm-tacho.c +7
-3- priv->fan_tach_present[index] = true; - priv->fan_tach_ch_source[index] = pwm_source; -aspeed_set_fan_tach_ch_source (priv->regmap, index, pwm_source); +if (index <MAX_ASPEED_FAN_TACH_CHANNELS ) { +aspeed_set_fan_tach_ch_enable (priv->regmap, index, true); + priv->fan_tach_present[index] = true; + priv->fan_tach_ch_source[index] = pwm_source; +aspeed_set_fan_tach_ch_source (priv->regmap, index, pwm_source); + }else { +pr_err ("Invalid Fan Tach input channel %u\n." , index);
This should use dev_err() (and, yes, that means dev needs to be passed as argument), and the function should return -EINVAL if this is encountered. Also, error handling should come first.
if (index >= MAX_ASPEED_FAN_TACH_CHANNELS) {
dev_err(dev, "Invalid Fan Tach input channel %u\n.", index);
return -EINVAL;
}Thanks,
Guenter
Quoted 10 lines · Guenter Roeck
Quoted 9 lines · Gustavo A. R. Silva
Based on the documentation below, the maximum number of Fan tach channels is 16:
Documentation/devicetree/bindings/hwmon/aspeed-pwm-tacho.txt:45:
45 - aspeed,fan-tach-ch : should specify the Fan tach input channel.46 integer value in the range 0 through 15, with 0 indicating 47 Fan tach channel 0 and 15 indicating Fan tach channel 15. 48 At least one Fan tach input channel is required.
Quoted 6 lines
Quoted 4 lines
However, the compiler doesn't know that, and legitimaly warns about a potential overwrite in array
u8 fan_tach_ch_source[16]instruct aspeed_pwm_tacho_data, in caseindextakes a value outside the boundaries of the array:All that doesn't warrant introducing checkpatch warnings.
Do you mean this?
WARNING: Prefer a maximum 75 chars per line (possible unwrapped commit description?) #17:
46 integer value in the range 0 through 15, with 0 indicating
I honestly didn't consider that relevant, and I didn't want to alter the format of the Doc text.
However, if you want me to split any offending line, that's not a problem. Just let me know. :)
Quoted 31 lines
Quoted 21 lines
drivers/hwmon/aspeed-pwm-tacho.c:
179 structaspeed_pwm_tacho_data{
...
184 bool fan_tach_present[16];
...
193 u8 fan_tach_ch_source[16];
...
196 };In function ?aspeed_create_fan_tach_channel?,
inlined from ?aspeed_create_fan? atdrivers/hwmon/aspeed-pwm-tacho.c:877:2,
inlined from ?aspeed_pwm_tacho_probe? atdrivers/hwmon/aspeed-pwm-tacho.c:936:9:drivers/hwmon/aspeed-pwm-tacho.c:751:49: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]751 | priv->fan_tach_ch_source[index] = pwm_source; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~ drivers/hwmon/aspeed-pwm-tacho.c: In function ?aspeed_pwm_tacho_probe?: drivers/hwmon/aspeed-pwm-tacho.c:193:12: note: at offset [48, 255] into destination object ?fan_tach_ch_source? of size 16 193 | u8 fan_tach_ch_source[16]; | ^~~~~~~~~~~~~~~~~~Quoted 9 lines
Fix this by sanity checking
indexbefore using it to index arrays of size 16 elements instruct aspeed_pwm_tacho_data. Also, and just for completeness, add apr_err()message to display in the unlikely case0 > index >= 16.This is probably the last remaining -Wstringop-overflow issue in the kernel, and this patch helps with the ongoing efforts to enable such compiler option globally.
Quoted 5 lines
I am sorry, but this description almost completely misses the point. The real issue is that the values in aspeed,fan-tach-ch are not range checked, which can cause real problems if is elements are set to values larger than 15. This is a real problem and has nothing to do with string overflows.
Yeah, the above paragraph was extra, and I removed it in v2[1]. The rest of the changelog text describes the issue in the code.
Quoted 9 lines
This should use
dev_err()(and, yes, that means dev needs to be passed as argument), and the function should return-EINVALif this is encountered. Also, error handling should come first.if (index >= MAX_ASPEED_FAN_TACH_CHANNELS) { dev_err(dev, "Invalid Fan Tach input channel %u\n.", index); return -EINVAL; }
Done in v2.
Thanks a lot for the feedback.
--
Gustavo
[1] https://lore.kernel.org/linux-hardening/ZVPQJIP26dIzRAr6 at work/