Re: [PATCH v2 4/6] PCI/VPD: Reject resource tags with invalid size

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 09.08.2021 20:46, Bjorn Helgaas wrote:
> On Mon, Aug 09, 2021 at 02:15:20PM -0400, Qian Cai wrote:
>>
>>
>> On 7/29/2021 2:42 PM, Bjorn Helgaas wrote:
>>> From: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
>>>
>>> VPD is limited in size by the 15-bit VPD Address field in the VPD
>>> Capability.  Each resource tag includes a length that determines the
>>> overall size of the resource.  Reject any resources that would extend past
>>> the maximum VPD size.
>>>
>>> Signed-off-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
>>
>> + mlx5_core maintainers
>>
>> Hi there, running the latest linux-next with this commit, our system started to
>> get noisy. Could those indicate some device firmware bugs?
>>
>> [  164.937191] mlx5_core 0000:01:00.0: invalid VPD tag 0x78 at offset 113
>> [  165.933527] mlx5_core 0000:01:00.1: invalid VPD tag 0x78 at offset 113
> 
> Thanks a lot for reporting this!
> 
> I guess VPD contains a tag of 0x78, which is a small resource item
> with name 0xf (an End Tag) and size 0.  Per PNPISA, the End Tag should
> have a length 1, with the single byte being a checksum of the resource
> data.  But the PCI spec doesn't mention that checksum byte, so I think
> we should accept the size 0 without any message.
> 

PCI 2.2 spec includes a VPD example in section I.3.2.
There the end tag is listed as 0x78.

> I think the following patch on top of linux-next should do this:
> 
> diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
> index 5e2e638093f1..d7f705ba6664 100644
> --- a/drivers/pci/vpd.c
> +++ b/drivers/pci/vpd.c
> @@ -69,12 +69,11 @@ EXPORT_SYMBOL(pci_write_vpd);
>   */
>  static size_t pci_vpd_size(struct pci_dev *dev)
>  {
> -	size_t off = 0;
> -	unsigned char header[1+2];	/* 1 byte tag, 2 bytes length */
> +	size_t off = 0, size;
> +	unsigned char tag, header[1+2];	/* 1 byte tag, 2 bytes length */
>  
>  	while (pci_read_vpd(dev, off, 1, header) == 1) {
> -		unsigned char tag;
> -		size_t size;
> +		size = 0;
>  
>  		if (off == 0 && (header[0] == 0x00 || header[0] == 0xff))
>  			goto error;
> @@ -95,7 +94,7 @@ static size_t pci_vpd_size(struct pci_dev *dev)
>  			/* Short Resource Data Type Tag */
>  			tag = pci_vpd_srdt_tag(header);
>  			size = pci_vpd_srdt_size(header);
> -			if (size == 0 || off + size > PCI_VPD_MAX_SIZE)
> +			if (off + size > PCI_VPD_MAX_SIZE)
>  				goto error;
>  
>  			off += PCI_VPD_SRDT_TAG_SIZE + size;
> @@ -106,8 +105,8 @@ static size_t pci_vpd_size(struct pci_dev *dev)
>  	return off;
>  
>  error:
> -	pci_info(dev, "invalid VPD tag %#04x at offset %zu%s\n",
> -		 header[0], off, off == 0 ?
> +	pci_info(dev, "invalid VPD tag %#04x (size %zu) at offset %zu%s\n",
> +		 header[0], size, off, off == 0 ?
>  		 "; assume missing optional EEPROM" : "");
>  	return off;
>  }
> 




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux