Re: [Intel-wired-lan] [PATCH] e100: prevent shift out-of-bounds in e100_eeprom_load

Yalagada Pavan Kumar <[email protected]>
Newsgroups org.kernel.vger.netdev,org.kernel.vger.linux-kernel,org.osuosl.intel-wired-lan
Message-ID <and-4dPXVkwerqZU@user>
On Sun, Aug 09, 2026 at 12:12:31AM +0900, Kohei Enju wrote:
> On 08/07 20:26, [email protected] wrote:
> > From: Yalagada Pavan Kumar <[email protected]>
> > 
> > When reading the EEPROM address length, e100_eeprom_read() can return
> > an invalid length (0 or >= 16). Passing an invalid addr_len to bit-shift
> > operations causes a shift out-of-bounds, triggering a kernel panic or
> > UBSAN warning.
> > 
> > Validate addr_len after reading it from EEPROM and return -EINVAL if
> > the value is out of bounds. Additionally, use 1U to prevent
> > signed integer overflow when calculating eeprom_wc.
> > 
> > Reported-by: [email protected]
> > Tested-by: [email protected]
> > Closes: https://syzkaller.appspot.com/bug?extid=e0abb1d45ac291ebebeb
> > Signed-off-by: Yalagada Pavan Kumar <[email protected]>
> > ---
> > Tested using syzbot c reproducer.
> > ---
> >  drivers/net/ethernet/intel/e100.c | 17 +++++++++++++++--
> >  1 file changed, 15 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
> > index 29960762e64a..1de5cd41ea0c 100644
> > --- a/drivers/net/ethernet/intel/e100.c
> > +++ b/drivers/net/ethernet/intel/e100.c
> > @@ -744,7 +744,12 @@ static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
> >  		 * complete address.  Use this to adjust addr_len. */
> >  		ctrl = ioread8(&nic->csr->eeprom_ctrl_lo);
> >  		if (!(ctrl & eedo) && i > 16) {
> > -			*addr_len -= (i - 16);
> > +			u16 len = i - 16;
> > +
> > +			if (len > *addr_len)
> > +				*addr_len = 0;
> > +			else
> > +				*addr_len -= len;
> >  			i = 17;
> >  		}
> >  
> > @@ -765,7 +770,15 @@ static int e100_eeprom_load(struct nic *nic)
> >  
> >  	/* Try reading with an 8-bit addr len to discover actual addr len */
> >  	e100_eeprom_read(nic, &addr_len, 0);
> > -	nic->eeprom_wc = 1 << addr_len;
> > +
> > +	if (!addr_len || addr_len >= 16) {
> > +		netif_err(nic, probe, nic->netdev,
> > +			"Invalid EEPROM address length %u\n",
> > +			addr_len);
> > +		return -EINVAL;
> 
> An invalid address length here appears to indicate an unexpected
> response from the EEPROM, rather than an invalid argument. Therefore,
> -EINVAL seems somewhat misleading. Would -EIO be more appropriate here?
Agreed, addr_len comes from an unexpected EEPROM response,
so i will change -EINVAL to -EIO.
> 
> Also, e100_eeprom_save() seems to have the same pattern. Shouldn't we
> fix that as well?
yes, i'll fix e100_eeprom_save() as well. 
> 
> > +	}
> > +
> > +	nic->eeprom_wc = 1U << addr_len;
> 
> The commit message says that the U suffix prevents signed integer
> overflow. However, after the validation addr_len is in [1, 15], so 1 <<
> addr_len cannot overflow an int. I think what prevents the out-of-bounds
> shift is the validation, not the U.
Agreed, I'll remove the unnecessary U suffix.
I made these changes and will send v2.
> 
> >  
> >  	for (addr = 0; addr < nic->eeprom_wc; addr++) {
> >  		nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr);
> > -- 
> > 2.43.0
> >
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.