• Jacob Keller's avatar
    ice: fix iteration of TLVs in Preserved Fields Area · 03e4a092
    Jacob Keller authored
    The ice_get_pfa_module_tlv() function iterates over the Type-Length-Value
    structures in the Preserved Fields Area (PFA) of the NVM. This is used by
    the driver to access data such as the Part Board Assembly identifier.
    
    The function uses simple logic to iterate over the PFA. First, the pointer
    to the PFA in the NVM is read. Then the total length of the PFA is read
    from the first word.
    
    A pointer to the first TLV is initialized, and a simple loop iterates over
    each TLV. The pointer is moved forward through the NVM until it exceeds the
    PFA area.
    
    The logic seems sound, but it is missing a key detail. The Preserved
    Fields Area length includes one additional final word. This is documented
    in the device data sheet as a dummy word which contains 0xFFFF. All NVMs
    have this extra word.
    
    If the driver tries to scan for a TLV that is not in the PFA, it will read
    past the size of the PFA. It reads and interprets the last dummy word of
    the PFA as a TLV with type 0xFFFF. It then reads the word following the PFA
    as a length.
    
    The PFA resides within the Shadow RAM portion of the NVM, which is
    relatively small. All of its offsets are within a 16-bit size. The PFA
    pointer and TLV pointer are stored by the driver as 16-bit values.
    
    In almost all cases, the word following the PFA will be such that
    interpreting it as a length will result in 16-bit arithmetic overflow. Once
    overflowed, the new next_tlv value is now below the maximum offset of the
    PFA. Thus, the driver will continue to iterate the data as TLVs. In the
    worst case, the driver hits on a sequence of reads which loop back to
    reading the same offsets in an endless loop.
    
    To fix this, we need to correct the loop iteration check to account for
    this extra word at the end of the PFA. This alone is sufficient to resolve
    the known cases of this issue in the field. However, it is plausible that
    an NVM could be misconfigured or have corrupt data which results in the
    same kind of overflow. Protect against this by using check_add_overflow
    when calculating both the maximum offset of the TLVs, and when calculating
    the next_tlv offset at the end of each loop iteration. This ensures that
    the driver will not get stuck in an infinite loop when scanning the PFA.
    
    Fixes: e961b679 ("ice: add board identifier info to devlink .info_get")
    Co-developed-by: default avatarPaul Greenwalt <paul.greenwalt@intel.com>
    Signed-off-by: default avatarPaul Greenwalt <paul.greenwalt@intel.com>
    Reviewed-by: default avatarPrzemek Kitszel <przemyslaw.kitszel@intel.com>
    Tested-by: default avatarPucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com>
    Signed-off-by: default avatarJacob Keller <jacob.e.keller@intel.com>
    Link: https://lore.kernel.org/r/20240603-net-2024-05-30-intel-net-fixes-v2-1-e3563aa89b0c@intel.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
    03e4a092
ice_nvm.c 36.4 KB