aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä2015-12-15 06:18:32 -0600
committerVille Syrjälä2016-01-07 09:40:33 -0600
commite342c0fc250f3f16b817c43e96ab9b839fcb15c2 (patch)
tree4f0e67a91a5c2ca1a663e68556f0327fc5c38738 /xf86drmMode.c
parent242f77ce03f4db371d8de3de1bef8622c0fe7488 (diff)
downloadexternal-libgbm-e342c0fc250f3f16b817c43e96ab9b839fcb15c2.tar.gz
external-libgbm-e342c0fc250f3f16b817c43e96ab9b839fcb15c2.tar.xz
external-libgbm-e342c0fc250f3f16b817c43e96ab9b839fcb15c2.zip
Fix memory leak with drmModeGetConnectorCurrent()
drmModeGetConnectorCurrent() must provide temporary storage for the kernel to fill in at least one mode (asking for !=0 modes is how you prevent the heavyweight probe in the kernel). Currently we malloc that temp storage but we fail to free it before overwriting the pointer with the address of the actual storage we use to store the real mode list we get from the kernel in the second ioctl call. Let's just keep the temporary storage on the stack and thus we avoid the leak and also eliminate some pointless mallocs. Cc: Chris Wilson <chris@chris-wilson.co.uk> Fixes: 5ed5fa10600f ("mode: Retrieve only the current information for a Connector") Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'xf86drmMode.c')
-rw-r--r--xf86drmMode.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/xf86drmMode.c b/xf86drmMode.c
index ab6b5195..77100618 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -475,12 +475,13 @@ _drmModeGetConnector(int fd, uint32_t connector_id, int probe)
475{ 475{
476 struct drm_mode_get_connector conn, counts; 476 struct drm_mode_get_connector conn, counts;
477 drmModeConnectorPtr r = NULL; 477 drmModeConnectorPtr r = NULL;
478 struct drm_mode_modeinfo stack_mode;
478 479
479 memclear(conn); 480 memclear(conn);
480 conn.connector_id = connector_id; 481 conn.connector_id = connector_id;
481 if (!probe) { 482 if (!probe) {
482 conn.count_modes = 1; 483 conn.count_modes = 1;
483 conn.modes_ptr = VOID2U64(drmMalloc(sizeof(struct drm_mode_modeinfo))); 484 conn.modes_ptr = VOID2U64(&stack_mode);
484 } 485 }
485 486
486 if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) 487 if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
@@ -504,7 +505,7 @@ retry:
504 goto err_allocs; 505 goto err_allocs;
505 } else { 506 } else {
506 conn.count_modes = 1; 507 conn.count_modes = 1;
507 conn.modes_ptr = VOID2U64(drmMalloc(sizeof(struct drm_mode_modeinfo))); 508 conn.modes_ptr = VOID2U64(&stack_mode);
508 } 509 }
509 510
510 if (conn.count_encoders) { 511 if (conn.count_encoders) {
@@ -525,7 +526,8 @@ retry:
525 counts.count_encoders < conn.count_encoders) { 526 counts.count_encoders < conn.count_encoders) {
526 drmFree(U642VOID(conn.props_ptr)); 527 drmFree(U642VOID(conn.props_ptr));
527 drmFree(U642VOID(conn.prop_values_ptr)); 528 drmFree(U642VOID(conn.prop_values_ptr));
528 drmFree(U642VOID(conn.modes_ptr)); 529 if (U642VOID(conn.modes_ptr) != &stack_mode)
530 drmFree(U642VOID(conn.modes_ptr));
529 drmFree(U642VOID(conn.encoders_ptr)); 531 drmFree(U642VOID(conn.encoders_ptr));
530 532
531 goto retry; 533 goto retry;
@@ -567,7 +569,8 @@ retry:
567err_allocs: 569err_allocs:
568 drmFree(U642VOID(conn.prop_values_ptr)); 570 drmFree(U642VOID(conn.prop_values_ptr));
569 drmFree(U642VOID(conn.props_ptr)); 571 drmFree(U642VOID(conn.props_ptr));
570 drmFree(U642VOID(conn.modes_ptr)); 572 if (U642VOID(conn.modes_ptr) != &stack_mode)
573 drmFree(U642VOID(conn.modes_ptr));
571 drmFree(U642VOID(conn.encoders_ptr)); 574 drmFree(U642VOID(conn.encoders_ptr));
572 575
573 return r; 576 return r;