nouveau/ws: make sure we don't submit nonsense
authorKarol Herbst <kherbst@redhat.com>
Tue, 14 Jun 2022 23:23:17 +0000 (01:23 +0200)
committerMarge Bot <emma+marge@anholt.net>
Fri, 4 Aug 2023 21:31:54 +0000 (21:31 +0000)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>

src/nouveau/winsys/nouveau_private.h
src/nouveau/winsys/nouveau_push.c
src/nouveau/winsys/nouveau_push.h

index ec977d3..139a04d 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef NOUVEAU_PRIVATE
 #define NOUVEAU_PRIVATE 1
 
+#include <assert.h>
 #include <stdint.h>
 
 #include "util/u_memory.h"
index efc0a48..547f908 100644 (file)
@@ -55,6 +55,42 @@ nouveau_ws_push_destroy(struct nouveau_ws_push *push)
    nouveau_ws_bo_destroy(push->bo);
 }
 
+static void
+nouveau_ws_push_valid(struct nouveau_ws_push *push) {
+   uint32_t *cur = push->orig_map;
+
+   /* submitting empty push buffers is probably a bug */
+   assert(push->map != push->orig_map);
+
+   /* make sure we don't overrun the bo */
+   assert(push->map <= push->end);
+
+   /* parse all the headers to see if we get to push->map */
+   while (cur < push->map) {
+      uint32_t hdr = *cur;
+      uint32_t mthd = hdr >> 29;
+
+      switch (mthd) {
+      /* immd */
+      case 4:
+         break;
+      case 1:
+      case 3:
+      case 5: {
+         uint32_t count = (hdr >> 16) & 0x1fff;
+         assert(count);
+         cur += count;
+         break;
+      }
+      default:
+         assert(!"unknown method found");
+      }
+
+      cur++;
+      assert(cur <= push->map);
+   }
+}
+
 int
 nouveau_ws_push_submit(
    struct nouveau_ws_push *push,
@@ -68,6 +104,12 @@ nouveau_ws_push_submit(
    struct drm_nouveau_gem_pushbuf req = {};
    struct drm_nouveau_gem_pushbuf_push req_push = {};
 
+   if (push->map == push->orig_map)
+      return 0;
+
+   /* make sure we don't submit nonsense */
+   nouveau_ws_push_valid(push);
+
    int i = 0;
    util_dynarray_foreach(&push->bos, struct nouveau_ws_push_bo, push_bo) {
       struct nouveau_ws_bo *bo = push_bo->bo;
index 502d57c..c1da94f 100644 (file)
@@ -47,8 +47,26 @@ NVC0_FIFO_PKHDR_SQ(int subc, int mthd, unsigned size)
 }
 
 static inline void
+__push_verify(struct nouveau_ws_push *push)
+{
+   if (!push->last_size)
+      return;
+
+   /* make sure we don't add a new method if the last one wasn't used */
+   uint32_t last_hdr = *push->last_size;
+
+   /* check for immd */
+   if (last_hdr >> 29 == 4)
+      return;
+
+   UNUSED uint32_t last_count = (last_hdr & 0x1fff0000);
+   assert(last_count);
+}
+
+static inline void
 __push_mthd(struct nouveau_ws_push *push, int subc, uint32_t mthd)
 {
+   __push_verify(push);
    push->last_size = push->map;
    *push->map = NVC0_FIFO_PKHDR_SQ(subc, mthd, 0);
    push->map++;
@@ -66,6 +84,7 @@ NVC0_FIFO_PKHDR_IL(int subc, int mthd, uint16_t data)
 static inline void
 __push_immd(struct nouveau_ws_push *push, int subc, uint32_t mthd, uint32_t val)
 {
+   __push_verify(push);
    push->last_size = push->map;
    *push->map = NVC0_FIFO_PKHDR_IL(subc, mthd, val);
    push->map++;
@@ -86,6 +105,7 @@ NVC0_FIFO_PKHDR_1I(int subc, int mthd, unsigned size)
 static inline void
 __push_1inc(struct nouveau_ws_push *push, int subc, uint32_t mthd)
 {
+   __push_verify(push);
    push->last_size = push->map;
    *push->map = NVC0_FIFO_PKHDR_1I(subc, mthd, 0);
    push->map++;
@@ -102,6 +122,7 @@ NVC0_FIFO_PKHDR_0I(int subc, int mthd, unsigned size)
 static inline void
 __push_0inc(struct nouveau_ws_push *push, int subc, uint32_t mthd)
 {
+   __push_verify(push);
    push->last_size = push->map;
    *push->map = NVC0_FIFO_PKHDR_0I(subc, mthd, 0);
    push->map++;
@@ -173,6 +194,7 @@ nvk_push_val(struct nouveau_ws_push *push, uint32_t idx, uint32_t val)
    assert(last_hdr_val);
    assert(!is_immd);
    assert(last_method == idx);
+   assert(push->map < push->end);
 
    P_INLINE_DATA(push, val);
 }