Skip to content

Commit 11ce8fd

Browse files
johnharr-intelrodrigovivi
authored andcommitted
drm/i915/uc: Fix two issues with over-size firmware files
In the case where a firmware file is too large (e.g. someone downloaded a web page ASCII dump from github...), the firmware object is released but the pointer is not zerod. If no other firmware file was found then release would be called again leading to a double kfree. Also, the size check was only being applied to the initial firmware load not any of the subsequent attempts. So move the check into a wrapper that is used for all loads. Fixes: 0162411 ("drm/i915/uc: use different ggtt pin offsets for uc loads") Signed-off-by: John Harrison <John.C.Harrison@Intel.com> Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Cc: Alan Previn <alan.previn.teres.alexis@intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Matt Roper <matthew.d.roper@intel.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Matthew Auld <matthew.auld@intel.com> Cc: "Thomas Hellström" <thomas.hellstrom@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20221221193031.687266-4-John.C.Harrison@Intel.com (cherry picked from commit 4071d98) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
1 parent 3f882f2 commit 11ce8fd

File tree

1 file changed

+28
-14
lines changed

1 file changed

+28
-14
lines changed

drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,32 @@ static int check_ccs_header(struct intel_gt *gt,
545545
return 0;
546546
}
547547

548+
static int try_firmware_load(struct intel_uc_fw *uc_fw, const struct firmware **fw)
549+
{
550+
struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
551+
struct device *dev = gt->i915->drm.dev;
552+
int err;
553+
554+
err = firmware_request_nowarn(fw, uc_fw->file_selected.path, dev);
555+
556+
if (err)
557+
return err;
558+
559+
if ((*fw)->size > INTEL_UC_RSVD_GGTT_PER_FW) {
560+
drm_err(&gt->i915->drm,
561+
"%s firmware %s: size (%zuKB) exceeds max supported size (%uKB)\n",
562+
intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
563+
(*fw)->size / SZ_1K, INTEL_UC_RSVD_GGTT_PER_FW / SZ_1K);
564+
565+
/* try to find another blob to load */
566+
release_firmware(*fw);
567+
*fw = NULL;
568+
return -ENOENT;
569+
}
570+
571+
return 0;
572+
}
573+
548574
/**
549575
* intel_uc_fw_fetch - fetch uC firmware
550576
* @uc_fw: uC firmware
@@ -558,7 +584,6 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
558584
struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
559585
struct drm_i915_private *i915 = gt->i915;
560586
struct intel_uc_fw_file file_ideal;
561-
struct device *dev = i915->drm.dev;
562587
struct drm_i915_gem_object *obj;
563588
const struct firmware *fw = NULL;
564589
bool old_ver = false;
@@ -574,20 +599,9 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
574599
__force_fw_fetch_failures(uc_fw, -EINVAL);
575600
__force_fw_fetch_failures(uc_fw, -ESTALE);
576601

577-
err = firmware_request_nowarn(&fw, uc_fw->file_selected.path, dev);
602+
err = try_firmware_load(uc_fw, &fw);
578603
memcpy(&file_ideal, &uc_fw->file_wanted, sizeof(file_ideal));
579604

580-
if (!err && fw->size > INTEL_UC_RSVD_GGTT_PER_FW) {
581-
drm_err(&i915->drm,
582-
"%s firmware %s: size (%zuKB) exceeds max supported size (%uKB)\n",
583-
intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
584-
fw->size / SZ_1K, INTEL_UC_RSVD_GGTT_PER_FW / SZ_1K);
585-
586-
/* try to find another blob to load */
587-
release_firmware(fw);
588-
err = -ENOENT;
589-
}
590-
591605
/* Any error is terminal if overriding. Don't bother searching for older versions */
592606
if (err && intel_uc_fw_is_overridden(uc_fw))
593607
goto fail;
@@ -608,7 +622,7 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
608622
break;
609623
}
610624

611-
err = firmware_request_nowarn(&fw, uc_fw->file_selected.path, dev);
625+
err = try_firmware_load(uc_fw, &fw);
612626
}
613627

614628
if (err)

0 commit comments

Comments
 (0)