diff mbox

drm/i915/bios: handle MIPI Sequence Block v3+ gracefully

Message ID 1442497327-27033-1-git-send-email-jani.nikula@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jani Nikula Sept. 17, 2015, 1:42 p.m. UTC
The VBT MIPI Sequence Block version 3 has forward incompatible changes:

First, the block size in the header has been specified reserved, and the
actual size is a separate 32-bit value within the block. The current
find_section() function to will only look at the size in the block
header, and, depending on what's in that now reserved size field,
continue looking for other sections in the wrong place.

Fix this by taking the new block size field into account. This will
ensure that the lookups for other sections will work properly, as long
as the new 32-bit size does not go beyond the opregion VBT mailbox size.

Second, the contents of the block have been completely
changed. Gracefully refuse parsing the yet unknown data version.

Cc: Deepak M <m.deepak@intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_bios.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

Comments

Daniel Vetter Sept. 23, 2015, 1:31 p.m. UTC | #1
On Thu, Sep 17, 2015 at 04:42:07PM +0300, Jani Nikula wrote:
> The VBT MIPI Sequence Block version 3 has forward incompatible changes:
> 
> First, the block size in the header has been specified reserved, and the
> actual size is a separate 32-bit value within the block. The current
> find_section() function to will only look at the size in the block
> header, and, depending on what's in that now reserved size field,
> continue looking for other sections in the wrong place.
> 
> Fix this by taking the new block size field into account. This will
> ensure that the lookups for other sections will work properly, as long
> as the new 32-bit size does not go beyond the opregion VBT mailbox size.
> 
> Second, the contents of the block have been completely
> changed. Gracefully refuse parsing the yet unknown data version.
> 
> Cc: Deepak M <m.deepak@intel.com>
> Cc: stable@vger.kernel.org
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>

Deepak, ping for review.
-Daniel

> ---
>  drivers/gpu/drm/i915/intel_bios.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
> index c8acc2952f82..68421c273c8c 100644
> --- a/drivers/gpu/drm/i915/intel_bios.c
> +++ b/drivers/gpu/drm/i915/intel_bios.c
> @@ -42,7 +42,7 @@ find_section(const void *_bdb, int section_id)
>  	const struct bdb_header *bdb = _bdb;
>  	const u8 *base = _bdb;
>  	int index = 0;
> -	u16 total, current_size;
> +	u32 total, current_size;
>  	u8 current_id;
>  
>  	/* skip to first section */
> @@ -57,6 +57,10 @@ find_section(const void *_bdb, int section_id)
>  		current_size = *((const u16 *)(base + index));
>  		index += 2;
>  
> +		/* The MIPI Sequence Block v3+ has a separate size field. */
> +		if (current_id == BDB_MIPI_SEQUENCE && *(base + index) >= 3)
> +			current_size = *((const u32 *)(base + index + 1));
> +
>  		if (index + current_size > total)
>  			return NULL;
>  
> @@ -799,6 +803,12 @@ parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
>  		return;
>  	}
>  
> +	/* Fail gracefully for forward incompatible sequence block. */
> +	if (sequence->version >= 3) {
> +		DRM_ERROR("Unable to parse MIPI Sequence Block v3+\n");
> +		return;
> +	}
> +
>  	DRM_DEBUG_DRIVER("Found MIPI sequence block\n");
>  
>  	block_size = get_blocksize(sequence);
> -- 
> 2.1.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Deepak M Sept. 23, 2015, 1:50 p.m. UTC | #2
Reviewed-by: Deepak M <m.deepak@intel.com>

