vrend: Make sure no stale links to shader programs remain in a sub-context

The sub-context holds a pointer to the last shader program used and this
is de-referenced , e.g. in vrend_vbo_draw. However, the guest may destroy
the program without notifying the sub-context, and as a result the pointer
becomes stale and may ber used after free.

As a solution add a pointer to the owning context when a program is
referenced and if the program gets destroyed, clean the pointer in the sub-context.

Closes: #52

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
macos/master
Gert Wollny 6 years ago committed by Dave Airlie
parent f500a29ae1
commit 4cf8edd9bf
  1. 10
      src/vrend_renderer.c

@ -296,6 +296,8 @@ struct vrend_linked_shader_program {
uint32_t ssbo_used_mask[PIPE_SHADER_TYPES]; uint32_t ssbo_used_mask[PIPE_SHADER_TYPES];
GLuint *ssbo_locs[PIPE_SHADER_TYPES]; GLuint *ssbo_locs[PIPE_SHADER_TYPES];
struct vrend_sub_context *ref_context;
}; };
struct vrend_shader { struct vrend_shader {
@ -1462,6 +1464,9 @@ static struct vrend_linked_shader_program *lookup_shader_program(struct vrend_co
static void vrend_destroy_program(struct vrend_linked_shader_program *ent) static void vrend_destroy_program(struct vrend_linked_shader_program *ent)
{ {
int i; int i;
if (ent->ref_context && ent->ref_context->prog == ent)
ent->ref_context->prog = NULL;
glDeleteProgram(ent->id); glDeleteProgram(ent->id);
list_del(&ent->head); list_del(&ent->head);
@ -3940,6 +3945,7 @@ int vrend_draw_vbo(struct vrend_context *ctx,
if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]) if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL])
ctx->sub->prog_ids[PIPE_SHADER_TESS_EVAL] = ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id; ctx->sub->prog_ids[PIPE_SHADER_TESS_EVAL] = ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id;
ctx->sub->prog = prog; ctx->sub->prog = prog;
prog->ref_context = ctx->sub;
} }
} }
if (!ctx->sub->prog) { if (!ctx->sub->prog) {
@ -4136,6 +4142,7 @@ void vrend_launch_grid(struct vrend_context *ctx,
ctx->sub->prog_ids[PIPE_SHADER_VERTEX] = -1; ctx->sub->prog_ids[PIPE_SHADER_VERTEX] = -1;
ctx->sub->prog_ids[PIPE_SHADER_COMPUTE] = ctx->sub->shaders[PIPE_SHADER_COMPUTE]->current->id; ctx->sub->prog_ids[PIPE_SHADER_COMPUTE] = ctx->sub->shaders[PIPE_SHADER_COMPUTE]->current->id;
ctx->sub->prog = prog; ctx->sub->prog = prog;
prog->ref_context = ctx->sub;
} }
ctx->sub->shader_dirty = true; ctx->sub->shader_dirty = true;
} }
@ -5371,6 +5378,9 @@ static void vrend_destroy_sub_context(struct vrend_sub_context *sub)
vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_TESS_EVAL], NULL); vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_TESS_EVAL], NULL);
vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_COMPUTE], NULL); vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_COMPUTE], NULL);
if (sub->prog)
sub->prog->ref_context = NULL;
vrend_free_programs(sub); vrend_free_programs(sub);
for (i = 0; i < PIPE_SHADER_TYPES; i++) { for (i = 0; i < PIPE_SHADER_TYPES; i++) {
free(sub->consts[i].consts); free(sub->consts[i].consts);

Loading…
Cancel
Save