From patchwork Mon Jul 19 14:53:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kroah-Hartman X-Patchwork-Id: 480015 Delivered-To: patch@linaro.org Received: by 2002:a02:c94a:0:0:0:0:0 with SMTP id u10csp4281165jao; Mon, 19 Jul 2021 09:23:14 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzuMcQiW8rTWSwvjEVgT16GG9zcCg5g/iRZyLDec9HmZiHWbOJFtVaCFyym2k8cPWKG2A9N X-Received: by 2002:a17:906:a185:: with SMTP id s5mr27637915ejy.96.1626711691183; Mon, 19 Jul 2021 09:21:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1626711691; cv=none; d=google.com; s=arc-20160816; b=MS8WfdU2hkfzN7ZxkEIZcTSQdK9SounR/WVMA7MhT8XavNWBrmOBRSNZ+bdmCSnEpE qsZhvmZ5nU3h1RtQd4vHLptmA+uOq+fyyeVVxIfQlD3bY0Ht3nEb77n8VshEyI/tlnQl Pz9XvxfpbWwFu1b0He+hVEOVXjvupRksycZgw8tjqp1kpZTZlhl3T/GCglC8kmir/OaB TL93DBgkVr+bQKuPsIMeCrOKDb1IgjHD7SKzwQiAvYSh3lDQeGohOxqpaNQhAgilx8BR 3M69IxITm+Gm2mCbWkPAqSPYdPKORP9lXAE2zcIVL+0WJ73hmgF9cWD9Q3cQySU5ehiD zifw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=YhV4s8HzCxwq4ySSphL2HiOOu0muO0aAdLLau9xs44U=; b=la/iWFLfbs8hpWoKVNPvnYCYngcXZowzvr8STiYN8Uyd9KhKyiJOduCXcG8h/+znkk WG0t3tJ0xs8TsQsh/QUpNwk1NHd/Lh32seHt5bwsHzcM0UI73is3sj2mIkOax/16pxci KyCUiaQJ1QVq3M+qAJQs2qGp9kt2pnYnaLGZeCYpOApKIlZy/dH48ta7gux328dV+VMp H6oMRp5Ovk9m4EDS5YW35HvBBpoD5eidYYGQXZsdIoQg2+5Hs9g5QOK34/sqGQvkGSa1 2qAPbnXEKymS5LtWVNhG4BMmLpoCWbnFG+O/SfF825YObpvJSvbMwhELtIaX1I4WDgiu cHXQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=fEBoH40W; spf=pass (google.com: domain of stable-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id la14si22045543ejc.142.2021.07.19.09.21.31; Mon, 19 Jul 2021 09:21:31 -0700 (PDT) Received-SPF: pass (google.com: domain of stable-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=fEBoH40W; spf=pass (google.com: domain of stable-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245420AbhGSPiF (ORCPT + 12 others); Mon, 19 Jul 2021 11:38:05 -0400 Received: from mail.kernel.org ([198.145.29.99]:56632 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348470AbhGSPfZ (ORCPT ); Mon, 19 Jul 2021 11:35:25 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 24BFB6161F; Mon, 19 Jul 2021 16:13:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1626711227; bh=QhB3fuEgoUJggLBXEFnE+5pmiY1T3OzUYbMVISNzp6M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fEBoH40W3mC4tIsJ28E9bXKzfxY6vGKVaeRnEURQ9rewE+AV30oJBIXAMlvU8CI0h cshdyndEj+VF36o2tlk+LR7T2b8BtT+zbg4IL3XJwTwkp/arkBmGDHoMTlx5gcGUrJ gVJv7Xosde5DJ7DedAwdUVGT9oOiie3nOdfnLS54= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, "Paul E. McKenney" , Vincent Guittot , Ionela Voinescu , Qian Cai , Viresh Kumar , Sasha Levin Subject: [PATCH 5.13 241/351] arch_topology: Avoid use-after-free for scale_freq_data Date: Mon, 19 Jul 2021 16:53:07 +0200 Message-Id: <20210719144952.920595699@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210719144944.537151528@linuxfoundation.org> References: <20210719144944.537151528@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Viresh Kumar [ Upstream commit 83150f5d05f065fb5c12c612f119015cabdcc124 ] Currently topology_scale_freq_tick() (which gets called from scheduler_tick()) may end up using a pointer to "struct scale_freq_data", which was previously cleared by topology_clear_scale_freq_source(), as there is no protection in place here. The users of topology_clear_scale_freq_source() though needs a guarantee that the previously cleared scale_freq_data isn't used anymore, so they can free the related resources. Since topology_scale_freq_tick() is called from scheduler tick, we don't want to add locking in there. Use the RCU update mechanism instead (which is already used by the scheduler's utilization update path) to guarantee race free updates here. synchronize_rcu() makes sure that all RCU critical sections that started before it is called, will finish before it returns. And so the callers of topology_clear_scale_freq_source() don't need to worry about their callback getting called anymore. Cc: Paul E. McKenney Fixes: 01e055c120a4 ("arch_topology: Allow multiple entities to provide sched_freq_tick() callback") Tested-by: Vincent Guittot Reviewed-by: Ionela Voinescu Tested-by: Qian Cai Signed-off-by: Viresh Kumar Signed-off-by: Sasha Levin --- drivers/base/arch_topology.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) -- 2.30.2 diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index c1179edc0f3b..921312a8d957 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -18,10 +18,11 @@ #include #include #include +#include #include #include -static DEFINE_PER_CPU(struct scale_freq_data *, sft_data); +static DEFINE_PER_CPU(struct scale_freq_data __rcu *, sft_data); static struct cpumask scale_freq_counters_mask; static bool scale_freq_invariant; @@ -66,16 +67,20 @@ void topology_set_scale_freq_source(struct scale_freq_data *data, if (cpumask_empty(&scale_freq_counters_mask)) scale_freq_invariant = topology_scale_freq_invariant(); + rcu_read_lock(); + for_each_cpu(cpu, cpus) { - sfd = per_cpu(sft_data, cpu); + sfd = rcu_dereference(*per_cpu_ptr(&sft_data, cpu)); /* Use ARCH provided counters whenever possible */ if (!sfd || sfd->source != SCALE_FREQ_SOURCE_ARCH) { - per_cpu(sft_data, cpu) = data; + rcu_assign_pointer(per_cpu(sft_data, cpu), data); cpumask_set_cpu(cpu, &scale_freq_counters_mask); } } + rcu_read_unlock(); + update_scale_freq_invariant(true); } EXPORT_SYMBOL_GPL(topology_set_scale_freq_source); @@ -86,22 +91,32 @@ void topology_clear_scale_freq_source(enum scale_freq_source source, struct scale_freq_data *sfd; int cpu; + rcu_read_lock(); + for_each_cpu(cpu, cpus) { - sfd = per_cpu(sft_data, cpu); + sfd = rcu_dereference(*per_cpu_ptr(&sft_data, cpu)); if (sfd && sfd->source == source) { - per_cpu(sft_data, cpu) = NULL; + rcu_assign_pointer(per_cpu(sft_data, cpu), NULL); cpumask_clear_cpu(cpu, &scale_freq_counters_mask); } } + rcu_read_unlock(); + + /* + * Make sure all references to previous sft_data are dropped to avoid + * use-after-free races. + */ + synchronize_rcu(); + update_scale_freq_invariant(false); } EXPORT_SYMBOL_GPL(topology_clear_scale_freq_source); void topology_scale_freq_tick(void) { - struct scale_freq_data *sfd = *this_cpu_ptr(&sft_data); + struct scale_freq_data *sfd = rcu_dereference_sched(*this_cpu_ptr(&sft_data)); if (sfd) sfd->set_freq_scale();