>-----Original Message-----
>From: Daniel Vetter [mailto:daniel.vetter@ffwll.ch] On Behalf Of Daniel
>Vetter
>Sent: Wednesday, September 23, 2015 7:02 PM
>To: Nikula, Jani
>Cc: intel-gfx@lists.freedesktop.org; Deepak, M
>Subject: Re: [Intel-gfx] [PATCH] drm/i915/bios: handle MIPI Sequence Block
>v3+ gracefully
>
>On Thu, Sep 17, 2015 at 04:42:07PM +0300, Jani Nikula wrote:
>> The VBT MIPI Sequence Block version 3 has forward incompatible changes:
>>
>> First, the block size in the header has been specified reserved, and
>> the actual size is a separate 32-bit value within the block. The
>> current
>> find_section() function to will only look at the size in the block
>> header, and, depending on what's in that now reserved size field,
>> continue looking for other sections in the wrong place.
>>
>> Fix this by taking the new block size field into account. This will
>> ensure that the lookups for other sections will work properly, as long
>> as the new 32-bit size does not go beyond the opregion VBT mailbox size.
>>
>> Second, the contents of the block have been completely changed.
>> Gracefully refuse parsing the yet unknown data version.
>>
>> Cc: Deepak M <m.deepak@intel.com>
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
>
>Deepak, ping for review.
>-Daniel
>
>> ---
>>  drivers/gpu/drm/i915/intel_bios.c | 12 +++++++++++-
>>  1 file changed, 11 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_bios.c
>> b/drivers/gpu/drm/i915/intel_bios.c
>> index c8acc2952f82..68421c273c8c 100644
>> --- a/drivers/gpu/drm/i915/intel_bios.c
>> +++ b/drivers/gpu/drm/i915/intel_bios.c
>> @@ -42,7 +42,7 @@ find_section(const void *_bdb, int section_id)
>>  	const struct bdb_header *bdb = _bdb;
>>  	const u8 *base = _bdb;
>>  	int index = 0;
>> -	u16 total, current_size;
>> +	u32 total, current_size;
>>  	u8 current_id;
>>
>>  	/* skip to first section */
>> @@ -57,6 +57,10 @@ find_section(const void *_bdb, int section_id)
>>  		current_size = *((const u16 *)(base + index));
>>  		index += 2;
>>
>> +		/* The MIPI Sequence Block v3+ has a separate size field. */
>> +		if (current_id == BDB_MIPI_SEQUENCE && *(base + index) >=
>3)
>> +			current_size = *((const u32 *)(base + index + 1));
>> +
>>  		if (index + current_size > total)
>>  			return NULL;
>>
>> @@ -799,6 +803,12 @@ parse_mipi(struct drm_i915_private *dev_priv,
>const struct bdb_header *bdb)
>>  		return;
>>  	}
>>
>> +	/* Fail gracefully for forward incompatible sequence block. */
>> +	if (sequence->version >= 3) {
>> +		DRM_ERROR("Unable to parse MIPI Sequence Block v3+\n");
>> +		return;
>> +	}
>> +
>>  	DRM_DEBUG_DRIVER("Found MIPI sequence block\n");
>>
>>  	block_size = get_blocksize(sequence);
>> --
>> 2.1.4
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>--
>Daniel Vetter
>Software Engineer, Intel Corporation
>http://blog.ffwll.ch
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index c8acc2952f82..68421c273c8c 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -42,7 +42,7 @@  find_section(const void *_bdb, int section_id)
 	const struct bdb_header *bdb = _bdb;
 	const u8 *base = _bdb;
 	int index = 0;
-	u16 total, current_size;
+	u32 total, current_size;
 	u8 current_id;
 
 	/* skip to first section */
@@ -57,6 +57,10 @@  find_section(const void *_bdb, int section_id)
 		current_size = *((const u16 *)(base + index));
 		index += 2;
 
+		/* The MIPI Sequence Block v3+ has a separate size field. */
+		if (current_id == BDB_MIPI_SEQUENCE && *(base + index) >= 3)
+			current_size = *((const u32 *)(base + index + 1));
+
 		if (index + current_size > total)
 			return NULL;
 
@@ -799,6 +803,12 @@  parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
 		return;
 	}
 
+	/* Fail gracefully for forward incompatible sequence block. */
+	if (sequence->version >= 3) {
+		DRM_ERROR("Unable to parse MIPI Sequence Block v3+\n");
+		return;
+	}
+
 	DRM_DEBUG_DRIVER("Found MIPI sequence block\n");
 
 	block_size = get_blocksize(sequence);