diff options
author | Sultan Alsawaf <sultan@kerneltoast.com> | 2023-01-22 20:59:32 -0800 |
---|---|---|
committer | Sultan Alsawaf <sultan@kerneltoast.com> | 2023-02-28 22:43:37 -0800 |
commit | 35975d90546931de10b014a222a6051f34c62e57 (patch) | |
tree | 71c2eb701b5d34b59417c18b53c59d7da45195ab | |
parent | be864d8e185fe9e699fa661e70e02b319384dee6 (diff) | |
download | xserver-35975d90546931de10b014a222a6051f34c62e57.tar.gz |
modesetting: Fix memory leak on ms_do_pageflip error
The event allocation for ms_do_pageflip is leaked on error because callers
of ms_do_pageflip have no way of knowing whether or not a page flip
succeeded for any CRTCs. If a page flip succeeded for at least one CRTC,
then it's not safe for the caller to free the event allocation, and the
allocation won't be leaked. The event allocation is only leaked when not a
single CRTC's page flip succeeded.
Since all callers of ms_do_pageflip allocate the event pointer, and all of
them intentionally leak the event allocation when ms_do_pageflip returns an
error, just free the event pointer inside ms_do_pageflip when a page flip
doesn't succeed for any CRTC.
Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
Reviewed-by: Martin Roukala <martin.roukala@mupuf.org>
-rw-r--r-- | hw/xfree86/drivers/modesetting/pageflip.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/hw/xfree86/drivers/modesetting/pageflip.c b/hw/xfree86/drivers/modesetting/pageflip.c index 08a1bcd31..94437c0f3 100644 --- a/hw/xfree86/drivers/modesetting/pageflip.c +++ b/hw/xfree86/drivers/modesetting/pageflip.c @@ -336,7 +336,7 @@ ms_do_pageflip(ScreenPtr screen, xf86DrvMsg(scrn->scrnIndex, X_ERROR, "%s: Failed to get GBM BO for flip to new front.\n", log_prefix); - return FALSE; + goto error_free_event; } flipdata = calloc(1, sizeof(struct ms_flipdata)); @@ -344,7 +344,7 @@ ms_do_pageflip(ScreenPtr screen, drmmode_bo_destroy(&ms->drmmode, &new_front_bo); xf86DrvMsg(scrn->scrnIndex, X_ERROR, "%s: Failed to allocate flipdata.\n", log_prefix); - return FALSE; + goto error_free_event; } flipdata->event = event; @@ -465,11 +465,16 @@ error_out: drmmode_bo_destroy(&ms->drmmode, &new_front_bo); /* if only the local reference - free the structure, * else drop the local reference and return */ - if (flipdata->flip_count == 1) + if (flipdata->flip_count == 1) { free(flipdata); - else + } else { flipdata->flip_count--; + return FALSE; + } +error_free_event: + /* Free the event since the caller has no way to know it's safe to free */ + free(event); return FALSE; } |