diff mbox series

drm/edid: fix invalid EDID extension block filtering

Message ID 20220330170426.349248-1-jani.nikula@intel.com (mailing list archive)
State New, archived
Headers show
Series drm/edid: fix invalid EDID extension block filtering | expand

Commit Message

Jani Nikula March 30, 2022, 5:04 p.m. UTC
The invalid EDID block filtering uses the number of valid EDID
extensions instead of all EDID extensions for looping the extensions in
the copy. This is fine, by coincidence, if all the invalid blocks are at
the end of the EDID. However, it's completely broken if there are
invalid extensions in the middle; the invalid blocks are included and
valid blocks are excluded.

Fix it by modifying the base block after, not before, the copy.

Fixes: 14544d0937bf ("drm/edid: Only print the bad edid when aborting")
Reported-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/drm_edid.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Comments

Ville Syrjala March 30, 2022, 5:14 p.m. UTC | #1
On Wed, Mar 30, 2022 at 08:04:26PM +0300, Jani Nikula wrote:
> The invalid EDID block filtering uses the number of valid EDID
> extensions instead of all EDID extensions for looping the extensions in
> the copy. This is fine, by coincidence, if all the invalid blocks are at
> the end of the EDID. However, it's completely broken if there are
> invalid extensions in the middle; the invalid blocks are included and
> valid blocks are excluded.
> 
> Fix it by modifying the base block after, not before, the copy.
> 
> Fixes: 14544d0937bf ("drm/edid: Only print the bad edid when aborting")
> Reported-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> ---
>  drivers/gpu/drm/drm_edid.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index d79b06f7f34c..8829120470ab 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -2031,9 +2031,6 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
>  
>  		connector_bad_edid(connector, edid, edid[0x7e] + 1);
>  
> -		edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
> -		edid[0x7e] = valid_extensions;
> -
>  		new = kmalloc_array(valid_extensions + 1, EDID_LENGTH,
>  				    GFP_KERNEL);
>  		if (!new)
> @@ -2050,6 +2047,9 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
>  			base += EDID_LENGTH;
>  		}
>  
> +		new[EDID_LENGTH - 1] += new[0x7e] - valid_extensions;
> +		new[0x7e] = valid_extensions;
> +
>  		kfree(edid);
>  		edid = new;
>  	}
> -- 
> 2.30.2
Jani Nikula March 31, 2022, 10:06 a.m. UTC | #2
On Wed, 30 Mar 2022, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> On Wed, Mar 30, 2022 at 08:04:26PM +0300, Jani Nikula wrote:
>> The invalid EDID block filtering uses the number of valid EDID
>> extensions instead of all EDID extensions for looping the extensions in
>> the copy. This is fine, by coincidence, if all the invalid blocks are at
>> the end of the EDID. However, it's completely broken if there are
>> invalid extensions in the middle; the invalid blocks are included and
>> valid blocks are excluded.
>> 
>> Fix it by modifying the base block after, not before, the copy.
>> 
>> Fixes: 14544d0937bf ("drm/edid: Only print the bad edid when aborting")
>> Reported-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
>
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Thanks, pushed to drm-misc-next. I didn't bother with -fixes, because
the bug is ancient and rare, and that would only cause conflicts for me.

BR,
Jani.

>
>> ---
>>  drivers/gpu/drm/drm_edid.c | 6 +++---
>>  1 file changed, 3 insertions(+), 3 deletions(-)
>> 
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index d79b06f7f34c..8829120470ab 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -2031,9 +2031,6 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
>>  
>>  		connector_bad_edid(connector, edid, edid[0x7e] + 1);
>>  
>> -		edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
>> -		edid[0x7e] = valid_extensions;
>> -
>>  		new = kmalloc_array(valid_extensions + 1, EDID_LENGTH,
>>  				    GFP_KERNEL);
>>  		if (!new)
>> @@ -2050,6 +2047,9 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
>>  			base += EDID_LENGTH;
>>  		}
>>  
>> +		new[EDID_LENGTH - 1] += new[0x7e] - valid_extensions;
>> +		new[0x7e] = valid_extensions;
>> +
>>  		kfree(edid);
>>  		edid = new;
>>  	}
>> -- 
>> 2.30.2
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index d79b06f7f34c..8829120470ab 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2031,9 +2031,6 @@  struct edid *drm_do_get_edid(struct drm_connector *connector,
 
 		connector_bad_edid(connector, edid, edid[0x7e] + 1);
 
-		edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
-		edid[0x7e] = valid_extensions;
-
 		new = kmalloc_array(valid_extensions + 1, EDID_LENGTH,
 				    GFP_KERNEL);
 		if (!new)
@@ -2050,6 +2047,9 @@  struct edid *drm_do_get_edid(struct drm_connector *connector,
 			base += EDID_LENGTH;
 		}
 
+		new[EDID_LENGTH - 1] += new[0x7e] - valid_extensions;
+		new[0x7e] = valid_extensions;
+
 		kfree(edid);
 		edid = new;
 	}