From e72ad05c1d6bdedf3b15cfe7ba42c801254d6112 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Sun, 11 Feb 2018 14:38:42 +0100 Subject: [PATCH] radv: Return NULL for entrypoints when not supported. This implements strict checking for the entrypoint ProcAddr functions. - InstanceProcAddr with instance = NULL, only returns the 3 allowed entrypoints. - DeviceProcAddr does not return any instance entrypoints. - InstanceProcAddr does not return non-supported or disabled instance entrypoints. - DeviceProcAddr does not return non-supported or disabled device entrypoints. - InstanceProcAddr still returns non-supported device entrypoints. Reviewed-by: Dave Airlie --- src/amd/vulkan/radv_device.c | 18 +++++-- src/amd/vulkan/radv_entrypoints_gen.py | 66 ++++++++++++++++++++++++-- src/amd/vulkan/radv_private.h | 6 ++- src/amd/vulkan/radv_wsi.c | 2 +- 4 files changed, 83 insertions(+), 9 deletions(-) diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index 79534fbd5fc..f197b7f484c 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -2311,10 +2311,15 @@ VkResult radv_EnumerateDeviceExtensionProperties( } PFN_vkVoidFunction radv_GetInstanceProcAddr( - VkInstance instance, + VkInstance _instance, const char* pName) { - return radv_lookup_entrypoint(pName); + RADV_FROM_HANDLE(radv_instance, instance, _instance); + + return radv_lookup_entrypoint_checked(pName, + instance ? instance->apiVersion : 0, + instance ? &instance->enabled_extensions : NULL, + NULL); } /* The loader wants us to expose a second GetInstanceProcAddr function @@ -2334,10 +2339,15 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr( } PFN_vkVoidFunction radv_GetDeviceProcAddr( - VkDevice device, + VkDevice _device, const char* pName) { - return radv_lookup_entrypoint(pName); + RADV_FROM_HANDLE(radv_device, device, _device); + + return radv_lookup_entrypoint_checked(pName, + device->instance->apiVersion, + &device->instance->enabled_extensions, + &device->enabled_extensions); } bool radv_get_memory_fd(struct radv_device *device, diff --git a/src/amd/vulkan/radv_entrypoints_gen.py b/src/amd/vulkan/radv_entrypoints_gen.py index f7a791967b9..08ca9ccca13 100644 --- a/src/amd/vulkan/radv_entrypoints_gen.py +++ b/src/amd/vulkan/radv_entrypoints_gen.py @@ -185,7 +185,45 @@ static const uint16_t map[] = { % endfor }; -void * +/** Return true if the core version or extension in which the given entrypoint + * is defined is enabled. + * + * If instance is NULL, we only allow the 3 commands explicitly allowed by the vk + * spec. + * + * If device is NULL, all device extensions are considered enabled. + */ +static bool +radv_entrypoint_is_enabled(int index, uint32_t core_version, + const struct radv_instance_extension_table *instance, + const struct radv_device_extension_table *device) +{ + switch (index) { +% for e in entrypoints: + case ${e.num}: + % if not e.device_command: + if (device) return false; + % endif + % if e.name == 'vkCreateInstance' or e.name == 'vkEnumerateInstanceExtensionProperties' or e.name == 'vkEnumerateInstanceLayerProperties': + return !device; + % elif e.core_version: + return instance && ${e.core_version.c_vk_version()} <= core_version; + % elif e.extension: + % if e.extension.type == 'instance': + return instance && instance->${e.extension.name[3:]}; + % else: + return instance && (!device || device->${e.extension.name[3:]}); + % endif + % else: + return instance; + % endif +% endfor + default: + return false; + } +} + +static int radv_lookup_entrypoint(const char *name) { static const uint32_t prime_factor = ${prime_factor}; @@ -202,15 +240,36 @@ radv_lookup_entrypoint(const char *name) do { i = map[h & ${hash_mask}]; if (i == none) - return NULL; + return -1; e = &entrypoints[i]; h += prime_step; } while (e->hash != hash); if (strcmp(name, strings + e->name) != 0) + return -1; + + return i; +} + +void * +radv_lookup_entrypoint_unchecked(const char *name) +{ + int index = radv_lookup_entrypoint(name); + if (index < 0) return NULL; + return radv_resolve_entrypoint(index); +} - return radv_resolve_entrypoint(i); +void * +radv_lookup_entrypoint_checked(const char *name, + uint32_t core_version, + const struct radv_instance_extension_table *instance, + const struct radv_device_extension_table *device) +{ + int index = radv_lookup_entrypoint(name); + if (index < 0 || !radv_entrypoint_is_enabled(index, core_version, instance, device)) + return NULL; + return radv_resolve_entrypoint(index); }""", output_encoding='utf-8') NONE = 0xffff @@ -239,6 +298,7 @@ class Entrypoint(object): # Extensions which require this entrypoint self.core_version = None self.extension = None + self.device_command = len(params) > 0 and (params[0].type == 'VkDevice' or params[0].type == 'VkQueue' or params[0].type == 'VkCommandBuffer') def prefixed_name(self, prefix): assert self.name.startswith('vk') diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 18665557eda..10690cbb727 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -255,7 +255,11 @@ void radv_loge_v(const char *format, va_list va); return; \ } while (0) -void *radv_lookup_entrypoint(const char *name); +void *radv_lookup_entrypoint_unchecked(const char *name); +void *radv_lookup_entrypoint_checked(const char *name, + uint32_t core_version, + const struct radv_instance_extension_table *instance, + const struct radv_device_extension_table *device); struct radv_physical_device { VK_LOADER_DATA _loader_data; diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c index e016e837102..3b525fe4453 100644 --- a/src/amd/vulkan/radv_wsi.c +++ b/src/amd/vulkan/radv_wsi.c @@ -32,7 +32,7 @@ static PFN_vkVoidFunction radv_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName) { - return radv_lookup_entrypoint(pName); + return radv_lookup_entrypoint_unchecked(pName); } VkResult -- 2.30.2