From patchwork Sat Mar 12 14:09:13 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gavin Guo X-Patchwork-Id: 596655 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 3qMm9G3kwZz9sDG; Sun, 13 Mar 2016 01:09:38 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=canonical-com.20150623.gappssmtp.com header.i=@canonical-com.20150623.gappssmtp.com header.b=oggrGVcE; dkim-atps=neutral Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1aekEZ-0000dY-Bw; Sat, 12 Mar 2016 14:09:35 +0000 Received: from mail-qg0-f44.google.com ([209.85.192.44]) by huckleberry.canonical.com with esmtps (TLS1.0:RSA_ARCFOUR_SHA1:16) (Exim 4.76) (envelope-from ) id 1aekEU-0000by-Iq for kernel-team@lists.ubuntu.com; Sat, 12 Mar 2016 14:09:30 +0000 Received: by mail-qg0-f44.google.com with SMTP id y89so120726127qge.2 for ; Sat, 12 Mar 2016 06:09:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical-com.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:in-reply-to:references; bh=HU3KBoOaGQMthWwTcv+V5FyHyNhBRgnA1xszAt4HRkE=; b=oggrGVcE4rzfzSs+p5JI7vQnFkzOGzKVCqIEVNtCxC49ZNNmT2TtJmIw1L2mJ6v0Gp xYo0LcMnOWaucgYMu7uM3nQYclAyP6gXJMP2aAQ+OOFn4qtOtTDWCQSjoEkXHaOmu7LV 0LE2HFEIyR54Vmuiy9QSOFqINRqkdKzyv1s1SfmnBNNXW7B2M+anUJGxs9L4Su7lT6Fc zJiQ4WhhIrNpSXdR9Y+a4gTWAn0sW2YrE2Nen50BvTWxzrDmoaI6FWZZ/o+A/jMxMh/5 3qwH5GKz8RmD1tOAa8ZUZAYOwGG3Ln63ty4NDiF+efyc7LX4j9BqrbjolV07Va+v0Qf1 bvzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=HU3KBoOaGQMthWwTcv+V5FyHyNhBRgnA1xszAt4HRkE=; b=Yg7vZSPLG6aOzfhkuBVJx9xx3DvJ3o0D0rEcjG077rDROJONcaunWvMaGmLu6fLRnb 8HQ4/kRJz1JAtk25/5KjqNAgr2AA+pFRZrPQoXGsbfxg6piG+rRzM62LwEkT9sAbhkwl UPRw8VfV8lUNIJiw0ypA9hCKbUYIAQIXWCaKqy8RVapDyfBgbnXKA3HoxmIepc2oDozL T1bN721/bWw+ekvVpoXXMo1ZXAL//bMR8bmbCkMysoRy6CfJKZ97bZneObwzQVJ+TD9b 5FmnMg0s1ULhqXL/9MNa1ZM6egl4l8oqk6ecbT6HUDChj34FwBkO+cfVE1/YFfnZu0v4 2TOQ== X-Gm-Message-State: AD7BkJLH8NKvMfYRDhwO4pZT8xDAvhULZyB44skHDYrDazSwgoZUaePekCZh93nmFmyyAOGl X-Received: by 10.140.175.136 with SMTP id v130mr19781661qhv.74.1457791769585; Sat, 12 Mar 2016 06:09:29 -0800 (PST) Received: from localhost.localdomain (114-35-245-81.HINET-IP.hinet.net. [114.35.245.81]) by smtp.gmail.com with ESMTPSA id z110sm6131857qgd.45.2016.03.12.06.09.28 for (version=TLS1_1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 12 Mar 2016 06:09:29 -0800 (PST) From: Gavin Guo To: kernel-team@lists.ubuntu.com Subject: [SRU][Trusty][PATCH 2/3] sched/numa: Fix unsafe get_task_struct() in task_numa_assign() Date: Sat, 12 Mar 2016 22:09:13 +0800 Message-Id: <1457791755-7266-6-git-send-email-gavin.guo@canonical.com> X-Mailer: git-send-email 2.0.0 In-Reply-To: <1457791755-7266-1-git-send-email-gavin.guo@canonical.com> References: <1457791755-7266-1-git-send-email-gavin.guo@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.14 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: kernel-team-bounces@lists.ubuntu.com From: Kirill Tkhai BugLink: https://bugs.launchpad.net/bugs/1527643 Unlocked access to dst_rq->curr in task_numa_compare() is racy. If curr task is exiting this may be a reason of use-after-free: task_numa_compare() do_exit() ... current->flags |= PF_EXITING; ... release_task() ... ~~delayed_put_task_struct()~~ ... schedule() rcu_read_lock() ... cur = ACCESS_ONCE(dst_rq->curr) ... ... rq->curr = next; ... context_switch() ... finish_task_switch() ... put_task_struct() ... __put_task_struct() ... free_task_struct() task_numa_assign() ... get_task_struct() ... As noted by Oleg: <task_numa_assign() path does get_task_struct(dst_rq->curr) and this is not safe. The task_struct itself can't go away, but rcu_read_lock() can't save us from the final put_task_struct() in finish_task_switch(); this reference goes away without rcu gp>> The patch provides simple check of PF_EXITING flag. If it's not set, this guarantees that call_rcu() of delayed_put_task_struct() callback hasn't happened yet, so we can safely do get_task_struct() in task_numa_assign(). Locked dst_rq->lock protects from concurrency with the last schedule(). Reusing or unmapping of cur's memory may happen without it. Suggested-by: Oleg Nesterov Signed-off-by: Kirill Tkhai Signed-off-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Link: http://lkml.kernel.org/r/1413962231.19914.130.camel@tkhai Signed-off-by: Ingo Molnar (cherry picked from commit 1effd9f19324efb05fccc7421530e11a52db0278) Signed-off-by: Gavin Guo --- kernel/sched/fair.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ce501de4d682..35bf8b92feec 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -1060,9 +1060,19 @@ static void task_numa_compare(struct task_numa_env *env, long imp = (groupimp > 0) ? groupimp : taskimp; rcu_read_lock(); - cur = ACCESS_ONCE(dst_rq->curr); - if (cur->pid == 0) /* idle */ + + raw_spin_lock_irq(&dst_rq->lock); + cur = dst_rq->curr; + /* + * No need to move the exiting task, and this ensures that ->curr + * wasn't reaped and thus get_task_struct() in task_numa_assign() + * is safe under RCU read lock. + * Note that rcu_read_lock() itself can't protect from the final + * put_task_struct() after the last schedule(). + */ + if ((cur->flags & PF_EXITING) || is_idle_task(cur)) cur = NULL; + raw_spin_unlock_irq(&dst_rq->lock); /* * "imp" is the fault differential for the source task between the