vc4: Add a sentinel after simulator buffers for buffer overflow detection.
authorEric Anholt <eric@anholt.net>
Thu, 22 Oct 2015 10:31:56 +0000 (11:31 +0100)
committerEric Anholt <eric@anholt.net>
Fri, 23 Oct 2015 13:29:07 +0000 (14:29 +0100)
This is a little bit like the mprotect-based fencing I've experimented
with, but it's simple and low overhead.  The downside is that only catches
writes, not reads.

It didn't catch any bad writes on a current piglit run, but may be useful
in the future.

src/gallium/drivers/vc4/vc4_simulator.c

index 76980ca32af8c8fc1e7dc54bc3299152e9319c1e..10dabd09f5e1aa0f648c7b09d52b4d89cbd7a161 100644 (file)
 #include "vc4_simulator_validate.h"
 #include "simpenrose/simpenrose.h"
 
+/* A marker placed just after each BO, then checked after rendering to make
+ * sure it's still there.
+ */
+#define BO_SENTINEL            0xfedcba98
+
 #define OVERFLOW_SIZE (32 * 1024 * 1024)
 
 static struct drm_gem_cma_object *
@@ -49,10 +54,12 @@ vc4_wrap_bo_with_cma(struct drm_device *dev, struct vc4_bo *bo)
         obj->vaddr = screen->simulator_mem_base + dev->simulator_mem_next;
         obj->paddr = simpenrose_hw_addr(obj->vaddr);
 
-        dev->simulator_mem_next += size;
+        dev->simulator_mem_next += size + sizeof(uint32_t);
         dev->simulator_mem_next = align(dev->simulator_mem_next, 4096);
         assert(dev->simulator_mem_next <= screen->simulator_mem_size);
 
+        *(uint32_t *)(obj->vaddr + bo->size) = BO_SENTINEL;
+
         return obj;
 }
 
@@ -109,6 +116,7 @@ vc4_simulator_unpin_bos(struct vc4_exec_info *exec)
                 struct drm_vc4_bo *drm_bo = to_vc4_bo(&obj->base);
                 struct vc4_bo *bo = drm_bo->bo;
 
+                assert(*(uint32_t *)(obj->vaddr + bo->size) == BO_SENTINEL);
                 memcpy(bo->map, obj->vaddr, bo->size);
 
                 if (drm_bo->validated_shader) {
@@ -197,6 +205,8 @@ vc4_simulator_flush(struct vc4_context *vc4, struct drm_vc4_submit_cl *args)
         list_for_each_entry_safe(struct drm_vc4_bo, bo, &exec.unref_list,
                                  unref_head) {
                list_del(&bo->unref_head);
+                assert(*(uint32_t *)(bo->base.vaddr + bo->bo->size) ==
+                       BO_SENTINEL);
                 vc4_bo_unreference(&bo->bo);
                 free(bo);
         }