Merge pull request #2453 from kumpera/fix_ji_free
authorRodrigo Kumpera <kumpera@gmail.com>
Sat, 23 Jan 2016 05:10:59 +0000 (00:10 -0500)
committerRodrigo Kumpera <kumpera@gmail.com>
Sat, 23 Jan 2016 05:10:59 +0000 (00:10 -0500)
[runtime] Avoid a read-after-free in JI table that frees tomstones. Fixes some of the crashes in #36851.

mono/metadata/domain-internals.h
mono/metadata/jit-info.c

index 09127101d0b8da21371697881ad8f96484de87a3..04eec95154a6152d5d40b182f835430e147edcc3 100644 (file)
@@ -60,6 +60,7 @@ struct _MonoJitInfoTableChunk
        int                    refcount;
        volatile int           num_elements;
        volatile gint8        *last_code_end;
+       MonoJitInfo *next_tombstone;
        MonoJitInfo * volatile data [MONO_JIT_INFO_TABLE_CHUNK_SIZE];
 };
 
@@ -201,7 +202,10 @@ struct _MonoJitInfo {
                gpointer aot_info;
                gpointer tramp_info;
        } d;
-       struct _MonoJitInfo *next_jit_code_hash;
+       union {
+               struct _MonoJitInfo *next_jit_code_hash;
+               struct _MonoJitInfo *next_tombstone;
+       } n;
        gpointer    code_start;
        guint32     unwind_info;
        int         code_size;
index 33dd5471c5fc713016ed172149a0b0642720d9bb..17b7107e63d873a495ed3fa70569a79bde57499b 100644 (file)
@@ -125,18 +125,15 @@ mono_jit_info_table_free (MonoJitInfoTable *table)
 
        for (i = 0; i < num_chunks; ++i) {
                MonoJitInfoTableChunk *chunk = table->chunks [i];
-               int num_elements;
-               int j;
+               MonoJitInfo *tombstone;
 
                if (--chunk->refcount > 0)
                        continue;
 
-               num_elements = chunk->num_elements;
-               for (j = 0; j < num_elements; ++j) {
-                       MonoJitInfo *ji = chunk->data [j];
-
-                       if (IS_JIT_INFO_TOMBSTONE (ji))
-                               g_free (ji);
+               for (tombstone = chunk->next_tombstone; tombstone; ) {
+                       MonoJitInfo *next = tombstone->n.next_tombstone;
+                       g_free (tombstone);
+                       tombstone = next;
                }
 
                g_free (chunk);
@@ -657,13 +654,15 @@ mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
 }
 
 static MonoJitInfo*
-mono_jit_info_make_tombstone (MonoJitInfo *ji)
+mono_jit_info_make_tombstone (MonoJitInfoTableChunk *chunk, MonoJitInfo *ji)
 {
        MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
 
        tombstone->code_start = ji->code_start;
        tombstone->code_size = ji->code_size;
        tombstone->d.method = JIT_INFO_TOMBSTONE_MARKER;
+       tombstone->n.next_tombstone = chunk->next_tombstone;
+       chunk->next_tombstone = tombstone;
 
        return tombstone;
 }
@@ -716,7 +715,7 @@ jit_info_table_remove (MonoJitInfoTable *table, MonoJitInfo *ji)
  found:
        g_assert (chunk->data [pos] == ji);
 
-       chunk->data [pos] = mono_jit_info_make_tombstone (ji);
+       chunk->data [pos] = mono_jit_info_make_tombstone (chunk, ji);
 
        /* Debugging code, should be removed. */
        //jit_info_table_check (table);
@@ -840,7 +839,7 @@ jit_info_next_value (gpointer value)
 {
        MonoJitInfo *info = (MonoJitInfo*)value;
 
-       return (gpointer*)&info->next_jit_code_hash;
+       return (gpointer*)&info->n.next_jit_code_hash;
 }
 
 void