vrend: unbind texture target after allocating a new texture

If a texture is bound in a GL context the texture object will not be
destroyed by the driver even if the program using the texture freed it.
At least with  mesa Gallium drivers the effect that these texture objects
also hold references to sampler views that might have been created and
destroyed in sub-contexts. Now, when a new texture is allocated and
bound to the corresponding texture target, the old texture will finally
be destroyed at this point, and by doing so it will try to access these
already destroyed sampler views, resulting in a use after free.

Consequently, unbind the texture in context 0 after it has been allocated,
so that the driver doesn't hold an additional reference to it that inhibits
its destruction of the texture when the guest program requests this.

v2: Make sure that the texture is also unbound when the allocation function
    bails out with an error (Chia-I Wu)

Closes #98

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Reviewed-by: Chia-I Wu <olvaffe@gmail.com>
macos/master
Gert Wollny 6 years ago
parent aa908a612c
commit a6f9fac9e6
  1. 9
      src/vrend_renderer.c

@ -5959,9 +5959,6 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr,
gr->target = GL_TEXTURE_2D_ARRAY; gr->target = GL_TEXTURE_2D_ARRAY;
} }
glGenTextures(1, &gr->id);
glBindTexture(gr->target, gr->id);
debug_texture(__func__, gr); debug_texture(__func__, gr);
internalformat = tex_conv_table[pr->format].internalformat; internalformat = tex_conv_table[pr->format].internalformat;
@ -5974,12 +5971,16 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr,
return EINVAL; return EINVAL;
} }
glGenTextures(1, &gr->id);
glBindTexture(gr->target, gr->id);
if (image_oes) { if (image_oes) {
if (epoxy_has_gl_extension("GL_OES_EGL_image_external")) { if (epoxy_has_gl_extension("GL_OES_EGL_image_external")) {
glEGLImageTargetTexture2DOES(gr->target, (GLeglImageOES) image_oes); glEGLImageTargetTexture2DOES(gr->target, (GLeglImageOES) image_oes);
} else { } else {
vrend_printf( "missing GL_OES_EGL_image_external extension\n"); vrend_printf( "missing GL_OES_EGL_image_external extension\n");
FREE(gr); FREE(gr);
glBindTexture(gr->target, 0);
return EINVAL; return EINVAL;
} }
} else if (pr->nr_samples > 0) { } else if (pr->nr_samples > 0) {
@ -6069,6 +6070,8 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr,
glTexParameteri(gr->target, GL_TEXTURE_MAX_LEVEL, pr->last_level); glTexParameteri(gr->target, GL_TEXTURE_MAX_LEVEL, pr->last_level);
} }
glBindTexture(gr->target, 0);
gt->state.max_lod = -1; gt->state.max_lod = -1;
gt->cur_swizzle_r = gt->cur_swizzle_g = gt->cur_swizzle_b = gt->cur_swizzle_a = -1; gt->cur_swizzle_r = gt->cur_swizzle_g = gt->cur_swizzle_b = gt->cur_swizzle_a = -1;
gt->cur_base = -1; gt->cur_base = -1;

Loading…
Cancel
Save