]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-5.1/drm-i915-dmc-protect-against-reading-random-memory.patch
move all the pending queues back to their "real" places
[thirdparty/kernel/stable-queue.git] / queue-5.1 / drm-i915-dmc-protect-against-reading-random-memory.patch
1 From 326fb6dd1483c985a6ef47db3fa8788bb99e8b83 Mon Sep 17 00:00:00 2001
2 From: Lucas De Marchi <lucas.demarchi@intel.com>
3 Date: Wed, 5 Jun 2019 16:55:35 -0700
4 Subject: drm/i915/dmc: protect against reading random memory
5
6 From: Lucas De Marchi <lucas.demarchi@intel.com>
7
8 commit 326fb6dd1483c985a6ef47db3fa8788bb99e8b83 upstream.
9
10 While loading the DMC firmware we were double checking the headers made
11 sense, but in no place we checked that we were actually reading memory
12 we were supposed to. This could be wrong in case the firmware file is
13 truncated or malformed.
14
15 Before this patch:
16 # ls -l /lib/firmware/i915/icl_dmc_ver1_07.bin
17 -rw-r--r-- 1 root root 25716 Feb 1 12:26 icl_dmc_ver1_07.bin
18 # truncate -s 25700 /lib/firmware/i915/icl_dmc_ver1_07.bin
19 # modprobe i915
20 # dmesg| grep -i dmc
21 [drm:intel_csr_ucode_init [i915]] Loading i915/icl_dmc_ver1_07.bin
22 [drm] Finished loading DMC firmware i915/icl_dmc_ver1_07.bin (v1.7)
23
24 i.e. it loads random data. Now it fails like below:
25 [drm:intel_csr_ucode_init [i915]] Loading i915/icl_dmc_ver1_07.bin
26 [drm:csr_load_work_fn [i915]] *ERROR* Truncated DMC firmware, rejecting.
27 i915 0000:00:02.0: Failed to load DMC firmware i915/icl_dmc_ver1_07.bin. Disabling runtime power management.
28 i915 0000:00:02.0: DMC firmware homepage: https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/i915
29
30 Before reading any part of the firmware file, validate the input first.
31
32 Fixes: eb805623d8b1 ("drm/i915/skl: Add support to load SKL CSR firmware.")
33 Cc: stable@vger.kernel.org
34 Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
35 Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
36 Link: https://patchwork.freedesktop.org/patch/msgid/20190605235535.17791-1-lucas.demarchi@intel.com
37 (cherry picked from commit bc7b488b1d1c71dc4c5182206911127bc6c410d6)
38 Signed-off-by: Jani Nikula <jani.nikula@intel.com>
39 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
40
41 ---
42 drivers/gpu/drm/i915/intel_csr.c | 18 ++++++++++++++++++
43 1 file changed, 18 insertions(+)
44
45 --- a/drivers/gpu/drm/i915/intel_csr.c
46 +++ b/drivers/gpu/drm/i915/intel_csr.c
47 @@ -300,10 +300,17 @@ static u32 *parse_csr_fw(struct drm_i915
48 u32 dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
49 u32 i;
50 u32 *dmc_payload;
51 + size_t fsize;
52
53 if (!fw)
54 return NULL;
55
56 + fsize = sizeof(struct intel_css_header) +
57 + sizeof(struct intel_package_header) +
58 + sizeof(struct intel_dmc_header);
59 + if (fsize > fw->size)
60 + goto error_truncated;
61 +
62 /* Extract CSS Header information*/
63 css_header = (struct intel_css_header *)fw->data;
64 if (sizeof(struct intel_css_header) !=
65 @@ -363,6 +370,9 @@ static u32 *parse_csr_fw(struct drm_i915
66 /* Convert dmc_offset into number of bytes. By default it is in dwords*/
67 dmc_offset *= 4;
68 readcount += dmc_offset;
69 + fsize += dmc_offset;
70 + if (fsize > fw->size)
71 + goto error_truncated;
72
73 /* Extract dmc_header information. */
74 dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
75 @@ -394,6 +404,10 @@ static u32 *parse_csr_fw(struct drm_i915
76
77 /* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
78 nbytes = dmc_header->fw_size * 4;
79 + fsize += nbytes;
80 + if (fsize > fw->size)
81 + goto error_truncated;
82 +
83 if (nbytes > csr->max_fw_size) {
84 DRM_ERROR("DMC FW too big (%u bytes)\n", nbytes);
85 return NULL;
86 @@ -407,6 +421,10 @@ static u32 *parse_csr_fw(struct drm_i915
87 }
88
89 return memcpy(dmc_payload, &fw->data[readcount], nbytes);
90 +
91 +error_truncated:
92 + DRM_ERROR("Truncated DMC firmware, rejecting.\n");
93 + return NULL;
94 }
95
96 static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv)