From: Rodrigo Vivi <rodrigo.vivi@intel.com>
To: Lucas De Marchi <lucas.demarchi@intel.com>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH 09/10] drm/i915/dmc: protect against reading random memory
Date: Thu, 23 May 2019 11:58:46 -0700 [thread overview]
Message-ID: <20190523185846.GU4441@intel.com> (raw)
In-Reply-To: <20190523082420.10352-9-lucas.demarchi@intel.com>
On Thu, May 23, 2019 at 01:24:19AM -0700, Lucas De Marchi wrote:
> 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.
>
> Before parsing any part of the firmware, validate the input first.
>
> Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
I wonder if this patch should be the first one on the series
for easy backport if needed.
Maybe cc: Stable?
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
> ---
> drivers/gpu/drm/i915/intel_csr.c | 71 ++++++++++++++++++++++++--------
> 1 file changed, 53 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
> index 7ff08de83cc6..b7181ca6c8f5 100644
> --- a/drivers/gpu/drm/i915/intel_csr.c
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -360,7 +360,8 @@ static u32 find_dmc_fw_offset(const struct intel_fw_info *fw_info,
> }
>
> static u32 parse_csr_fw_dmc(struct intel_csr *csr,
> - const struct intel_dmc_header_base *dmc_header)
> + const struct intel_dmc_header_base *dmc_header,
> + size_t rem_size)
> {
> unsigned int header_len_bytes, dmc_header_size, payload_size, i;
> const u32 *mmioaddr, *mmiodata;
> @@ -375,6 +376,9 @@ static u32 parse_csr_fw_dmc(struct intel_csr *csr,
> const struct intel_dmc_header_v3 *v3 =
> (const struct intel_dmc_header_v3 *)dmc_header;
>
> + if (rem_size < sizeof(struct intel_dmc_header_v3))
> + goto error_truncated;
> +
> mmioaddr = v3->mmioaddr;
> mmiodata = v3->mmiodata;
> mmio_count = v3->mmio_count;
> @@ -386,6 +390,9 @@ static u32 parse_csr_fw_dmc(struct intel_csr *csr,
> const struct intel_dmc_header_v1 *v1 =
> (const struct intel_dmc_header_v1 *)dmc_header;
>
> + if (rem_size < sizeof(struct intel_dmc_header_v1))
> + goto error_truncated;
> +
> mmioaddr = v1->mmioaddr;
> mmiodata = v1->mmiodata;
> mmio_count = v1->mmio_count;
> @@ -404,6 +411,8 @@ static u32 parse_csr_fw_dmc(struct intel_csr *csr,
> return 0;
> }
>
> + rem_size -= header_len_bytes;
> +
> /* Cache the dmc header info. */
> if (mmio_count > mmio_count_max) {
> DRM_ERROR("DMC firmware has wrong mmio count %u\n", mmio_count);
> @@ -424,6 +433,9 @@ static u32 parse_csr_fw_dmc(struct intel_csr *csr,
>
> /* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
> payload_size = dmc_header->fw_size * 4;
> + if (rem_size < payload_size)
> + goto error_truncated;
> +
> if (payload_size > csr->max_fw_size) {
> DRM_ERROR("DMC FW too big (%u bytes)\n", payload_size);
> return 0;
> @@ -440,16 +452,25 @@ static u32 parse_csr_fw_dmc(struct intel_csr *csr,
> memcpy(csr->dmc_payload, payload, payload_size);
>
> return header_len_bytes + payload_size;
> +
> +error_truncated:
> + DRM_ERROR("Truncated DMC firmware, refusing.\n");
> + return 0;
> }
>
> static u32
> parse_csr_fw_package(struct intel_csr *csr,
> const struct intel_package_header *package_header,
> - const struct stepping_info *si)
> + const struct stepping_info *si,
> + size_t rem_size)
> {
> - u32 num_entries, max_entries, dmc_offset, r;
> + u32 package_size = sizeof(struct intel_package_header);
> + u32 num_entries, max_entries, dmc_offset;
> const struct intel_fw_info *fw_info;
>
> + if (rem_size < package_size)
> + goto error_truncated;
> +
> if (package_header->header_ver == 1) {
> max_entries = PACKAGE_MAX_FW_INFO_ENTRIES;
> } else if (package_header->header_ver == 2) {
> @@ -460,11 +481,17 @@ parse_csr_fw_package(struct intel_csr *csr,
> return 0;
> }
>
> - if (package_header->header_len * 4 !=
> - sizeof(struct intel_package_header) +
> - max_entries * sizeof(struct intel_fw_info)) {
> + /*
> + * We should always have space for max_entries,
> + * even if not all are used
> + */
> + package_size += max_entries * sizeof(struct intel_fw_info);
> + if (rem_size < package_size)
> + goto error_truncated;
> +
> + if (package_header->header_len * 4 != package_size) {
> DRM_ERROR("DMC firmware has wrong package header length "
> - "(%u bytes)\n", package_header->header_len * 4);
> + "(%u bytes)\n", package_size);
> return 0;
> }
>
> @@ -481,21 +508,24 @@ parse_csr_fw_package(struct intel_csr *csr,
> return 0;
> }
>
> - r = sizeof(struct intel_package_header);
> -
> - /* we always have space for max_entries, even if not all are used */
> - r += max_entries * sizeof(struct intel_fw_info);
> -
> /* dmc_offset is in dwords */
> - r += dmc_offset * 4;
> + return package_size + dmc_offset * 4;
>
> - return r;
> +error_truncated:
> + DRM_ERROR("Truncated DMC firmware, refusing.\n");
> + return 0;
> }
>
> /* Return number of bytes parsed or 0 on error */
> static u32 parse_csr_fw_css(struct intel_csr *csr,
> - struct intel_css_header *css_header)
> + struct intel_css_header *css_header,
> + size_t rem_size)
> {
> + if (rem_size < sizeof(struct intel_css_header)) {
> + DRM_ERROR("Truncated DMC firmware, refusing.\n");
> + return 0;
> + }
> +
> if (sizeof(struct intel_css_header) !=
> (css_header->header_len * 4)) {
> DRM_ERROR("DMC firmware has wrong CSS header length "
> @@ -530,29 +560,34 @@ static void parse_csr_fw(struct drm_i915_private *dev_priv,
> const struct stepping_info *si = intel_get_stepping_info(dev_priv);
> u32 readcount = 0;
> u32 r;
> + size_t rem_size;
>
> if (!fw)
> return;
>
> + rem_size = fw->size;
> +
> /* Extract CSS Header information*/
> css_header = (struct intel_css_header *)fw->data;
> - r = parse_csr_fw_css(csr, css_header);
> + r = parse_csr_fw_css(csr, css_header, rem_size);
> if (!r)
> return;
>
> + rem_size -= r;
> readcount += r;
>
> /* Extract Package Header information*/
> package_header = (struct intel_package_header *)&fw->data[readcount];
> - r = parse_csr_fw_package(csr, package_header, si);
> + r = parse_csr_fw_package(csr, package_header, si, rem_size);
> if (!r)
> return;
>
> + rem_size -= r;
> readcount += r;
>
> /* Extract dmc_header information. */
> dmc_header = (struct intel_dmc_header_base *)&fw->data[readcount];
> - parse_csr_fw_dmc(csr, dmc_header);
> + parse_csr_fw_dmc(csr, dmc_header, rem_size);
> }
>
> static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv)
> --
> 2.21.0
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2019-05-23 18:58 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-23 8:24 [PATCH 01/10] drm/i915/dmc: use kernel types Lucas De Marchi
2019-05-23 8:24 ` [PATCH 02/10] drm/i915/dmc: extract fw_info and table walk from intel_package_header Lucas De Marchi
2019-05-23 17:36 ` Rodrigo Vivi
2019-05-23 17:45 ` Srivatsa, Anusha
2019-05-23 8:24 ` [PATCH 03/10] drm/i915/dmc: add support for package_header with version 2 Lucas De Marchi
2019-05-23 17:43 ` Rodrigo Vivi
2019-05-23 17:55 ` Lucas De Marchi
2019-05-23 17:49 ` Srivatsa, Anusha
2019-05-23 8:24 ` [PATCH 04/10] drm/i915/dmc: extract function to parse css header Lucas De Marchi
2019-05-23 17:45 ` Rodrigo Vivi
2019-05-23 17:51 ` Srivatsa, Anusha
2019-05-23 8:24 ` [PATCH 05/10] drm/i915/dmc: extract function to parse package_header Lucas De Marchi
2019-05-23 18:03 ` Srivatsa, Anusha
2019-05-23 8:24 ` [PATCH 06/10] drm/i915/dmc: extract function to parse dmc_header Lucas De Marchi
2019-05-23 18:22 ` Srivatsa, Anusha
2019-05-23 8:24 ` [PATCH 07/10] drm/i915/dmc: add support to load dmc_header version 3 Lucas De Marchi
2019-05-23 18:26 ` Srivatsa, Anusha
2019-05-23 18:57 ` Rodrigo Vivi
2019-05-23 19:25 ` Lucas De Marchi
2019-05-23 23:27 ` Rodrigo Vivi
2019-05-23 8:24 ` [PATCH 08/10] drm/i915/dmc: remove redundant return in parse_csr_fw() Lucas De Marchi
2019-05-23 18:28 ` Srivatsa, Anusha
2019-05-23 8:24 ` [PATCH 09/10] drm/i915/dmc: protect against reading random memory Lucas De Marchi
2019-05-23 18:58 ` Rodrigo Vivi [this message]
2019-05-23 19:41 ` Lucas De Marchi
2019-05-23 8:24 ` [PATCH 10/10] drm/i915/dmc: protect against loading wrong firmware Lucas De Marchi
2019-05-23 19:00 ` Rodrigo Vivi
2019-05-23 16:13 ` ✓ Fi.CI.BAT: success for series starting with [01/10] drm/i915/dmc: use kernel types Patchwork
2019-05-23 17:32 ` [PATCH 01/10] " Srivatsa, Anusha
2019-05-23 17:34 ` Rodrigo Vivi
2019-05-24 23:56 ` ✓ Fi.CI.IGT: success for series starting with [01/10] " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190523185846.GU4441@intel.com \
--to=rodrigo.vivi@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=lucas.demarchi@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.