Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'acpi-6.13-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI fix from Rafael Wysocki:
"Prevent acpi_video_device_EDID() from returning a pointer to a memory
region that should not be passed to kfree() which causes one of its
users to crash randomly on attempts to free it (Chris Bainbridge)"

* tag 'acpi-6.13-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPI: video: Fix random crashes due to bad kfree()

+28 -23
+27 -22
drivers/acpi/acpi_video.c
··· 610 610 return 0; 611 611 } 612 612 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 + */ 613 626 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) 616 628 { 617 - int status; 629 + acpi_status status; 618 630 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 619 631 union acpi_object *obj; 620 632 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 621 633 struct acpi_object_list args = { 1, &arg0 }; 622 - 634 + int ret; 623 635 624 636 *edid = NULL; 625 637 ··· 648 636 649 637 obj = buffer.pointer; 650 638 651 - if (obj && obj->type == ACPI_TYPE_BUFFER) 652 - *edid = obj; 653 - else { 639 + if (obj && obj->type == ACPI_TYPE_BUFFER) { 640 + *edid = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL); 641 + ret = *edid ? obj->buffer.length : -ENOMEM; 642 + } else { 654 643 acpi_handle_debug(device->dev->handle, 655 644 "Invalid _DDC data for length %d\n", length); 656 - status = -EFAULT; 657 - kfree(obj); 645 + ret = -EFAULT; 658 646 } 659 647 660 - return status; 648 + kfree(obj); 649 + return ret; 661 650 } 662 651 663 652 /* bus */ ··· 1448 1435 { 1449 1436 struct acpi_video_bus *video; 1450 1437 struct acpi_video_device *video_device; 1451 - union acpi_object *buffer = NULL; 1452 - acpi_status status; 1453 - int i, length; 1438 + int i, length, ret; 1454 1439 1455 1440 if (!device || !acpi_driver_data(device)) 1456 1441 return -EINVAL; ··· 1488 1477 } 1489 1478 1490 1479 for (length = 512; length > 0; length -= 128) { 1491 - status = acpi_video_device_EDID(video_device, &buffer, 1492 - length); 1493 - if (ACPI_SUCCESS(status)) 1494 - break; 1480 + ret = acpi_video_device_EDID(video_device, edid, length); 1481 + if (ret > 0) 1482 + return ret; 1495 1483 } 1496 - if (!length) 1497 - continue; 1498 - 1499 - *edid = buffer->buffer.pointer; 1500 - return length; 1501 1484 } 1502 1485 1503 1486 return -ENODEV;
+1 -1
drivers/gpu/drm/nouveau/nouveau_acpi.c
··· 384 384 if (ret < 0) 385 385 return NULL; 386 386 387 - return kmemdup(edid, EDID_LENGTH, GFP_KERNEL); 387 + return edid; 388 388 } 389 389 390 390 bool nouveau_acpi_video_backlight_use_native(void)