Received: by 2002:a25:6193:0:0:0:0:0 with SMTP id v141csp1558080ybb; Thu, 2 Apr 2020 03:10:41 -0700 (PDT) X-Google-Smtp-Source: APiQypIYRPbHv3Wk4e+dA44ykSKLhVa9wRkghJV9H+Uldt4cjBe6B29/snvE3ZI2u0LqeccHiJgg X-Received: by 2002:a9d:548:: with SMTP id 66mr1563659otw.227.1585822241118; Thu, 02 Apr 2020 03:10:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1585822241; cv=none; d=google.com; s=arc-20160816; b=H0QqNIGGTCtUuN4GIINWVc9PCFq+K1KHE0iWm7jCdXva1qfyRS0m82zsZbmaPgdTdn Q+R9EERrH+LOJVaBatlSSC0gsd+/GhUjawn6sBH3UW055GnNj/Rys82UCXM4C31i4udE +v5UM0PtolRnO6nkJxmhUAaw9EqgcT0Y3JrK8SLXAxCG+8uYgxVKgxwYCxPBWRzN9FUW 8it5qh2jqOIbHl8YhvRQBy7ChUJeeeG94GzIsk6DH/RkFQqI8/LY7iD17sW8MAcApRDB p5emOU/IfA/erckUoFkGIN0rYRIeHxBjr3q80TUQronYHLVwf8hw6gQwWBmvJ9DECouv hufw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:subject:cc:to:from:message-id:date; bh=iIlrAdqRzF8zXMU8UbzQCOH8yrrq+jvPy34qbjrRgB0=; b=Hx4t6FK4AJ14MImtwpdSIGe998pfE2feaPkCUxGs+pW3P1LCMbqgnKa1crujvYc7e3 If1VrGG7SyZ3baz0jfjy4A3Mt09bTcUAfV0Yko476dtVQT2bhmgpjeJ/Cc2hn4Rvlkad 14gBstcNwXK18s1pQTyPbppOkNY8SAGXMG+yFV9Uqfpln/1MLVWH9EvrUIXYrS4MHqpG ONS3eq9ZUr/7XD7UPgjSmaFVQdgPvhEzn575ZYfCtAZWM7r36wYg7Fwz5qyMyPReRxjc jv/iHdn8SA0R1sRCqTzE4TUMk+Vasfuwc0V7RdjM93mvK7PxYFq2+MLlu5Z90LNeqArB YnQg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r25si2229487otq.113.2020.04.02.03.10.28; Thu, 02 Apr 2020 03:10:41 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387726AbgDBKJz (ORCPT + 99 others); Thu, 2 Apr 2020 06:09:55 -0400 Received: from mx2.suse.de ([195.135.220.15]:41502 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728135AbgDBKJz (ORCPT ); Thu, 2 Apr 2020 06:09:55 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id EEB66AC0C; Thu, 2 Apr 2020 10:09:52 +0000 (UTC) Date: Thu, 02 Apr 2020 12:09:52 +0200 Message-ID: From: Takashi Iwai To: Zhang Rui Cc: "linux-acpi@vger.kernel.org" , "Rafael J. Wysocki" , Len Brown , "linux-kernel@vger.kernel.org" Subject: Re: OOB access on ACPI processor thermal device via sysfs write In-Reply-To: <0926f44775e91145a83c9eb88a468c64261af20d.camel@intel.com> References: <744357E9AAD1214791ACBA4B0B90926377CEB399@SHSMSX108.ccr.corp.intel.com> <0926f44775e91145a83c9eb88a468c64261af20d.camel@intel.com> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.8 Emacs/25.3 (x86_64-suse-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, 02 Apr 2020 12:03:30 +0200, Zhang Rui wrote: > > On Thu, 2020-04-02 at 11:03 +0200, Takashi Iwai wrote: > > On Thu, 02 Apr 2020 09:47:50 +0200, > > Zhang, Rui wrote: > > > > > > CC Viresh. > > > > > > Yes, I've received it. > > > > > > To me, there is not a hard rule that the cooling device max_state > > > must be static. > > > We should be able to detect the max_state change and reset the > > > stats table when necessary. > > > > > > I just finished a prototype patch to do so, and will paste it > > > later. > > > > Great, that sounds like a feasible option, indeed. > > > > > Please try the patch below and see if the problem goes away or not. > > >From 7b429674a0e1a6226734c8919b876bb57d946b1d Mon Sep 17 00:00:00 2001 > From: Zhang Rui > Date: Thu, 2 Apr 2020 11:18:44 +0800 > Subject: [RFC PATCH] thermal: update thermal stats table when max cooling > state changed > > The maximum cooling state of a cooling device may be changed at > runtime. Thus the statistics table must be updated to handle the real > maximum cooling states supported. > > This fixes an OOB issue when updating the statistics of the processor > cooling device, because it only supports 1 cooling state before cpufreq > driver loaded. > > Fixes: 8ea229511e06 ("thermal: Add cooling device's statistics in sysfs") > Reported-by: Takashi Iwai > Signed-off-by: Zhang Rui > --- > drivers/thermal/thermal_sysfs.c | 38 +++++++++++++++++++++++++++------ > 1 file changed, 31 insertions(+), 7 deletions(-) > > diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c > index aa99edb4dff7..c69173eb4b24 100644 > --- a/drivers/thermal/thermal_sysfs.c > +++ b/drivers/thermal/thermal_sysfs.c > @@ -755,6 +755,9 @@ struct cooling_dev_stats { > unsigned int *trans_table; > }; > > +static int cooling_device_stats_table_update(struct thermal_cooling_device *cdev); > +static void cooling_device_stats_destroy(struct thermal_cooling_device *cdev); > + > static void update_time_in_state(struct cooling_dev_stats *stats) > { > ktime_t now = ktime_get(), delta; > @@ -768,8 +771,12 @@ static void update_time_in_state(struct cooling_dev_stats *stats) > void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev, > unsigned long new_state) > { > - struct cooling_dev_stats *stats = cdev->stats; > + struct cooling_dev_stats *stats; > > + if (cooling_device_stats_table_update(cdev)) > + return; > + > + stats = cdev->stats; > spin_lock(&stats->lock); > > if (stats->state == new_state) > @@ -904,24 +911,32 @@ static const struct attribute_group cooling_device_stats_attr_group = { > .name = "stats" > }; > > -static void cooling_device_stats_setup(struct thermal_cooling_device *cdev) > +static int cooling_device_stats_table_update(struct thermal_cooling_device *cdev) > { > struct cooling_dev_stats *stats; > unsigned long states; > - int var; > + int var, ret; > > - if (cdev->ops->get_max_state(cdev, &states)) > - return; > + ret = cdev->ops->get_max_state(cdev, &states); > + if (ret) > + return ret; > > states++; /* Total number of states is highest state + 1 */ > > + stats = cdev->stats; > + if (stats) { > + if (stats->max_states == states) > + return 0; > + else > + cooling_device_stats_destroy(cdev); > + } This looks racy. We may have concurrent accesses and it'll lead to another access-after-free. > var = sizeof(*stats); > var += sizeof(*stats->time_in_state) * states; > var += sizeof(*stats->trans_table) * states * states; > - > stats = kzalloc(var, GFP_KERNEL); > if (!stats) > - return; > + return -ENOMEM; ... and this leaves NULL to cdev->stats. Then a later access to sysfs would lead to NULL derference. > stats->time_in_state = (ktime_t *)(stats + 1); > stats->trans_table = (unsigned int *)(stats->time_in_state + states); > @@ -930,6 +945,15 @@ static void cooling_device_stats_setup(struct thermal_cooling_device *cdev) > stats->max_states = states; > > spin_lock_init(&stats->lock); Also we must not re-initialize spinlock here at each resizing. Rather use spinlock for switching to the new table. thanks, Takashi