Skip to content

Commit 5cb9af3

Browse files
committed
Merge: ACPI: video: Fix random crashes due to bad kfree()
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1179 A regression has presented during the 10.1 main DRM Backport test, AMD Kraken and AMD Strix freeze at boot after install either before or at the ringloader, and in some cases even anaconda will not boot. This MR contains a single patch fixing the issue extracted from @mlangsdorf ACPI backport MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/880 JIRA: https://issues.redhat.com/browse/RHEL-102414 Signed-off-by: José Expósito <jexposit@redhat.com> Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com> Approved-by: Mark Langsdorf <mlangsdo@redhat.com> Approved-by: Robert Foss <rfoss@kernel.org> Merged-by: Julio Faracco <jfaracco@redhat.com>
2 parents 717ae03 + ebd9bf6 commit 5cb9af3

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

drivers/acpi/acpi_video.c

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -610,16 +610,28 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
610610
return 0;
611611
}
612612

613+
/**
614+
* acpi_video_device_EDID() - Get EDID from ACPI _DDC
615+
* @device: video output device (LCD, CRT, ..)
616+
* @edid: address for returned EDID pointer
617+
* @length: _DDC length to request (must be a multiple of 128)
618+
*
619+
* Get EDID from ACPI _DDC. On success, a pointer to the EDID data is written
620+
* to the @edid address, and the length of the EDID is returned. The caller is
621+
* responsible for freeing the edid pointer.
622+
*
623+
* Return the length of EDID (positive value) on success or error (negative
624+
* value).
625+
*/
613626
static int
614-
acpi_video_device_EDID(struct acpi_video_device *device,
615-
union acpi_object **edid, int length)
627+
acpi_video_device_EDID(struct acpi_video_device *device, void **edid, int length)
616628
{
617-
int status;
629+
acpi_status status;
618630
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
619631
union acpi_object *obj;
620632
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
621633
struct acpi_object_list args = { 1, &arg0 };
622-
634+
int ret;
623635

624636
*edid = NULL;
625637

@@ -636,16 +648,17 @@ acpi_video_device_EDID(struct acpi_video_device *device,
636648

637649
obj = buffer.pointer;
638650

639-
if (obj && obj->type == ACPI_TYPE_BUFFER)
640-
*edid = obj;
641-
else {
651+
if (obj && obj->type == ACPI_TYPE_BUFFER) {
652+
*edid = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL);
653+
ret = *edid ? obj->buffer.length : -ENOMEM;
654+
} else {
642655
acpi_handle_debug(device->dev->handle,
643656
"Invalid _DDC data for length %d\n", length);
644-
status = -EFAULT;
645-
kfree(obj);
657+
ret = -EFAULT;
646658
}
647659

648-
return status;
660+
kfree(obj);
661+
return ret;
649662
}
650663

651664
/* bus */
@@ -1435,9 +1448,7 @@ int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
14351448
{
14361449
struct acpi_video_bus *video;
14371450
struct acpi_video_device *video_device;
1438-
union acpi_object *buffer = NULL;
1439-
acpi_status status;
1440-
int i, length;
1451+
int i, length, ret;
14411452

14421453
if (!device || !acpi_driver_data(device))
14431454
return -EINVAL;
@@ -1477,16 +1488,10 @@ int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
14771488
}
14781489

14791490
for (length = 512; length > 0; length -= 128) {
1480-
status = acpi_video_device_EDID(video_device, &buffer,
1481-
length);
1482-
if (ACPI_SUCCESS(status))
1483-
break;
1491+
ret = acpi_video_device_EDID(video_device, edid, length);
1492+
if (ret > 0)
1493+
return ret;
14841494
}
1485-
if (!length)
1486-
continue;
1487-
1488-
*edid = buffer->buffer.pointer;
1489-
return length;
14901495
}
14911496

14921497
return -ENODEV;

0 commit comments

Comments
 (0)