aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Dias <joaodias@google.com>2016-11-09 11:03:57 -0800
committerPat Tjin <pattjin@google.com>2016-11-17 19:12:49 +0000
commit3118fef33be5cb887e21ee70fb21d40d52d1a36f (patch)
tree670bb6c12698bb5461d3d287c97cdcdecb466c52
parent3887caac32849f127eccdd4e7dec08957eeffe2a (diff)
perf: don't leave group_entry on sibling list (use-after-free)android-7.1.1_r0.19
When perf_group_detach is called on a group leader, it should empty its sibling list. Otherwise, when a sibling is later deallocated, list_del_event() removes the sibling's group_entry from its current list, which can be the now-deallocated group leader's sibling list (use-after-free bug). Bug: 32402548 Change-Id: I99f6bc97c8518df1cb0035814368012ba72ab1f1 Signed-off-by: John Dias <joaodias@google.com>
-rw-r--r--kernel/events/core.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 32b7ca93a75a..d8a33cbc9fe3 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1228,10 +1228,17 @@ static void perf_group_detach(struct perf_event *event)
* If this was a group event with sibling events then
* upgrade the siblings to singleton events by adding them
* to whatever list we are on.
+ * If this isn't on a list, make sure we still remove the sibling's
+ * group_entry from this sibling_list; otherwise, when that sibling
+ * is later deallocated, it will try to remove itself from this
+ * sibling_list, which may well have been deallocated already,
+ * resulting in a use-after-free.
*/
list_for_each_entry_safe(sibling, tmp, &event->sibling_list, group_entry) {
if (list)
list_move_tail(&sibling->group_entry, list);
+ else
+ list_del_init(&sibling->group_entry);
sibling->group_leader = sibling;
/* Inherit group flags from the previous leader */