Commit adfbae9f authored by Lucas De Marchi's avatar Lucas De Marchi

drm/i915/gt: Avoid out-of-bounds access when loading HuC

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: a7b516bd ("drm/i915/huc: Add fetch support for gsc-loaded HuC binary")
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Signed-off-by: default avatarLucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230413200349.3492571-1-lucas.demarchi@intel.com
parent b90b044c
...@@ -488,12 +488,25 @@ static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw, int e) ...@@ -488,12 +488,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) struct intel_uc_fw *uc_fw)
{ {
u32 *dw = (u32 *)fw->data; u32 *dw = (u32 *)fw->data;
u32 version_hi = dw[HUC_GSC_VERSION_HI_DW]; u32 version_hi, version_lo;
u32 version_lo = dw[HUC_GSC_VERSION_LO_DW]; 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.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); uc_fw->file_selected.ver.minor = FIELD_GET(HUC_GSC_MINOR_VER_HI_MASK, version_hi);
...@@ -664,7 +677,7 @@ static int check_fw_header(struct intel_gt *gt, ...@@ -664,7 +677,7 @@ static int check_fw_header(struct intel_gt *gt,
return 0; return 0;
if (uc_fw->loaded_via_gsc) if (uc_fw->loaded_via_gsc)
err = check_gsc_manifest(fw, uc_fw); err = check_gsc_manifest(gt, fw, uc_fw);
else else
err = check_ccs_header(gt, fw, uc_fw); err = check_ccs_header(gt, fw, uc_fw);
if (err) if (err)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment