[PATCH] drm/nouveau/acpi: Fix memory leak in nouveau_acpi_edid()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux