From c6a5b958e655d6d23bdede8103876d5ffe1c56b6 Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Tue, 13 Mar 2018 16:03:15 +0530 Subject: [PATCH] sched/walt: Fix use after free in trace_sched_update_task_ravg() commit 4d09122c1868 ("sched: Fix spinlock recursion in sched_exit()") moved freeing of task's current and previous window arrays outside the rq->lock. These arrays can be accessed from another CPU in parallel and end up using freed memory. For example, CPU#0 CPU#1 ---------------------------------- ------------------------------- sched_exit() try_to_wake_up()--> The task wakes up on CPU#0 task_rq_lock() set_task_cpu() fixup_busy_time() --> waiting for CPU#0's rq->lock task_rq_unlock() fixup_busy_time()-->lock acquired free_task_load_ptrs() kfree(p->ravg.curr_window_cpu) update_task_ravg()-->called on current of CPU#0 trace_sched_update_task_ravg() --> access freed memory p->ravg.curr_window_cpu = NULL; To fix this issue, window array pointers must be set to NULL before freeing the memory. Since this happens outside the lock, memory barriers are needed on write and read paths. A much simpler alternative would be skipping update_task_ravg() trace point for tasks that are marked as dead. The window stats of dead tasks are not updated any ways. While at it, skip this trace point for newly created tasks for which also window stats are not updated. Change-Id: I4d7cb8a3cf7cf84270b09721140d35205643b7ab Signed-off-by: Pavankumar Kondeti [spathi@codeaurora.org: moved changes to hmp.c since EAS is not supported] Signed-off-by: Srinivasarao P --- kernel/sched/hmp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c index ea066ab8376b..d9f0669ff683 100644 --- a/kernel/sched/hmp.c +++ b/kernel/sched/hmp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2881,11 +2881,15 @@ void update_task_ravg(struct task_struct *p, struct rq *rq, int event, update_task_burst(p, rq, event, runtime); update_cpu_busy_time(p, rq, event, wallclock, irqtime); update_task_pred_demand(rq, p, event); -done: + + if (exiting_task(p)) + goto done; + trace_sched_update_task_ravg(p, rq, event, wallclock, irqtime, rq->cc.cycles, rq->cc.time, p->grp ? &rq->grp_time : NULL); +done: p->ravg.mark_start = wallclock; } -- 2.11.0