From 21952ffb0767fa101502f3a841355c5757408cca Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Thu, 5 Feb 2026 10:10:09 +0200 Subject: [PATCH] anv: don't relocate memory from blob This could override data allocated by the application when shader code is loaded from binary in vkCreateShaderObjectEXT(). Signed-off-by: Lionel Landwerlin Fixes: d39e443ef8 ("anv: add infrastructure for common vk_pipeline") Reviewed-by: Ivan Briano Part-of: --- src/intel/vulkan/anv_private.h | 6 +++ src/intel/vulkan/anv_shader.c | 71 ++++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 307a3a559d9..9cf9fcfd02b 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1314,6 +1314,12 @@ struct anv_shader_group_rt_replay { struct anv_shader { struct vk_shader vk; + /** + * Code of the shader on the host + * + * This is before relocations are applied so that can always return the + * same blob of data for serialization. + */ void *code; struct anv_shader_alloc kernel; diff --git a/src/intel/vulkan/anv_shader.c b/src/intel/vulkan/anv_shader.c index c0c768006a0..5efe5acfe42 100644 --- a/src/intel/vulkan/anv_shader.c +++ b/src/intel/vulkan/anv_shader.c @@ -548,35 +548,59 @@ anv_shader_set_relocs(struct anv_device *device, return rv_count; } +struct anv_shader_reloc { + struct anv_device *device; + const VkAllocationCallbacks *alloc; + const void *in_code; + uint32_t *code_size; + + void *relocated_code; +}; + static VkResult -anv_shader_reloc(struct anv_device *device, - void *code, - struct anv_shader *shader, - const VkAllocationCallbacks *pAllocator) +anv_shader_reloc_begin(struct anv_shader_reloc *reloc, + struct anv_device *device, + const void *in_code, + struct anv_shader *shader, + const VkAllocationCallbacks *alloc) { + memset(reloc, 0, sizeof(*reloc)); + reloc->device = device; + reloc->alloc = alloc; + const uint32_t max_relocs = BRW_SHADER_RELOC_EMBEDDED_SAMPLER_HANDLE + shader->bind_map.embedded_sampler_count; - uint32_t rv_count; - struct intel_shader_reloc_value *reloc_values = - vk_zalloc2(&device->vk.alloc, pAllocator, - sizeof(struct intel_shader_reloc_value) * max_relocs, 8, - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); - if (reloc_values == NULL) + VK_MULTIALLOC(ma); + VK_MULTIALLOC_DECL_SIZE(&ma, void, code, shader->prog_data->program_size); + VK_MULTIALLOC_DECL(&ma, struct intel_shader_reloc_value, reloc_values, max_relocs); + + if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, alloc, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE)) return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - rv_count = anv_shader_set_relocs(device, reloc_values, shader); + /* Make a copy of the code to relocate it, we don't know where the data + * comes from, could be read-only, could app-managed, ... + */ + reloc->relocated_code = code; + memcpy(reloc->relocated_code, in_code, shader->prog_data->program_size); + + uint32_t rv_count = anv_shader_set_relocs(device, reloc_values, shader); assert(rv_count <= max_relocs); brw_write_shader_relocs(&device->physical->compiler->isa, - code, shader->prog_data, + reloc->relocated_code, shader->prog_data, reloc_values, rv_count); - vk_free2(&device->vk.alloc, pAllocator, reloc_values); - return VK_SUCCESS; } +static void +anv_shader_reloc_end(struct anv_shader_reloc *reloc) +{ + vk_free2(&reloc->device->vk.alloc, reloc->alloc, reloc->relocated_code); +} + struct internal_representation { char *nir_str; uint32_t nir_str_len; @@ -712,16 +736,20 @@ anv_shader_create(struct anv_device *device, shader->instance_multiplier = shader_data->instance_multiplier; - result = anv_shader_reloc(device, shader_data->code, shader, pAllocator); + struct anv_shader_reloc reloc; + result = anv_shader_reloc_begin(&reloc, device, shader_data->code, + shader, pAllocator); if (result != VK_SUCCESS) goto error_state; anv_shader_heap_upload(&device->shader_heap, shader->kernel, - shader_data->code, + reloc.relocated_code, shader->prog_data, shader->stats->dispatch_width); + anv_shader_reloc_end(&reloc); + if (mesa_shader_stage_is_rt(shader->vk.stage)) { const struct brw_bs_prog_data *bs_prog_data = (const struct brw_bs_prog_data *)shader->prog_data; @@ -879,16 +907,19 @@ anv_replay_rt_shader_group(struct vk_device *vk_device, 64, true, offset); assert(shader->replay_kernel.alloc_size != 0); - /* TODO: make a copy of the code to leave it untouched */ - VkResult result = - anv_shader_reloc(device, shader->code, shader, &vk_device->alloc); + struct anv_shader_reloc reloc; + VkResult result = anv_shader_reloc_begin(&reloc, device, + shader->code, + shader, NULL); assert(result == VK_SUCCESS); anv_shader_heap_upload(&device->shader_heap, shader->replay_kernel, - shader->code, + reloc.relocated_code, shader->prog_data, shader->stats->dispatch_width); + + anv_shader_reloc_end(&reloc); } simple_mtx_unlock(&shader->replay_mutex);