[PATCH] w1_therm: verify CRC only after a full scratchpad read

Жамбакиев Радий Рикардинович posted 1 patch 2 weeks ago
drivers/w1/slaves/w1_therm.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
[PATCH] w1_therm: verify CRC only after a full scratchpad read
Posted by Жамбакиев Радий Рикардинович 2 weeks ago
From: Radiy Zhambakiev <r.zhambakiev@prosoftsystems.ru>

read_scratchpad() computes the CRC and updates verdict/ret
unconditionally after w1_read_block(), even when it failed and returned
fewer than 9 bytes without writing to info->rom.

info->rom is zeroed at the top of the function, so a failed read leaves
it all zeros. w1_calc_crc8() of eight zero bytes is 0 and info->rom[8]
is also 0, so the 'rom[8] == crc' comparison spuriously matches, verdict
is set and ret becomes 0. That makes the retry loop,
'while (max_trying-- && ret)', exit early and read_scratchpad() report
success with an all-zero scratchpad. Callers such as temperature_show()
then surface a bogus 0 degC reading instead of an error.

Only run the CRC check (and the resulting ret/verdict update) when all
9 bytes were actually read; otherwise keep the -EIO so the loop retries.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Fixes: 308bdb94de0c ("w1_therm: adding resolution sysfs entry")
Signed-off-by: Radiy Zhambakiev <r.zhambakiev@prosoftsystems.ru>
---
 drivers/w1/slaves/w1_therm.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index d96b224e2215..fd8c067a92d4 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -1302,15 +1302,15 @@ static int read_scratchpad(struct w1_slave *sl, struct therm_info *info)
 					"w1_read_block(): returned %u instead of 9.\n",
 					nb_bytes_read);
 				ret = -EIO;
-			}
-
-			info->crc = w1_calc_crc8(info->rom, 8);
+			} else {
+				info->crc = w1_calc_crc8(info->rom, 8);
 
-			if (info->rom[8] == info->crc) {
-				info->verdict = 1;
-				ret = 0;
-			} else
-				ret = -EIO; /* CRC not checked */
+				if (info->rom[8] == info->crc) {
+					info->verdict = 1;
+					ret = 0;
+				} else
+					ret = -EIO; /* CRC not checked */
+			}
 		}
 
 	}
-- 
2.53.0