<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>