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;
    }

Reply via email to