<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Oct 17, 2017 at 5:27 PM, Chad Versace <span dir="ltr"><<a href="mailto:chadversary@chromium.org" target="_blank">chadversary@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This change prepares for VK_ANDROID_native_buffer. When the user imports<br>
a gralloc hande into a VkImage using VK_ANDROID_native_buffer, the user<br>
provides no size. The driver must infer the size from the internals of<br>
the gralloc buffer.<br>
<br>
The patch is essentially a refactor patch.  It should change no behavior<br>
other than improved debug messages.<br>
---<br>
<br>
Jason, you were right about the race; it poses no security problem.<br>
<br>
This patch replaces 07/10 in the series.<br>
<br>
<br>
<br>
 src/intel/vulkan/anv_<wbr>allocator.c | 21 +++------------------<br>
 src/intel/vulkan/anv_device.c    | 21 +++++++++++++++++++--<br>
 src/intel/vulkan/anv_intel.c     | 12 +++++++++++-<br>
 src/intel/vulkan/anv_private.h   |  2 +-<br>
 src/intel/vulkan/anv_queue.c     |  7 ++++++-<br>
 5 files changed, 40 insertions(+), 23 deletions(-)<br>
<br>
diff --git a/src/intel/vulkan/anv_<wbr>allocator.c b/src/intel/vulkan/anv_<wbr>allocator.c<br>
index 401cea40e6..27eedb53aa 100644<br>
--- a/src/intel/vulkan/anv_<wbr>allocator.c<br>
+++ b/src/intel/vulkan/anv_<wbr>allocator.c<br>
@@ -1272,13 +1272,10 @@ anv_bo_cache_alloc(struct anv_device *device,<br>
 VkResult<br>
 anv_bo_cache_import(struct anv_device *device,<br>
                     struct anv_bo_cache *cache,<br>
-                    int fd, uint64_t size, struct anv_bo **bo_out)<br>
+                    int fd, struct anv_bo **bo_out)<br>
 {<br>
    pthread_mutex_lock(&cache-><wbr>mutex);<br>
<br>
-   /* The kernel is going to give us whole pages anyway */<br>
-   size = align_u64(size, 4096);<br>
-<br>
    uint32_t gem_handle = anv_gem_fd_to_handle(device, fd);<br>
    if (!gem_handle) {<br>
       pthread_mutex_unlock(&cache-><wbr>mutex);<br>
@@ -1287,22 +1284,10 @@ anv_bo_cache_import(struct anv_device *device,<br>
<br>
    struct anv_cached_bo *bo = anv_bo_cache_lookup_locked(<wbr>cache, gem_handle);<br>
    if (bo) {<br>
-      if (bo->bo.size != size) {<br>
-         pthread_mutex_unlock(&cache-><wbr>mutex);<br>
-         return vk_error(VK_ERROR_INVALID_<wbr>EXTERNAL_HANDLE_KHR);<br>
-      }<br>
       __sync_fetch_and_add(&bo-><wbr>refcount, 1);<br>
    } else {<br>
-      /* For security purposes, we reject BO imports where the size does not<br>
-       * match exactly.  This prevents a malicious client from passing a<br>
-       * buffer to a trusted client, lying about the size, and telling the<br>
-       * trusted client to try and texture from an image that goes<br>
-       * out-of-bounds.  This sort of thing could lead to GPU hangs or worse<br>
-       * in the trusted client.  The trusted client can protect itself against<br>
-       * this sort of attack but only if it can trust the buffer size.<br>
-       */<br>
-      off_t import_size = lseek(fd, 0, SEEK_END);<br>
-      if (import_size == (off_t)-1 || import_size < size) {<br>
+      off_t size = lseek(fd, 0, SEEK_END);<br>
+      if (size == (off_t)-1) {<br>
          anv_gem_close(device, gem_handle);<br>
          pthread_mutex_unlock(&cache-><wbr>mutex);<br>
          return vk_error(VK_ERROR_INVALID_<wbr>EXTERNAL_HANDLE_KHR);<br>
diff --git a/src/intel/vulkan/anv_device.<wbr>c b/src/intel/vulkan/anv_device.<wbr>c<br>
index 1634b5158c..900de9778c 100644<br>
--- a/src/intel/vulkan/anv_device.<wbr>c<br>
+++ b/src/intel/vulkan/anv_device.<wbr>c<br>
@@ -1543,11 +1543,28 @@ VkResult anv_AllocateMemory(<br>
              VK_EXTERNAL_MEMORY_HANDLE_<wbr>TYPE_OPAQUE_FD_BIT_KHR);<br>
<br>
       result = anv_bo_cache_import(device, &device->bo_cache,<br>
-                                   fd_info->fd, pAllocateInfo->allocationSize,<br>
-                                   &mem->bo);<br>
+                                   fd_info->fd, &mem->bo);<br>
       if (result != VK_SUCCESS)<br>
          goto fail;<br>
<br>
+      /* For security purposes, we reject BO imports where the size does not<br>
+       * match exactly.  This prevents a malicious client from passing<br>
+       * a buffer to a trusted client, lying about the size, and telling the<br>
+       * trusted client to try and texture from an image that goes<br>
+       * out-of-bounds.  This sort of thing could lead to GPU hangs or worse<br>
+       * in the trusted client.  The trusted client can protect itself against<br>
+       * this sort of attack but only if it can trust the buffer size.<br>
+       */<br>
+      if (pAllocateInfo->allocationSize != mem->bo->size) {<br></blockquote><div><br></div><div>You're not checking the aligned size like we were before.  Maybe make that align_u64(pAllocateInfo->allocationSize, 4096)?  In any case, I don't think it matters because the client will be getting the size based on an image query which will likely be a multiple of 4k.  Still, it'd be nice to not have a behavioral change.  With that,</div><div><br></div><div>Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+         result = vk_errorf(device->instace, device,<br>
+                            VK_ERROR_INVALID_EXTERNAL_<wbr>HANDLE_KHR,<br>
+                            "invalid allocationSize for VK_EXTERNAL_MEMORY_HANDLE_<wbr>TYPE_OPAQUE_FD_BIT_KHR: "<br>
+                            "expected %"PRIu64"B, actual %"PRIu64"B",<br>
+                            mem->bo->size, pAllocateInfo->allocationSize)<wbr>;<br>
+         anv_bo_cache_release(device, &device->bo_cache, mem->bo);<br>
+         goto fail;<br>
+      }<br>
+<br>
       /* From the Vulkan spec:<br>
        *<br>
        *    "Importing memory from a file descriptor transfers ownership of<br>
diff --git a/src/intel/vulkan/anv_intel.c b/src/intel/vulkan/anv_intel.c<br>
index d6bad44091..a80b1e4623 100644<br>
--- a/src/intel/vulkan/anv_intel.c<br>
+++ b/src/intel/vulkan/anv_intel.c<br>
@@ -76,10 +76,20 @@ VkResult anv_CreateDmaBufImageINTEL(<br>
    image = anv_image_from_handle(image_h)<wbr>;<br>
<br>
    result = anv_bo_cache_import(device, &device->bo_cache,<br>
-                                pCreateInfo->fd, image->size, &mem->bo);<br>
+                                pCreateInfo->fd, &mem->bo);<br>
    if (result != VK_SUCCESS)<br>
       goto fail_import;<br>
<br>
+   if (image->size != mem->bo->size) {<br>
+      result = vk_errorf(device->instace, device,<br>
+                         VK_ERROR_INVALID_EXTERNAL_<wbr>HANDLE_KHR,<br>
+                         "invalid dma-buf size in vkCreateDmaBufImageINTEL: "<br>
+                         "expected %"PRIu64"B, actual %"PRIu64"B",<br>
+                         image->size, mem->bo->size);<br>
+      anv_bo_cache_release(device, &device->bo_cache, mem->bo);<br>
+      goto fail_import;<br>
+   }<br>
+<br>
    if (device->instance-><wbr>physicalDevice.supports_48bit_<wbr>addresses)<br>
       mem->bo->flags |= EXEC_OBJECT_SUPPORTS_48B_<wbr>ADDRESS;<br>
<br>
diff --git a/src/intel/vulkan/anv_<wbr>private.h b/src/intel/vulkan/anv_<wbr>private.h<br>
index 8af3f5c69e..61e23282b0 100644<br>
--- a/src/intel/vulkan/anv_<wbr>private.h<br>
+++ b/src/intel/vulkan/anv_<wbr>private.h<br>
@@ -718,7 +718,7 @@ VkResult anv_bo_cache_alloc(struct anv_device *device,<br>
                             uint64_t size, struct anv_bo **bo);<br>
 VkResult anv_bo_cache_import(struct anv_device *device,<br>
                              struct anv_bo_cache *cache,<br>
-                             int fd, uint64_t size, struct anv_bo **bo);<br>
+                             int fd, struct anv_bo **bo);<br>
 VkResult anv_bo_cache_export(struct anv_device *device,<br>
                              struct anv_bo_cache *cache,<br>
                              struct anv_bo *bo_in, int *fd_out);<br>
diff --git a/src/intel/vulkan/anv_queue.c b/src/intel/vulkan/anv_queue.c<br>
index 7e675e2274..63335490fd 100644<br>
--- a/src/intel/vulkan/anv_queue.c<br>
+++ b/src/intel/vulkan/anv_queue.c<br>
@@ -1023,10 +1023,15 @@ VkResult anv_ImportSemaphoreFdKHR(<br>
          new_impl.type = ANV_SEMAPHORE_TYPE_BO;<br>
<br>
          VkResult result = anv_bo_cache_import(device, &device->bo_cache,<br>
-                                               fd, 4096, &<a href="http://new_impl.bo" rel="noreferrer" target="_blank">new_impl.bo</a>);<br>
+                                               fd, &<a href="http://new_impl.bo" rel="noreferrer" target="_blank">new_impl.bo</a>);<br>
          if (result != VK_SUCCESS)<br>
             return result;<br>
<br>
+         if (new_impl.bo->size != 4096) {<br>
+            anv_bo_cache_release(device, &device->bo_cache, <a href="http://new_impl.bo" rel="noreferrer" target="_blank">new_impl.bo</a>);<br>
+            return vk_error(VK_ERROR_INVALID_<wbr>EXTERNAL_HANDLE_KHR);<br>
+         }<br>
+<br>
          /* If we're going to use this as a fence, we need to *not* have the<br>
           * EXEC_OBJECT_ASYNC bit set.<br>
           */<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.13.0<br>
<br>
</font></span></blockquote></div><br></div></div>