llvmpipe: fix UAF in lp_scene_is_resource_referenced.

reworked slightly by airlied

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24414>
(cherry picked from commit 87ec9456be)
This commit is contained in:
Martin Stransky 2023-08-01 12:38:16 +10:00 committed by Eric Engestrom
parent 0c6dc68d4c
commit 39d703856c
3 changed files with 27 additions and 18 deletions

View file

@ -1381,7 +1381,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
},

View file

@ -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)

View file

@ -1115,17 +1115,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;
}