Received: by 2002:a25:1506:0:0:0:0:0 with SMTP id 6csp3688430ybv; Mon, 10 Feb 2020 04:44:32 -0800 (PST) X-Google-Smtp-Source: APXvYqzqFP8SeqnLUD16RLhbYpZbJouDjRLTWv474s11sXGR8BM7KZ67AmC8WpHXcX3qLDKj1gAi X-Received: by 2002:a9d:7e99:: with SMTP id m25mr891407otp.212.1581338671939; Mon, 10 Feb 2020 04:44:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1581338671; cv=none; d=google.com; s=arc-20160816; b=BcR04Cco6M+qwjfLqsnQSce9B0xIM0eC6uFUUB4gs8Q/K+p81YgjsdxyqwCUUYb7o0 HBvp7ZL6Fu75IsYpVGjD5Ifjsnaiqm9jbFUcGAp8SXTQpfbKeIKmkc+aWgoAx96Nq+DL Qi7nRr6tosbHqhyyT6skHj+qKX56Bi6h55c26D8gjl0Y/Y9zS1aOKAeSbnKs61buBKAt 066XEg1S2+m4zr7FaMUnAIhZOtmpNFLEQW36Lx8DgGuPr/rNk4fErP8HEcxWedO7qMze 0NghY5LKAiBriKtmMZ5cscNsf+0xb4qnnlYxavgD/HghHInmpiyQvh1rklDbt7mM5lQB ySqQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=d+k2NK1fiwGlOdU7Y3EyKqPUPNZNyhsZ+GPjw13FMtM=; b=YHL71qtqAiGkF+4JzcmzBLWepJ4FzcczAZF0fxb2op6k9J1kjj+5UkZwG9GzkNl4A5 N35QaHqxJwGMrNHCd4f1Cd4Ee5hET9tvukr7FOrtjEM/oYw2HqUkRCZy/bWxDNB0Wlbi B6SqoPfHMxRrgptWZamBHCIElSXhMSqsC2I2RM1bail+oPOciyTKwP31rC7UJofDDSr6 tknGVbSB43Z+kY+pJHnw7I4tTkHP4NXz2rGXfcCXRXk1Qlu0l0FMFxzNJRZtyR/Qowgk KJyDFiQhbhHCYjy5hf7YagRkcdagCD0JoJTor3Ti7EF7v5iPRCe4fCLljbMF+rIrXOIE eJPA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=XaLP77e3; 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 k15si117226oij.134.2020.02.10.04.44.20; Mon, 10 Feb 2020 04:44:31 -0800 (PST) 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; dkim=pass header.i=@kernel.org header.s=default header.b=XaLP77e3; 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 S1730139AbgBJMoE (ORCPT + 99 others); Mon, 10 Feb 2020 07:44:04 -0500 Received: from mail.kernel.org ([198.145.29.99]:40142 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729700AbgBJMkU (ORCPT ); Mon, 10 Feb 2020 07:40:20 -0500 Received: from localhost (unknown [209.37.97.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 3FCE220838; Mon, 10 Feb 2020 12:40:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581338419; bh=48TEUTnydgvfKvfHMu92SI76lcQD60sAxKeahChds5g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XaLP77e3Fucy3NTtx6KqVe8yvQz/17qfxm2wmhbOhGJQIa1ZrXDHxZQ+yBr+45m2q pgdVzMo9frWHmhKDL6qY7bTdi9YiO5NWUta8zJoDtHkBSMA4IK6egZzfcUFeY//jRo o06BO0Og2UMOs6umR2rbSpLdeXHu8CGWlvmgGjoQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Chanho Min , "Rafael J. Wysocki" Subject: [PATCH 5.5 136/367] PM: core: Fix handling of devices deleted during system-wide resume Date: Mon, 10 Feb 2020 04:30:49 -0800 Message-Id: <20200210122437.424309269@linuxfoundation.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200210122423.695146547@linuxfoundation.org> References: <20200210122423.695146547@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Rafael J. Wysocki commit 0552e05fdfea191a2cf3a0abd33574b5ef9ca818 upstream. If a device is deleted by one of its system-wide resume callbacks (for example, because it does not appear to be present or accessible any more) along with its children, the resume of the children may continue leading to use-after-free errors and other issues (potentially). Namely, if the device's children are resumed asynchronously, their resume may have been scheduled already before the device's callback runs and so the device may be deleted while dpm_wait_for_superior() is being executed for them. The memory taken up by the parent device object may be freed then while dpm_wait() is waiting for the parent's resume callback to complete, which leads to a use-after-free. Moreover, the resume of the children is really not expected to continue after they have been unregistered, so it must be terminated right away in that case. To address this problem, modify dpm_wait_for_superior() to check if the target device is still there in the system-wide PM list of devices and if so, to increment its parent's reference counter, both under dpm_list_mtx which prevents device_del() running for the child from dropping the parent's reference counter prematurely. If the device is not present in the system-wide PM list of devices any more, the resume of it cannot continue, so check that again after dpm_wait() returns, which means that the parent's callback has been completed, and pass the result of that check to the caller of dpm_wait_for_superior() to allow it to abort the device's resume if it is not there any more. Link: https://lore.kernel.org/linux-pm/1579568452-27253-1-git-send-email-chanho.min@lge.com Reported-by: Chanho Min Cc: All applicable Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/main.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -273,10 +273,38 @@ static void dpm_wait_for_suppliers(struc device_links_read_unlock(idx); } -static void dpm_wait_for_superior(struct device *dev, bool async) +static bool dpm_wait_for_superior(struct device *dev, bool async) { - dpm_wait(dev->parent, async); + struct device *parent; + + /* + * If the device is resumed asynchronously and the parent's callback + * deletes both the device and the parent itself, the parent object may + * be freed while this function is running, so avoid that by reference + * counting the parent once more unless the device has been deleted + * already (in which case return right away). + */ + mutex_lock(&dpm_list_mtx); + + if (!device_pm_initialized(dev)) { + mutex_unlock(&dpm_list_mtx); + return false; + } + + parent = get_device(dev->parent); + + mutex_unlock(&dpm_list_mtx); + + dpm_wait(parent, async); + put_device(parent); + dpm_wait_for_suppliers(dev, async); + + /* + * If the parent's callback has deleted the device, attempting to resume + * it would be invalid, so avoid doing that then. + */ + return device_pm_initialized(dev); } static void dpm_wait_for_consumers(struct device *dev, bool async) @@ -621,7 +649,8 @@ static int device_resume_noirq(struct de if (!dev->power.is_noirq_suspended) goto Out; - dpm_wait_for_superior(dev, async); + if (!dpm_wait_for_superior(dev, async)) + goto Out; skip_resume = dev_pm_may_skip_resume(dev); @@ -829,7 +858,8 @@ static int device_resume_early(struct de if (!dev->power.is_late_suspended) goto Out; - dpm_wait_for_superior(dev, async); + if (!dpm_wait_for_superior(dev, async)) + goto Out; callback = dpm_subsys_resume_early_cb(dev, state, &info); @@ -944,7 +974,9 @@ static int device_resume(struct device * goto Complete; } - dpm_wait_for_superior(dev, async); + if (!dpm_wait_for_superior(dev, async)) + goto Complete; + dpm_watchdog_set(&wd, dev); device_lock(dev);