Merge "liblog: free event tag map in __android_log_close()" am: 1dfa8112ce am: 7d1c2ab2bc am: 3c947ae165
am: 4355c4e07a

Change-Id: Id7ee752e440ef43a043ed7a8c536477e4fe50aeb
diff --git a/liblog/event_tag_map.c b/liblog/event_tag_map.c
index 345f0d3..3e0b6b5 100644
--- a/liblog/event_tag_map.c
+++ b/liblog/event_tag_map.c
@@ -120,6 +120,7 @@
         return;
 
     munmap(map->mapAddr, map->mapLen);
+    free(map->tagArray);
     free(map);
 }
 
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index c7b5a84..08e6348 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -132,12 +132,20 @@
     }
     return kLogNotAvailable;
 }
+
+#if defined(__BIONIC__)
+static atomic_uintptr_t tagMap;
+#endif
+
 /*
  * Release any logger resources. A new log write will immediately re-acquire.
  */
 LIBLOG_ABI_PUBLIC void __android_log_close()
 {
     struct android_log_transport_write *transport;
+#if defined(__BIONIC__)
+    EventTagMap *m;
+#endif
 
     __android_log_lock();
 
@@ -165,7 +173,28 @@
         }
     }
 
+#if defined(__BIONIC__)
+    /*
+     * Additional risk here somewhat mitigated by immediately unlock flushing
+     * the processor cache. The multi-threaded race that we choose to accept,
+     * to minimize locking, is an atomic_load in a writer picking up a value
+     * just prior to entering this routine. There will be an use after free.
+     *
+     * Again, anyone calling this is doing so to release the logging resources
+     * is most probably going to quiesce then shut down; or to restart after
+     * a fork so the risk should be non-existent. For this reason we
+     * choose a mitigation stance for efficiency instead of incuring the cost
+     * of a lock for every log write.
+     */
+    m = (EventTagMap *)atomic_exchange(&tagMap, (uintptr_t)0);
+#endif
+
     __android_log_unlock();
+
+#if defined(__BIONIC__)
+    android_closeEventTagMap(m);
+#endif
+
 }
 
 /* log_init_lock assumed */
@@ -250,7 +279,6 @@
             return -EPERM;
         }
     } else if (log_id == LOG_ID_EVENTS) {
-        static atomic_uintptr_t map;
         const char *tag;
         EventTagMap *m, *f;
 
@@ -260,11 +288,11 @@
 
         tag = NULL;
         f = NULL;
-        m = (EventTagMap *)atomic_load(&map);
+        m = (EventTagMap *)atomic_load(&tagMap);
 
         if (!m) {
             ret = __android_log_trylock();
-            m = (EventTagMap *)atomic_load(&map); /* trylock flush cache */
+            m = (EventTagMap *)atomic_load(&tagMap); /* trylock flush cache */
             if (!m) {
                 m = android_openEventTagMap(EVENT_TAG_MAP_FILE);
                 if (ret) { /* trylock failed, use local copy, mark for close */
@@ -273,7 +301,7 @@
                     if (!m) { /* One chance to open map file */
                         m = (EventTagMap *)(uintptr_t)-1LL;
                     }
-                    atomic_store(&map, (uintptr_t)m);
+                    atomic_store(&tagMap, (uintptr_t)m);
                 }
             }
             if (!ret) { /* trylock succeeded, unlock */