The ACPI buffer memory 'edid' should be freed as the buffer is not used after kmemdup(). But we can't free 'edid' directly because it doesn't point to acpi_object which should be passed to kfree(). Make acpi_video_get_edid() get the address of acpi_object instead, so we can free it to prevent memory leak. Fixes: 24b102d3488c ("drm/nouveau: we can't free ACPI EDID, so make a copy that we can") Reported-by: Hanjun Guo <guohanjun@xxxxxxxxxx> Signed-off-by: Yu Liao <liaoyu15@xxxxxxxxxx> --- drivers/acpi/acpi_video.c | 4 ++-- drivers/gpu/drm/nouveau/nouveau_acpi.c | 8 ++++++-- include/acpi/video.h | 5 +++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 32953646caeb..f050a755efef 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -1441,7 +1441,7 @@ acpi_video_switch_brightness(struct work_struct *work) } int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, - void **edid) + union acpi_object **edid) { struct acpi_video_bus *video; struct acpi_video_device *video_device; @@ -1500,7 +1500,7 @@ int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, } } - *edid = buffer->buffer.pointer; + *edid = buffer; return length; } diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 8cf096f841a9..075ecad31572 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -365,7 +365,8 @@ nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { struct acpi_device *acpidev; int type, ret; - void *edid; + union acpi_object *edid; + void *ptr; switch (connector->connector_type) { case DRM_MODE_CONNECTOR_LVDS: @@ -384,7 +385,10 @@ nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) if (ret < 0) return NULL; - return kmemdup(edid, EDID_LENGTH, GFP_KERNEL); + ptr = kmemdup(edid->buffer.pointer, EDID_LENGTH, GFP_KERNEL); + kfree(edid); + + return ptr; } bool nouveau_acpi_video_backlight_use_native(void) diff --git a/include/acpi/video.h b/include/acpi/video.h index a275c35e5249..868749f95a34 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h @@ -19,6 +19,7 @@ struct acpi_video_device_brightness { }; struct acpi_device; +union acpi_object; #define ACPI_VIDEO_CLASS "video" @@ -57,7 +58,7 @@ extern int acpi_video_register(void); extern void acpi_video_unregister(void); extern void acpi_video_register_backlight(void); extern int acpi_video_get_edid(struct acpi_device *device, int type, - int device_id, void **edid); + int device_id, union acpi_object **edid); extern enum acpi_backlight_type acpi_video_get_backlight_type(void); extern bool acpi_video_backlight_use_native(void); /* @@ -73,7 +74,7 @@ static inline int acpi_video_register(void) { return -ENODEV; } static inline void acpi_video_unregister(void) { return; } static inline void acpi_video_register_backlight(void) { return; } static inline int acpi_video_get_edid(struct acpi_device *device, int type, - int device_id, void **edid) + int device_id, union acpi_object **edid) { return -ENODEV; } -- 2.25.1