[Intel-gfx] [PATCH] drm/i915/gt: Avoid out-of-bounds access when loading HuC

Ceraolo Spurio, Daniele daniele.ceraolospurio at intel.com
Thu Apr 13 21:50:54 UTC 2023



On 4/13/2023 1:03 PM, Lucas De Marchi wrote:
> When HuC is loaded by GSC, there is no header definition for the kernel
> to look at and firmware is just handed to GSC. However when reading the
> version, it should still check the size of the blob to guarantee it's not
> incurring into out-of-bounds array access.
>
> If firmware is smaller than expected, the following message is now
> printed:
>
> 	# echo boom > /lib/firmware/i915/dg2_huc_gsc.bin
> 	# dmesg | grep -i huc
> 	[drm] GT0: HuC firmware i915/dg2_huc_gsc.bin: invalid size: 5 < 184
> 	[drm] *ERROR* GT0: HuC firmware i915/dg2_huc_gsc.bin: fetch failed -ENODATA
> 	...
>
> Even without this change the size, header and signature are still
> checked by GSC when loading, so this only avoids the out-of-bounds array
> access.
>
> Fixes: a7b516bd981f ("drm/i915/huc: Add fetch support for gsc-loaded HuC binary")
> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
> Cc: Alan Previn <alan.previn.teres.alexis at intel.com>
> Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>

Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>

Daniele

> ---
>   drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 21 +++++++++++++++++----
>   1 file changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
> index 1ac6f9f340e3..a82a53dbbc86 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
> @@ -489,12 +489,25 @@ static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw, int e)
>   	}
>   }
>   
> -static int check_gsc_manifest(const struct firmware *fw,
> +static int check_gsc_manifest(struct intel_gt *gt,
> +			      const struct firmware *fw,
>   			      struct intel_uc_fw *uc_fw)
>   {
>   	u32 *dw = (u32 *)fw->data;
> -	u32 version_hi = dw[HUC_GSC_VERSION_HI_DW];
> -	u32 version_lo = dw[HUC_GSC_VERSION_LO_DW];
> +	u32 version_hi, version_lo;
> +	size_t min_size;
> +
> +	/* Check the size of the blob before examining buffer contents */
> +	min_size = sizeof(u32) * (HUC_GSC_VERSION_LO_DW + 1);
> +	if (unlikely(fw->size < min_size)) {
> +		gt_warn(gt, "%s firmware %s: invalid size: %zu < %zu\n",
> +			intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
> +			fw->size, min_size);
> +		return -ENODATA;
> +	}
> +
> +	version_hi = dw[HUC_GSC_VERSION_HI_DW];
> +	version_lo = dw[HUC_GSC_VERSION_LO_DW];
>   
>   	uc_fw->file_selected.ver.major = FIELD_GET(HUC_GSC_MAJOR_VER_HI_MASK, version_hi);
>   	uc_fw->file_selected.ver.minor = FIELD_GET(HUC_GSC_MINOR_VER_HI_MASK, version_hi);
> @@ -665,7 +678,7 @@ static int check_fw_header(struct intel_gt *gt,
>   		return 0;
>   
>   	if (uc_fw->loaded_via_gsc)
> -		err = check_gsc_manifest(fw, uc_fw);
> +		err = check_gsc_manifest(gt, fw, uc_fw);
>   	else
>   		err = check_ccs_header(gt, fw, uc_fw);
>   	if (err)



More information about the Intel-gfx mailing list