Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp252450pxj; Wed, 16 Jun 2021 01:20:56 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx0XdN5TMmQkFEO110Zf86btq1ac0qMd6vSuMEr0PYJnVB5grvR05rg0J87zjG0Fsc5dqCQ X-Received: by 2002:a17:906:1f11:: with SMTP id w17mr4041159ejj.33.1623831656251; Wed, 16 Jun 2021 01:20:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1623831656; cv=none; d=google.com; s=arc-20160816; b=I45qsV3wTlho5top9Mr9TXe1YOhMONFFU5s0GKKSi8uGzBOnjtvpqoi9quv34uQio1 KO0LDZT0XDQDUBA1Spx5Gz1g9hO6yfbJbjVly+yx/6LLxER0/wcLsqEhbE5h0Qq6AhjS QgtlotxXCP1fn7Y6fGbnMfOqU5q8o1SdywIpxPsZX+br8Fj6d9Ny/jdS17z2DpdO4/8y DToX0lKU5KZMpZqXgXpt6ZGBDwX7GGRD0MgRTVaS2YHpSk6c6dv0Qi52sGxFxm/wKAr/ a/EQpbyfOGQtdDzbLT5Hp1l3uHYW0fMCKjh+px2sxzABcpXRE407kfoxCMhtr71t4jta JXBg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:user-agent:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date :dkim-signature; bh=+AzUjtrJOh8ZWRh784rmLMzJQd1pE1/adqWdw+99bT4=; b=F2It/NElVO9ierTa5AiX+esvad9qMwtpN1zt7VJeu07hk0AVk0RT7cSs5YqGFRgcyW ZZaDyhHHkYCrGJCJwJ1jxF9MtS6vmmBsv4skCiKT3U+VT7fwtC2ZlBTJ6pKvP2pH2slp U0O/8n78aQHsck1nFPskKTNN5wNNtUpb8pyqH1otM2HLAsK9gyKCbJGtxsg5ec/Nrg3n z7K845aBOAT6jUCUkYu2XLf7adedg7LkNvJisiNQkF3qehVDEmllxB9fa1GTGYsCWGdh Ui4tCvrkjc4UqjyNJ/nlVuN7Jj2ye85X5WIjJkliOwA7T+Wh1Gacc5LMEDdvd+sNyjHy TS6Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=nqcq9amY; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id a11si1584774edn.126.2021.06.16.01.20.33; Wed, 16 Jun 2021 01:20:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-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=@linaro.org header.s=google header.b=nqcq9amY; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231638AbhFPIVI (ORCPT + 99 others); Wed, 16 Jun 2021 04:21:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231309AbhFPIVI (ORCPT ); Wed, 16 Jun 2021 04:21:08 -0400 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3A17C061574 for ; Wed, 16 Jun 2021 01:19:02 -0700 (PDT) Received: by mail-pl1-x635.google.com with SMTP id v13so726880ple.9 for ; Wed, 16 Jun 2021 01:19:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=+AzUjtrJOh8ZWRh784rmLMzJQd1pE1/adqWdw+99bT4=; b=nqcq9amYZYQtquTdDm40QUnU2urna5vkIVt25YGHbWE1PJv/OtejXkSFqDAl+BAKrN Bw79ZuawEIYG3SrfHHvNmR+gaTQJ8GOc65mIUwgifXEsXIuK/+YMGmb3x2uhLAI0CTcZ AizQez9fbr2QjQdNwy27mcKhYTNmSz0uzED29jpObh6SnHIJ2t/Q63zBJwvB8IBqOb1r Ye6o1cwDZkdPYhz25Nu6j0+8WP67wAklr+Ort09x8Lu9lpI4q+ck8SkCzAWU10MjJGQj 1wKW3EaxVWS7QUtLG9B+jAdJMJTtwNb4dFn7JOJBDIJF+1qTy+8UYANfmM0hphkpLygx LoNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=+AzUjtrJOh8ZWRh784rmLMzJQd1pE1/adqWdw+99bT4=; b=TQdG5CoFiUj5nWqsoQcnHSIYo0vY/GjT9pamIuA37/DvhLPp0J4yXo8TeBZTE42eRb jzfTV+nq01Xv5whCdx3v8exL+ehwY/rKTrKKOmtrEMqLEfH6QNYypEtgXgstN4S1g3iw GVpq3E8ZnJqQ1YoGa4RR9yMpjpqkQK1m09kTZHx0zgKyaDlXshUFafGeYRXBUZg0WeVf 74aJqIrwgQ+ITQB5HUO5PsfDMuM2BmyPIB/zKTBKv//fzsRKcCTFmzlBjH/Drn7mhFYI oe+ZojHj2OoJryR4I7NixghapBpDMDhzrUpQ+tjT8D6hT4M62bcuZByz32gs465hQUYU M5Ew== X-Gm-Message-State: AOAM530TK1FD8iSxZqDvbJD4FfEKR/eRX0MILVCUuNfGK0SevI2eJWbk cO5n+QZ03AlPiPvMVD8jX9sHDQ== X-Received: by 2002:a17:902:7244:b029:f5:2ffd:37f9 with SMTP id c4-20020a1709027244b02900f52ffd37f9mr8146848pll.26.1623831542179; Wed, 16 Jun 2021 01:19:02 -0700 (PDT) Received: from localhost ([136.185.134.182]) by smtp.gmail.com with ESMTPSA id f18sm4647252pjq.48.2021.06.16.01.19.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Jun 2021 01:19:01 -0700 (PDT) Date: Wed, 16 Jun 2021 13:48:59 +0530 From: Viresh Kumar To: Greg Kroah-Hartman Cc: Rafael Wysocki , Ionela Voinescu , Sudeep Holla , "Rafael J. Wysocki" , linux-pm@vger.kernel.org, Vincent Guittot , Qian Cai , "Paul E . McKenney" , linux-kernel@vger.kernel.org Subject: Re: [PATCH V2 2/3] arch_topology: Avoid use-after-free for scale_freq_data Message-ID: <20210616081859.idzpwzdyeu666xpz@vireshk-i7> References: <9dba462b4d09a1a8a9fbb75740b74bf91a09a3e1.1623825725.git.viresh.kumar@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: NeoMutt/20180716-391-311a52 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 16-06-21, 09:57, Greg Kroah-Hartman wrote: > On Wed, Jun 16, 2021 at 12:18:08PM +0530, Viresh Kumar wrote: > > Currently topology_scale_freq_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 previous scale_freq_data isn't used anymore. > > > > 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. > > > > Cc: Paul E. McKenney > > Signed-off-by: Viresh Kumar > > So this is a bugfix for problems in the current codebase? What commit > does this fix? Should it go to the stable kernels? There is only one user of topology_clear_scale_freq_source() (cppc-cpufreq driver, which is already reverted in pm/linux-next). So in the upcoming 5.13 kernel release, there will be no one using this API and so no one will break. And so I skipped the fixes tag, I can add it though. > > --- > > drivers/base/arch_topology.c | 27 +++++++++++++++++++++------ > > 1 file changed, 21 insertions(+), 6 deletions(-) > > > > 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(); > > What race is happening? How could the current code race? Only when a > cpu is removed? topology_scale_freq_tick() is called by the scheduler for each CPU from scheduler_tick(). It is possible that topology_scale_freq_tick() ends up using an older copy of sft_data pointer, while it is being removed by topology_clear_scale_freq_source() because a CPU went away or a cpufreq driver went away, or during normal suspend/resume (where CPUs are hot-unplugged). 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. -- viresh