drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 11 +++++++---- drivers/net/ethernet/intel/e1000e/ethtool.c | 10 +++++++++- 2 files changed, 16 insertions(+), 5 deletions(-)
This series refactors the EEPROM write logic in e1000 and e1000e drivers to avoid processing uninitialized memory. Instead of looping over the entire buffer, we now only perform endianness conversion on the boundary words that were actually read from the hardware. Patch 1: e1000: limit endianness conversion to boundary words Patch 2: e1000e: limit endianness conversion to boundary words --- v2: - Moved these improvements to the 'net-next' tree. - Improved commit description for clarity. drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 11 +++++++---- drivers/net/ethernet/intel/e1000e/ethtool.c | 10 +++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) -- 2.51.0
This series refactors the EEPROM write logic in e1000 and e1000e drivers to avoid processing uninitialized memory. Instead of looping over the entire buffer, we now only perform endianness conversion on the boundary words that were actually read from the hardware. Patch 1: e1000: limit endianness conversion to boundary words Patch 2: e1000e: limit endianness conversion to boundary words --- v3: - Reverted to v1's "check-then-convert" logic in patch for e1000e: the return value of e1000_read_nvm() is now checked before performing le16_to_cpus(). - Removed the redundant full-buffer loops in patch for e1000e that caused double endianness conversion in v2. v2: - Moved these improvements to the 'net-next' tree. - Improved commit description for clarity. .../net/ethernet/intel/e1000/e1000_ethtool.c | 11 +++++++---- drivers/net/ethernet/intel/e1000e/ethtool.c | 19 ++++++++++++------- 2 files changed, 19 insertions(+), 11 deletions(-) -- 2.51.0
On Wed, 01. Apr 15:08, Agalakov Daniil wrote: > This series refactors the EEPROM write logic in e1000 and e1000e drivers > to avoid processing uninitialized memory. Instead of looping over the > entire buffer, we now only perform endianness conversion on the boundary > words that were actually read from the hardware. > > Patch 1: e1000: limit endianness conversion to boundary words > Patch 2: e1000e: limit endianness conversion to boundary words > --- Daniil, for future submissions, please post new versions of the patches in a separate email-thread, not In-Reply-To. https://docs.kernel.org/process/maintainer-netdev.html#resending-after-review https://docs.kernel.org/process/maintainer-netdev.html#changes-requested
[Why]
In e1000_set_eeprom(), the eeprom_buff is allocated to hold a range of
words. However, only the boundary words (the first and the last) are
populated from the EEPROM if the write request is not word-aligned.
The words in the middle of the buffer remain uninitialized because they
are intended to be completely overwritten by the new data via memcpy().
The previous implementation had a loop that performed le16_to_cpus()
on the entire buffer. This resulted in endianness conversion being
performed on uninitialized memory for all interior words.
Fix this by converting the endianness only for the boundary words
immediately after they are successfully read from the EEPROM.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Co-developed-by: Iskhakov Daniil <dish@amicon.ru>
Signed-off-by: Iskhakov Daniil <dish@amicon.ru>
Signed-off-by: Agalakov Daniil <ade@amicon.ru>
---
v2:
- Split from the original bugfix series and targeted at 'net-next'.
- Removed the Fixes: tag; limiting the conversion scope is an
improvement to avoid unnecessary processing of uninitialized memory.
- Improved commit description for clarity.
drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index ab232b3fbbd0..38b1f91823ef 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -496,6 +496,10 @@ static int e1000_set_eeprom(struct net_device *netdev,
*/
ret_val = e1000_read_eeprom(hw, first_word, 1,
&eeprom_buff[0]);
+
+ /* Device's eeprom is always little-endian, word addressable */
+ le16_to_cpus(&eeprom_buff[0]);
+
ptr++;
}
if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
@@ -504,11 +508,10 @@ static int e1000_set_eeprom(struct net_device *netdev,
*/
ret_val = e1000_read_eeprom(hw, last_word, 1,
&eeprom_buff[last_word - first_word]);
- }
- /* Device's eeprom is always little-endian, word addressable */
- for (i = 0; i < last_word - first_word + 1; i++)
- le16_to_cpus(&eeprom_buff[i]);
+ /* Device's eeprom is always little-endian, word addressable */
+ le16_to_cpus(&eeprom_buff[last_word - first_word]);
+ }
memcpy(ptr, bytes, eeprom->len);
--
2.51.0
[Why]
In e1000_set_eeprom(), the eeprom_buff is allocated to hold a range of
words. However, only the boundary words (the first and the last) are
populated from the EEPROM if the write request is not word-aligned.
The words in the middle of the buffer remain uninitialized because they
are intended to be completely overwritten by the new data via memcpy().
The previous implementation had a loop that performed le16_to_cpus()
on the entire buffer. This resulted in endianness conversion being
performed on uninitialized memory for all interior words.
Fix this by converting the endianness only for the boundary words
immediately after they are successfully read from the EEPROM.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Co-developed-by: Iskhakov Daniil <dish@amicon.ru>
Signed-off-by: Iskhakov Daniil <dish@amicon.ru>
Signed-off-by: Agalakov Daniil <ade@amicon.ru>
---
v3:
- Reverted to v1's "check-then-convert" logic: the return value of
e1000_read_nvm() is now checked before performing le16_to_cpus().
- Removed the redundant full-buffer loops that caused double endianness
conversion in v2.
v2:
- Split from the original bugfix series and targeted at 'net-next'.
- Removed the Fixes: tag; limiting the conversion scope is an
improvement to avoid unnecessary processing of uninitialized memory.
- Improved commit description for clarity.
- Note on e1000e: this driver already contains the necessary return
value checks for EEPROM reads, so only the endianness conversion
cleanup is included for e1000e.
drivers/net/ethernet/intel/e1000e/ethtool.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index dbed30943ef4..a8b35ae41141 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -583,20 +583,25 @@ static int e1000_set_eeprom(struct net_device *netdev,
/* need read/modify/write of first changed EEPROM word */
/* only the second byte of the word is being modified */
ret_val = e1000_read_nvm(hw, first_word, 1, &eeprom_buff[0]);
+ if (ret_val)
+ goto out;
+
+ /* Device's eeprom is always little-endian, word addressable */
+ le16_to_cpus(&eeprom_buff[0]);
+
ptr++;
}
- if (((eeprom->offset + eeprom->len) & 1) && (!ret_val))
+ 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_nvm(hw, last_word, 1,
&eeprom_buff[last_word - first_word]);
+ if (ret_val)
+ goto out;
- if (ret_val)
- goto out;
-
- /* Device's eeprom is always little-endian, word addressable */
- for (i = 0; i < last_word - first_word + 1; i++)
- le16_to_cpus(&eeprom_buff[i]);
+ /* Device's eeprom is always little-endian, word addressable */
+ le16_to_cpus(&eeprom_buff[last_word - first_word]);
+ }
memcpy(ptr, bytes, eeprom->len);
--
2.51.0
© 2016 - 2026 Red Hat, Inc.