wayland: fixed memory corruption issue (write to free'd memory)

pass window and buffer index to buffer_release listener, so that it
fetches actual pointer to released buffer by wayland, instead of
directly passing a pointer to the UwacBuffer, which could result in
heap-use-after-free
This commit is contained in:
dance 2022-01-26 19:52:35 +03:00 committed by akallabeth
parent 4b416968c4
commit cbc6b666ae
2 changed files with 19 additions and 3 deletions

View File

@ -255,6 +255,14 @@ struct uwac_window
int pointer_current_cursor; int pointer_current_cursor;
}; };
/**@brief data to pass to wl_buffer release listener */
struct uwac_buffer_release_data
{
UwacWindow* window;
int bufferIdx;
};
typedef struct uwac_buffer_release_data UwacBufferReleaseData;
/* in uwa-display.c */ /* in uwa-display.c */
UwacEvent* UwacDisplayNewEvent(UwacDisplay* d, int type); UwacEvent* UwacDisplayNewEvent(UwacDisplay* d, int type);
int UwacDisplayWatchFd(UwacDisplay* display, int fd, uint32_t events, UwacTask* task); int UwacDisplayWatchFd(UwacDisplay* display, int fd, uint32_t events, UwacTask* task);

View File

@ -48,7 +48,8 @@ static int bppFromShmFormat(enum wl_shm_format format)
static void buffer_release(void* data, struct wl_buffer* buffer) static void buffer_release(void* data, struct wl_buffer* buffer)
{ {
UwacBuffer* uwacBuffer = (UwacBuffer*)data; UwacBufferReleaseData* releaseData = data;
UwacBuffer* uwacBuffer = &releaseData->window->buffers[releaseData->bufferIdx];
uwacBuffer->used = false; uwacBuffer->used = false;
} }
@ -66,7 +67,10 @@ static void UwacWindowDestroyBuffers(UwacWindow* w)
#else #else
region16_uninit(&buffer->damage); region16_uninit(&buffer->damage);
#endif #endif
UwacBufferReleaseData* releaseData =
(UwacBufferReleaseData*)wl_buffer_get_user_data(buffer->wayland_buffer);
wl_buffer_destroy(buffer->wayland_buffer); wl_buffer_destroy(buffer->wayland_buffer);
free(releaseData);
munmap(buffer->data, buffer->size); munmap(buffer->data, buffer->size);
} }
@ -344,7 +348,8 @@ int UwacWindowShmAllocBuffers(UwacWindow* w, int nbuffers, int allocSize, uint32
for (i = 0; i < nbuffers; i++) for (i = 0; i < nbuffers; i++)
{ {
UwacBuffer* buffer = &w->buffers[w->nbuffers + i]; int bufferIdx = w->nbuffers + i;
UwacBuffer* buffer = &w->buffers[bufferIdx];
#ifdef HAVE_PIXMAN_REGION #ifdef HAVE_PIXMAN_REGION
pixman_region32_init(&buffer->damage); pixman_region32_init(&buffer->damage);
#else #else
@ -354,7 +359,10 @@ int UwacWindowShmAllocBuffers(UwacWindow* w, int nbuffers, int allocSize, uint32
buffer->size = allocSize; buffer->size = allocSize;
buffer->wayland_buffer = buffer->wayland_buffer =
wl_shm_pool_create_buffer(pool, allocSize * i, width, height, w->stride, format); wl_shm_pool_create_buffer(pool, allocSize * i, width, height, w->stride, format);
wl_buffer_add_listener(buffer->wayland_buffer, &buffer_listener, buffer); UwacBufferReleaseData* listener_data = xmalloc(sizeof(UwacBufferReleaseData));
listener_data->window = w;
listener_data->bufferIdx = bufferIdx;
wl_buffer_add_listener(buffer->wayland_buffer, &buffer_listener, listener_data);
} }
wl_shm_pool_destroy(pool); wl_shm_pool_destroy(pool);