From abe2e577c3685f2965656e7e7a26da0782f54004 Mon Sep 17 00:00:00 2001 From: Shaleen Agrawal Date: Mon, 8 Feb 2021 21:41:48 -0800 Subject: [PATCH] ANDROID: sched: Fix wake_q length tracking The current approach to carry the wake_q length is exposed to an intertask stack access. For example, if A sets the wake_q_head for B but is preempted before it is able to set it back to NULL, then B continues to point to an address corresponding to A's stack. If B is then woken up by another task, it ends up accessing the address pointing to A's stack. This causes a memory fault. Replace this with a simple parameter which indicates the number of tasks that are being woken up as part of the same event. This avoids saving and accessing on stack pointers. Bug: 173981591 Change-Id: I0031747d79a27673e680f7b1121eb4896ac7c699 Signed-off-by: Shaleen Agrawal (cherry picked from commit 1e674650ffcd43de38d8a68549b345683a0a5f1d) Signed-off-by: Quentin Perret --- include/linux/sched.h | 2 +- kernel/sched/core.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index e0af82762e5b..1ed22d09fdaa 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1034,7 +1034,7 @@ struct task_struct { raw_spinlock_t pi_lock; struct wake_q_node wake_q; - struct wake_q_head *wake_q_head; + int wake_q_count; #ifdef CONFIG_RT_MUTEXES /* PI waiters blocked on a rt_mutex held by this task: */ diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8d7229011d79..03e10c05e0c1 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -597,14 +597,14 @@ void wake_up_q(struct wake_q_head *head) /* Task can safely be re-inserted now: */ node = node->next; task->wake_q.next = NULL; - task->wake_q_head = head; + task->wake_q_count = head->count; /* * wake_up_process() executes a full barrier, which pairs with * the queueing in wake_q_add() so as not to miss wakeups. */ wake_up_process(task); - task->wake_q_head = NULL; + task->wake_q_count = 0; put_task_struct(task); } }