pan/decode: Add static bounds checking utility
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Mon, 19 Aug 2019 22:14:48 +0000 (15:14 -0700)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Wed, 21 Aug 2019 15:40:53 +0000 (08:40 -0700)
Many structures in the command stream have a GPU address and size
determined statically. We should check that the pointers we are passed
are valid and the buffers they point to are big enough for the given
size. If they're not, an MMU fault would be raised.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
src/panfrost/pandecode/decode.c

index c9df2cecc618dc660b06071431d730d2073094d5..47ecc744ea9cead8b89d048d5e268161dfae82b4 100644 (file)
@@ -115,6 +115,44 @@ pandecode_log_cont(const char *format, ...)
         va_end(ap);
 }
 
+/* To check for memory safety issues, validates that the given pointer in GPU
+ * memory is valid, containing at least sz bytes. The goal is to eliminate
+ * GPU-side memory bugs (NULL pointer dereferences, buffer overflows, or buffer
+ * overruns) by statically validating pointers.
+ */
+
+static void
+pandecode_validate_buffer(mali_ptr addr, size_t sz)
+{
+        if (!addr) {
+                pandecode_msg("XXX: null pointer deref");
+                return;
+        }
+
+        /* Find a BO */
+
+        struct pandecode_mapped_memory *bo =
+                pandecode_find_mapped_gpu_mem_containing(addr);
+
+        if (!bo) {
+                pandecode_msg("XXX: invalid memory dereference\n");
+                return;
+        }
+
+        /* Bounds check */
+
+        unsigned offset = addr - bo->gpu_va;
+        unsigned total = offset + sz;
+
+        if (total > bo->length) {
+                pandecode_msg("XXX: buffer overrun."
+                                "Chunk of size %d at offset %d in buffer of size %d. "
+                                "Overrun by %d bytes.",
+                                sz, offset, bo->length, total - bo->length);
+                return;
+        }
+}
+
 struct pandecode_flag_info {
         u64 flag;
         const char *name;