Module: Mesa Branch: staging/23.2 Commit: 577e76d76c3042ae246106759f9266aefeb77713 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=577e76d76c3042ae246106759f9266aefeb77713
Author: Martin Stransky <[email protected]> Date: Tue Aug 1 12:38:16 2023 +1000 llvmpipe: fix UAF in lp_scene_is_resource_referenced. reworked slightly by airlied Reviewed-by: Roland Scheidegger <[email protected]> Cc: mesa-stable Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24414> (cherry picked from commit 87ec9456bed3112710b8afe8720279f6ad5f66e2) --- .pick_status.json | 2 +- src/gallium/drivers/llvmpipe/lp_scene.c | 32 ++++++++++++++++++++++++-------- src/gallium/drivers/llvmpipe/lp_setup.c | 11 ++--------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index d796c81213f..17f3df4c630 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -9994,7 +9994,7 @@ "description": "llvmpipe: fix UAF in lp_scene_is_resource_referenced.", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index 96e5b7535bc..7ed08861933 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -219,6 +219,8 @@ lp_scene_begin_rasterization(struct lp_scene *scene) void lp_scene_end_rasterization(struct lp_scene *scene) { + mtx_lock(&scene->mutex); + /* Unmap color buffers */ for (unsigned i = 0; i < scene->fb.nr_cbufs; i++) { if (scene->cbufs[i].map) { @@ -324,6 +326,8 @@ lp_scene_end_rasterization(struct lp_scene *scene) scene->alloc_failed = false; util_unreference_framebuffer_state(&scene->fb); + + mtx_unlock(&scene->mutex); } @@ -402,6 +406,8 @@ lp_scene_add_resource_reference(struct lp_scene *scene, struct resource_ref **list = writeable ? &scene->writeable_resources : &scene->resources; struct resource_ref **last = list; + mtx_lock(&scene->mutex); + /* Look at existing resource blocks: */ for (ref = *list; ref; ref = ref->next) { @@ -410,8 +416,10 @@ lp_scene_add_resource_reference(struct lp_scene *scene, /* Search for this resource: */ for (i = 0; i < ref->count; i++) - if (ref->resource[i] == resource) + if (ref->resource[i] == resource) { + mtx_unlock(&scene->mutex); return true; + } if (ref->count < RESOURCE_REF_SZ) { /* If the block is half-empty, then append the reference here. @@ -425,8 +433,10 @@ lp_scene_add_resource_reference(struct lp_scene *scene, if (!ref) { assert(*last == NULL); *last = lp_scene_alloc(scene, sizeof *ref); - if (*last == NULL) + if (*last == NULL) { + mtx_unlock(&scene->mutex); return false; + } ref = *last; memset(ref, 0, sizeof *ref); @@ -448,14 +458,11 @@ lp_scene_add_resource_reference(struct lp_scene *scene, * next resource added which exceeds 64MB in referenced texture * data. */ - if (!initializing_scene && - scene->resource_reference_size >= LP_SCENE_MAX_RESOURCE_SIZE) - return false; - - return true; + int flush = (initializing_scene || scene->resource_reference_size < LP_SCENE_MAX_RESOURCE_SIZE); + mtx_unlock(&scene->mutex); + return flush; } - /** * Add a reference to a fragment shader variant * Return FALSE if out of memory, TRUE otherwise. @@ -515,6 +522,15 @@ lp_scene_is_resource_referenced(const struct lp_scene *scene, { const struct resource_ref *ref; + /* check the render targets */ + for (unsigned j = 0; j < scene->fb.nr_cbufs; j++) { + if (scene->fb.cbufs[j] && scene->fb.cbufs[j]->texture == resource) + return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; + } + if (scene->fb.zsbuf && scene->fb.zsbuf->texture == resource) { + return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; + } + for (ref = scene->resources; ref; ref = ref->next) { for (int i = 0; i < ref->count; i++) if (ref->resource[i] == resource) diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index b959f7d5fbd..9b58e7158f6 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -960,17 +960,10 @@ lp_setup_is_resource_referenced(const struct lp_setup_context *setup, /* check resources referenced by active scenes */ for (unsigned i = 0; i < setup->num_active_scenes; i++) { struct lp_scene *scene = setup->scenes[i]; - /* check the render targets */ - for (unsigned j = 0; j < scene->fb.nr_cbufs; j++) { - if (scene->fb.cbufs[j] && scene->fb.cbufs[j]->texture == texture) - return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; - } - if (scene->fb.zsbuf && scene->fb.zsbuf->texture == texture) { - return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; - } - /* check resources referenced by the scene */ + mtx_lock(&scene->mutex); unsigned ref = lp_scene_is_resource_referenced(scene, texture); + mtx_unlock(&scene->mutex); if (ref) return ref; }
