Skip to content

Commit 0a11270

Browse files
lucasdemarchigregkh
authored andcommitted
drm/i915/dmc: protect against reading random memory
commit bc7b488 upstream. While loading the DMC firmware we were double checking the headers made sense, but in no place we checked that we were actually reading memory we were supposed to. This could be wrong in case the firmware file is truncated or malformed. Before this patch: # ls -l /lib/firmware/i915/icl_dmc_ver1_07.bin -rw-r--r-- 1 root root 25716 Feb 1 12:26 icl_dmc_ver1_07.bin # truncate -s 25700 /lib/firmware/i915/icl_dmc_ver1_07.bin # modprobe i915 # dmesg| grep -i dmc [drm:intel_csr_ucode_init [i915]] Loading i915/icl_dmc_ver1_07.bin [drm] Finished loading DMC firmware i915/icl_dmc_ver1_07.bin (v1.7) i.e. it loads random data. Now it fails like below: [drm:intel_csr_ucode_init [i915]] Loading i915/icl_dmc_ver1_07.bin [drm:csr_load_work_fn [i915]] *ERROR* Truncated DMC firmware, rejecting. i915 0000:00:02.0: Failed to load DMC firmware i915/icl_dmc_ver1_07.bin. Disabling runtime power management. i915 0000:00:02.0: DMC firmware homepage: https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/i915 Before reading any part of the firmware file, validate the input first. Fixes: eb80562 ("drm/i915/skl: Add support to load SKL CSR firmware.") Signed-off-by: Lucas De Marchi <[email protected]> Reviewed-by: Rodrigo Vivi <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] (cherry picked from commit bc7b488) Signed-off-by: Jani Nikula <[email protected]> [ Lucas: backported to 4.9+ adjusting the context ] Cc: [email protected] # v4.9+ Signed-off-by: Sasha Levin <[email protected]>
1 parent d271f22 commit 0a11270

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

drivers/gpu/drm/i915/intel_csr.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,17 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
280280
uint32_t i;
281281
uint32_t *dmc_payload;
282282
uint32_t required_version;
283+
size_t fsize;
283284

284285
if (!fw)
285286
return NULL;
286287

288+
fsize = sizeof(struct intel_css_header) +
289+
sizeof(struct intel_package_header) +
290+
sizeof(struct intel_dmc_header);
291+
if (fsize > fw->size)
292+
goto error_truncated;
293+
287294
/* Extract CSS Header information*/
288295
css_header = (struct intel_css_header *)fw->data;
289296
if (sizeof(struct intel_css_header) !=
@@ -349,6 +356,9 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
349356
return NULL;
350357
}
351358
readcount += dmc_offset;
359+
fsize += dmc_offset;
360+
if (fsize > fw->size)
361+
goto error_truncated;
352362

353363
/* Extract dmc_header information. */
354364
dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
@@ -379,6 +389,10 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
379389

380390
/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
381391
nbytes = dmc_header->fw_size * 4;
392+
fsize += nbytes;
393+
if (fsize > fw->size)
394+
goto error_truncated;
395+
382396
if (nbytes > CSR_MAX_FW_SIZE) {
383397
DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
384398
return NULL;
@@ -392,6 +406,10 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
392406
}
393407

394408
return memcpy(dmc_payload, &fw->data[readcount], nbytes);
409+
410+
error_truncated:
411+
DRM_ERROR("Truncated DMC firmware, rejecting.\n");
412+
return NULL;
395413
}
396414

397415
static void csr_load_work_fn(struct work_struct *work)

0 commit comments

Comments
 (0)