<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Jan 26, 2018 at 12:56 AM, <span dir="ltr"><<a href="mailto:kevin.rogovin@intel.com" target="_blank">kevin.rogovin@intel.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Kevin Rogovin <<a href="mailto:kevin.rogovin@intel.com">kevin.rogovin@intel.com</a>><br>
<br>
Signed-off-by: Kevin Rogovin <<a href="mailto:kevin.rogovin@intel.com">kevin.rogovin@intel.com</a>><br>
Reviewed-by: Chris Wilson <<a href="mailto:chris@chris-wilson.co.uk">chris@chris-wilson.co.uk</a>><br>
---<br>
src/mesa/drivers/dri/i965/brw_<wbr>bufmgr.c | 115 ++++++++++++++++++++++++++++++<wbr>++-<br>
src/mesa/drivers/dri/i965/brw_<wbr>bufmgr.h | 13 ++++<br>
2 files changed, 127 insertions(+), 1 deletion(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_bufmgr.c b/src/mesa/drivers/dri/i965/<wbr>brw_bufmgr.c<br>
index fb180289a0..7e50ba512e 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_bufmgr.c<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_bufmgr.c<br>
@@ -220,6 +220,39 @@ bucket_for_size(struct brw_bufmgr *bufmgr, uint64_t size)<br>
&bufmgr->cache_bucket[index] : NULL;<br>
}<br>
<br>
+/* Our goal is not to have noise good enough for cryto,<br>
+ * but instead values that are unique-ish enough that<br>
+ * it is incredibly unlikely that a buffer overwrite<br>
+ * will produce the exact same values.<br>
+ */<br>
+static uint8_t<br>
+next_noise_value(uint8_t prev_noise)<br>
+{<br>
+ uint32_t v = prev_noise;<br>
+ return (v * 103u + 227u) & 0xFF;<br>
+}<br>
+<br>
+static void<br>
+fill_noise_buffer(uint8_t *dst, uint8_t start, uint32_t length)<br>
+{<br>
+ for(uint32_t i = 0; i < length; ++i) {<br>
+ dst[i] = start;<br>
+ start = next_noise_value(start);<br>
+ }<br>
+}<br>
+<br>
+static uint8_t*<br>
+generate_noise_buffer(uint8_t start, uint32_t length)<br>
+{<br>
+ uint8_t *return_value;<br>
+ return_value = malloc(length);<br>
+ if (return_value) {<br>
+ fill_noise_buffer(return_<wbr>value, start, length);<br>
+ }<br>
+<br>
+ return return_value;<br>
+}<br>
+<br>
int<br>
brw_bo_busy(struct brw_bo *bo)<br>
{<br>
@@ -367,7 +400,18 @@ retry:<br>
bo->size = bo_size;<br>
bo->idle = true;<br>
<br>
- struct drm_i915_gem_create create = { .size = bo_size };<br>
+ bo->padding_size = 0;<br>
+ if (unlikely(INTEL_DEBUG & DEBUG_OUT_OF_BOUND_CHK)) {<br>
+ /* TODO: we want to make sure that the padding forces<br>
+ * the BO to take another page on the (PP)GTT; 4KB<br>
+ * may or may not be the page size for the GEM. Indeed,<br>
+ * depending on generation, kernel version and GEM size,<br>
+ * the page size can be one of 4KB, 64KB or 2M.<br>
+ */<br>
+ bo->padding_size = 4096;<br>
+ }<br>
+<br>
+ struct drm_i915_gem_create create = { .size = bo_size + bo->padding_size };<br>
<br>
/* All new BOs we get from the kernel are zeroed, so we don't need to<br>
* worry about that here.<br>
@@ -378,6 +422,27 @@ retry:<br>
goto err;<br>
}<br>
<br>
+ if (unlikely(bo->padding_size > 0)) {<br>
+ uint8_t *noise_values;<br>
+ struct drm_i915_gem_pwrite pwrite;<br>
+<br>
+ noise_values = generate_noise_buffer(create.<wbr>handle, bo->padding_size);<br>
+ if (!noise_values)<br>
+ goto err_free;<br>
+<br>
+ pwrite.handle = create.handle;<br>
+ pwrite.pad = 0;<br>
+ pwrite.offset = bo_size;<br>
+ pwrite.size = bo->padding_size;<br>
+ pwrite.data_ptr = (__u64) (uintptr_t) noise_values;<br>
+<br>
+ ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite);<br>
+ free(noise_values);<br>
+<br>
+ if (ret != 0)<br>
+ goto err_free;<br>
+ }<br>
+<br>
bo->gem_handle = create.handle;<br>
<br>
bo->bufmgr = bufmgr;<br>
@@ -424,6 +489,53 @@ err:<br>
return NULL;<br>
}<br>
<br>
+bool<br>
+brw_bo_padding_is_good(struct brw_bo *bo)<br>
+{<br>
+ if (bo->padding_size > 0) {<br>
+ struct drm_i915_gem_mmap mmap_arg = {<br>
+ .handle = bo->gem_handle,<br>
+ .offset = bo->size,<br>
+ .size = bo->padding_size,<br>
+ .flags = 0,<br>
+ };<br>
+ uint8_t *mapped;<br>
+ int ret;<br>
+ uint8_t expected_value;<br>
+<br>
+ /* We cannot use brw_bo_map() because it maps precisely the range<br>
+ * [0, bo->size) and we wish to map the range of the padding which<br>
+ * is [bo->size, bo->size + bo->pading_size)<br>
+ */<br>
+ ret = drmIoctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg);<br>
+ if (ret != 0) {<br>
+ DBG("Unable to map mapping buffer %d (%s) buffer for pad checking.\n",<br>
+ bo->gem_handle, bo->name);<br>
+ return false;<br>
+ }<br>
+<br>
+ mapped = (uint8_t*) (uintptr_t) mmap_arg.addr_ptr;<br>
+ /* bah-humbug, we need to see the latest contents and<br>
+ * if the bo is not cache coherent we likely need to<br>
+ * invalidate the cache lines to get it.<br>
+ */<br>
+ if (!bo->cache_coherent && !bo->bufmgr->has_llc) {<br>
+ gen_invalidate_range(mapped, bo->padding_size);<br>
+ }<br></blockquote><div><br></div><div>You used pwrite before. Why not just use pread and save yourself the hassle?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+ expected_value = bo->gem_handle & 0xFF;<br>
+ for (uint32_t i = 0; i < bo->padding_size; ++i) {<br>
+ if (expected_value != mapped[i]) {<br>
+ drm_munmap(mapped, bo->padding_size);<br>
+ return false;<br>
+ }<br>
+ expected_value = next_noise_value(expected_<wbr>value);<br>
+ }<br>
+ drm_munmap(mapped, bo->padding_size);<br>
+ }<br>
+ return true;<br>
+}<br>
+<br>
struct brw_bo *<br>
brw_bo_alloc(struct brw_bufmgr *bufmgr,<br>
const char *name, uint64_t size, uint64_t alignment)<br>
@@ -1157,6 +1269,7 @@ brw_bo_gem_create_from_prime_<wbr>internal(struct brw_bufmgr *bufmgr, int prime_fd,<br>
bo->name = "prime";<br>
bo->reusable = false;<br>
bo->external = true;<br>
+ bo->padding_size = 0;<br>
<br>
if (tiling_mode < 0) {<br>
struct drm_i915_gem_get_tiling get_tiling = { .handle = bo->gem_handle };<br>
diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_bufmgr.h b/src/mesa/drivers/dri/i965/<wbr>brw_bufmgr.h<br>
index a3745d6667..fcfd2a9f75 100644<br>
--- a/src/mesa/drivers/dri/i965/<wbr>brw_bufmgr.h<br>
+++ b/src/mesa/drivers/dri/i965/<wbr>brw_bufmgr.h<br>
@@ -165,6 +165,12 @@ struct brw_bo {<br>
* Boolean of whether this buffer is cache coherent<br>
*/<br>
bool cache_coherent;<br>
+<br>
+ /**<br>
+ * Padding size of weak pseudo-random values; used to check for out of<br>
+ * bounds buffer writing.<br>
+ */<br>
+ uint32_t padding_size;<br>
};<br>
<br>
#define BO_ALLOC_BUSY (1<<0)<br>
@@ -346,6 +352,13 @@ uint32_t brw_bo_export_gem_handle(<wbr>struct brw_bo *bo);<br>
int brw_reg_read(struct brw_bufmgr *bufmgr, uint32_t offset,<br>
uint64_t *result);<br>
<br>
+/* maps the padding of the brw_bo and returns true if and only if the<br>
+ * padding is the correct noise values. The caller must make sure that<br>
+ * the GPU is not going write to the BO; the best way to do that is to<br>
+ * call brw_bo_wait_rendering() on the batchbuffer.<br>
+ */<br>
+bool brw_bo_padding_is_good(struct brw_bo *bo);<br>
+<br>
/** @{ */<br>
<br>
#if defined(__cplusplus)<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.15.1<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>