mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 17:40:11 +01:00
zink: fix heap-use-after-free on batch_state with sub-allocated pipe_resources
zink_bo_create can run into a heap-use-after-free when the bo is still referencing an batch_state from an older destroyed context. In order to fix this, every context gives back their batch_states to the zink, where they can be reused from for new contexts. Cc: mesa-stable Suggested-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26889>
This commit is contained in:
parent
e2a7c877ad
commit
b06f6e00fb
4 changed files with 50 additions and 2 deletions
|
|
@ -446,6 +446,18 @@ get_batch_state(struct zink_context *ctx, struct zink_batch *batch)
|
||||||
if (bs == ctx->last_free_batch_state)
|
if (bs == ctx->last_free_batch_state)
|
||||||
ctx->last_free_batch_state = NULL;
|
ctx->last_free_batch_state = NULL;
|
||||||
}
|
}
|
||||||
|
/* try from the ones that are given back to the screen next */
|
||||||
|
if (!bs) {
|
||||||
|
simple_mtx_lock(&screen->free_batch_states_lock);
|
||||||
|
if (screen->free_batch_states) {
|
||||||
|
bs = screen->free_batch_states;
|
||||||
|
bs->ctx = ctx;
|
||||||
|
screen->free_batch_states = bs->next;
|
||||||
|
if (bs == screen->last_free_batch_state)
|
||||||
|
screen->last_free_batch_state = NULL;
|
||||||
|
}
|
||||||
|
simple_mtx_unlock(&screen->free_batch_states_lock);
|
||||||
|
}
|
||||||
if (!bs && ctx->batch_states) {
|
if (!bs && ctx->batch_states) {
|
||||||
/* states are stored sequentially, so if the first one doesn't work, none of them will */
|
/* states are stored sequentially, so if the first one doesn't work, none of them will */
|
||||||
if (zink_screen_check_last_finished(screen, ctx->batch_states->fence.batch_id) ||
|
if (zink_screen_check_last_finished(screen, ctx->batch_states->fence.batch_id) ||
|
||||||
|
|
|
||||||
|
|
@ -162,16 +162,41 @@ zink_context_destroy(struct pipe_context *pctx)
|
||||||
while (bs) {
|
while (bs) {
|
||||||
struct zink_batch_state *bs_next = bs->next;
|
struct zink_batch_state *bs_next = bs->next;
|
||||||
zink_clear_batch_state(ctx, bs);
|
zink_clear_batch_state(ctx, bs);
|
||||||
zink_batch_state_destroy(screen, bs);
|
/* restore link as we insert them into the screens free_batch_states
|
||||||
|
* list below
|
||||||
|
*/
|
||||||
|
bs->next = bs_next;
|
||||||
bs = bs_next;
|
bs = bs_next;
|
||||||
}
|
}
|
||||||
bs = ctx->free_batch_states;
|
bs = ctx->free_batch_states;
|
||||||
while (bs) {
|
while (bs) {
|
||||||
struct zink_batch_state *bs_next = bs->next;
|
struct zink_batch_state *bs_next = bs->next;
|
||||||
zink_clear_batch_state(ctx, bs);
|
zink_clear_batch_state(ctx, bs);
|
||||||
zink_batch_state_destroy(screen, bs);
|
/* restore link as we insert them into the screens free_batch_states
|
||||||
|
* list below
|
||||||
|
*/
|
||||||
|
bs->next = bs_next;
|
||||||
bs = bs_next;
|
bs = bs_next;
|
||||||
}
|
}
|
||||||
|
simple_mtx_lock(&screen->free_batch_states_lock);
|
||||||
|
if (ctx->batch_states) {
|
||||||
|
if (screen->free_batch_states)
|
||||||
|
screen->last_free_batch_state->next = ctx->batch_states;
|
||||||
|
else {
|
||||||
|
screen->free_batch_states = ctx->batch_states;
|
||||||
|
screen->last_free_batch_state = screen->free_batch_states;
|
||||||
|
}
|
||||||
|
while (screen->last_free_batch_state->next)
|
||||||
|
screen->last_free_batch_state = screen->last_free_batch_state->next;
|
||||||
|
}
|
||||||
|
if (ctx->free_batch_states) {
|
||||||
|
if (screen->free_batch_states)
|
||||||
|
screen->last_free_batch_state->next = ctx->free_batch_states;
|
||||||
|
else
|
||||||
|
screen->free_batch_states = ctx->free_batch_states;
|
||||||
|
screen->last_free_batch_state = ctx->last_free_batch_state;
|
||||||
|
}
|
||||||
|
simple_mtx_unlock(&screen->free_batch_states_lock);
|
||||||
if (ctx->batch.state) {
|
if (ctx->batch.state) {
|
||||||
zink_clear_batch_state(ctx, ctx->batch.state);
|
zink_clear_batch_state(ctx, ctx->batch.state);
|
||||||
zink_batch_state_destroy(screen, ctx->batch.state);
|
zink_batch_state_destroy(screen, ctx->batch.state);
|
||||||
|
|
|
||||||
|
|
@ -1463,6 +1463,12 @@ static void
|
||||||
zink_destroy_screen(struct pipe_screen *pscreen)
|
zink_destroy_screen(struct pipe_screen *pscreen)
|
||||||
{
|
{
|
||||||
struct zink_screen *screen = zink_screen(pscreen);
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
struct zink_batch_state *bs = screen->free_batch_states;
|
||||||
|
while (bs) {
|
||||||
|
struct zink_batch_state *bs_next = bs->next;
|
||||||
|
zink_batch_state_destroy(screen, bs);
|
||||||
|
bs = bs_next;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_RENDERDOC_APP_H
|
#ifdef HAVE_RENDERDOC_APP_H
|
||||||
if (screen->renderdoc_capture_all && p_atomic_dec_zero(&num_screens))
|
if (screen->renderdoc_capture_all && p_atomic_dec_zero(&num_screens))
|
||||||
|
|
@ -3498,6 +3504,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
|
||||||
screen->base_descriptor_size = MAX4(screen->db_size[0], screen->db_size[1], screen->db_size[2], screen->db_size[3]);
|
screen->base_descriptor_size = MAX4(screen->db_size[0], screen->db_size[1], screen->db_size[2], screen->db_size[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simple_mtx_init(&screen->free_batch_states_lock, mtx_plain);
|
||||||
simple_mtx_init(&screen->dt_lock, mtx_plain);
|
simple_mtx_init(&screen->dt_lock, mtx_plain);
|
||||||
|
|
||||||
util_idalloc_mt_init_tc(&screen->buffer_ids);
|
util_idalloc_mt_init_tc(&screen->buffer_ids);
|
||||||
|
|
|
||||||
|
|
@ -1416,6 +1416,10 @@ struct zink_screen {
|
||||||
simple_mtx_t copy_context_lock;
|
simple_mtx_t copy_context_lock;
|
||||||
struct zink_context *copy_context;
|
struct zink_context *copy_context;
|
||||||
|
|
||||||
|
struct zink_batch_state *free_batch_states; //unused batch states
|
||||||
|
struct zink_batch_state *last_free_batch_state; //for appending
|
||||||
|
simple_mtx_t free_batch_states_lock;
|
||||||
|
|
||||||
simple_mtx_t semaphores_lock;
|
simple_mtx_t semaphores_lock;
|
||||||
struct util_dynarray semaphores;
|
struct util_dynarray semaphores;
|
||||||
struct util_dynarray fd_semaphores;
|
struct util_dynarray fd_semaphores;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue