[Mesa-dev] [PATCH 2/2] nir: Fix clone/sweep of info allocated by nir_builder_init_simple_shader().
Eric Anholt
eric at anholt.net
Thu Oct 27 20:30:24 UTC 2016
Fixes use-after-free-caused segfaults in the tgsi_to_nir() path.
---
I don't like the boolean I added here, any better plans, though? I
haven't fully piglited this, but it's enough to get gears to not crash
on master (it at least touches the GLSL to NIR and TGSI to NIR paths.)
src/compiler/nir/nir.c | 2 ++
src/compiler/nir/nir.h | 2 ++
src/compiler/nir/nir_clone.c | 14 +++++++++++++-
src/compiler/nir/nir_sweep.c | 3 +++
4 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c
index 09aad57e87f8..1448837d8fd1 100644
--- a/src/compiler/nir/nir.c
+++ b/src/compiler/nir/nir.c
@@ -45,6 +45,8 @@ nir_shader_create(void *mem_ctx,
shader->options = options;
shader->info = si ? si : rzalloc(shader, shader_info);
+ if (!si)
+ shader->shader_owns_info = true;
exec_list_make_empty(&shader->functions);
exec_list_make_empty(&shader->registers);
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 92647632462b..7dde8bd4ebd6 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -1807,6 +1807,8 @@ typedef struct nir_shader {
/** Various bits of compile-time information about a given shader */
struct shader_info *info;
+ bool shader_owns_info;
+
/** list of global variables in the shader (nir_variable) */
struct exec_list globals;
diff --git a/src/compiler/nir/nir_clone.c b/src/compiler/nir/nir_clone.c
index 9f3bd7ff6baa..cd6063325274 100644
--- a/src/compiler/nir/nir_clone.c
+++ b/src/compiler/nir/nir_clone.c
@@ -710,7 +710,19 @@ nir_shader_clone(void *mem_ctx, const nir_shader *s)
clone_reg_list(&state, &ns->registers, &s->registers);
ns->reg_alloc = s->reg_alloc;
- ns->info = s->info;
+ if (s->shader_owns_info) {
+ ns->info = ralloc(ns, struct shader_info);
+ *ns->info = *s->info;
+ ns->shader_owns_info = true;
+ } else {
+ ns->info = s->info;
+ }
+
+ /* XXX: Note that for !shader_owns_info, we're making the info pointed to
+ * by s have data owned by ns, so if ns is freed before s then we might
+ * use-after-free the name/label. We should probably have name/label be
+ * owned by the info.
+ */
ns->info->name = ralloc_strdup(ns, ns->info->name);
if (ns->info->label)
ns->info->label = ralloc_strdup(ns, ns->info->label);
diff --git a/src/compiler/nir/nir_sweep.c b/src/compiler/nir/nir_sweep.c
index faf696d6decd..43664d4d5b96 100644
--- a/src/compiler/nir/nir_sweep.c
+++ b/src/compiler/nir/nir_sweep.c
@@ -153,6 +153,9 @@ nir_sweep(nir_shader *nir)
/* First, move ownership of all the memory to a temporary context; assume dead. */
ralloc_adopt(rubbish, nir);
+ if (nir->shader_owns_info)
+ ralloc_steal(nir, nir->info);
+
ralloc_steal(nir, (char *)nir->info->name);
if (nir->info->label)
ralloc_steal(nir, (char *)nir->info->label);
--
2.10.1
More information about the mesa-dev
mailing list