[Why]
e1000_set_eeprom() performs a read-modify-write operation when the write
range is not word-aligned. This requires reading the first and last words
of the range from the EEPROM to preserve the unmodified bytes.
However, the code does not check the return value of e1000_read_eeprom().
If the read fails, the operation continues using uninitialized data from
eeprom_buff. This results in corrupted data being written back to the
EEPROM for the boundary words.
Add the missing error checks and abort the operation if reading fails.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Co-developed-by: Iskhakov Daniil <[email protected]>
Signed-off-by: Iskhakov Daniil <[email protected]>
Signed-off-by: Agalakov Daniil <[email protected]>
---
drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index ab232b3fbbd0..4dcbeabb3ad2 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -496,14 +496,19 @@ static int e1000_set_eeprom(struct net_device *netdev,
*/
ret_val = e1000_read_eeprom(hw, first_word, 1,
&eeprom_buff[0]);
+ if (ret_val)
+ goto out;
+
ptr++;
}
- if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
+ if ((eeprom->offset + eeprom->len) & 1) {
/* need read/modify/write of last changed EEPROM word
* only the first byte of the word is being modified
*/
ret_val = e1000_read_eeprom(hw, last_word, 1,
&eeprom_buff[last_word -
first_word]);
+ if (ret_val)
+ goto out;
}
/* Device's eeprom is always little-endian, word addressable */
@@ -522,6 +527,7 @@ static int e1000_set_eeprom(struct net_device *netdev,
if ((ret_val == 0) && (first_word <= EEPROM_CHECKSUM_REG))
e1000_update_eeprom_checksum(hw);
+out:
kfree(eeprom_buff);
return ret_val;
}
--
2.51.0