From 008e9768ad11bf163fac913926872bc69f2c6374 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Wed, 15 Jun 2022 01:23:17 +0200 Subject: [PATCH] nouveau/ws: make sure we don't submit nonsense Part-of: --- src/nouveau/winsys/nouveau_private.h | 1 + src/nouveau/winsys/nouveau_push.c | 42 ++++++++++++++++++++++++++++++++++++ src/nouveau/winsys/nouveau_push.h | 22 +++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/src/nouveau/winsys/nouveau_private.h b/src/nouveau/winsys/nouveau_private.h index ec977d3..139a04d 100644 --- a/src/nouveau/winsys/nouveau_private.h +++ b/src/nouveau/winsys/nouveau_private.h @@ -1,6 +1,7 @@ #ifndef NOUVEAU_PRIVATE #define NOUVEAU_PRIVATE 1 +#include #include #include "util/u_memory.h" diff --git a/src/nouveau/winsys/nouveau_push.c b/src/nouveau/winsys/nouveau_push.c index efc0a48..547f908 100644 --- a/src/nouveau/winsys/nouveau_push.c +++ b/src/nouveau/winsys/nouveau_push.c @@ -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; diff --git a/src/nouveau/winsys/nouveau_push.h b/src/nouveau/winsys/nouveau_push.h index 502d57c..c1da94f 100644 --- a/src/nouveau/winsys/nouveau_push.h +++ b/src/nouveau/winsys/nouveau_push.h @@ -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); } -- 2.7.4