Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp3169310ybl; Mon, 20 Jan 2020 17:32:11 -0800 (PST) X-Google-Smtp-Source: APXvYqwiCSn0sX0bJH6KoOXpO3Ao2rb3TytsKuK+tHIP0IQvtDP0cQX2xcjN4D7U+MrYgzpZVkvL X-Received: by 2002:a05:6830:10d7:: with SMTP id z23mr1801193oto.114.1579570331440; Mon, 20 Jan 2020 17:32:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1579570331; cv=none; d=google.com; s=arc-20160816; b=kXu0WvKCrBpXGNTmAQENwtyogwq4dtcjoolyQHzqLLhvz53gNvs8ayleMdv5/RQ8G8 6G42nhokVm0iRAVJzNyIKDlX4cpxM/seNPDwsFKn68dDOoNGfI7VN62bMKK65zAzLxvr LbJ/uX7/NePxyclqDEKkhx/pr+7lsB1KGiWLhFkInzQtAeu7rdepooFaSuf0btZK33du LR0bRdPzOpPAMayYG7AFWU3MOxRc304m05FsmYGUPYSPR7L97pE/9wrHaw7rOeDu+eWf Ts5XTcOsmjW6DxaG18D2SN2fBqhjb+kfetHrh9NjcAEcz4l+l2/oxgjjxombH0y9mX0d g2XA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from; bh=j5jPhr3E87V+BS5XAheU6deCGrcAvYlTyLcmlUGN/wA=; b=BQcWS489gj7TeEZexVKI5ZOyDRk73HZMsZXRwOUF9wR02hmiqxNnpKag1NJGBsxCet S1ddLs11RIT4cu8eiH1OvOuk64ZYQS4SMNgEQZrm1omYCaiSAaK4Lb2guJcToI8nqFtP c5ZrnRiVT/PGJZxLC34dlazcrZ+xFynqL4GeKONOmgrcS2p4RwXdo6YPbhT+9ZrzKUKz hasoWggjNJGDnZzBs/7JtTfZ1OIdtZXCb5mi0vyp52c6YE33/L0zq/bn5Z4tyv+ZRXWp uiXYzkC2OziQP6eH4V/51wMpoRnht1N09JqdkYiTpHO19vBt18IpNiqy7WRBNzMi2mT6 a7Qw== 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 g6si20966894otk.171.2020.01.20.17.31.57; Mon, 20 Jan 2020 17:32:11 -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; 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 S1728829AbgAUBa7 (ORCPT + 99 others); Mon, 20 Jan 2020 20:30:59 -0500 Received: from lgeamrelo11.lge.com ([156.147.23.51]:47973 "EHLO lgeamrelo11.lge.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727009AbgAUBa7 (ORCPT ); Mon, 20 Jan 2020 20:30:59 -0500 X-Greylist: delayed 1799 seconds by postgrey-1.27 at vger.kernel.org; Mon, 20 Jan 2020 20:30:57 EST Received: from unknown (HELO lgeamrelo04.lge.com) (156.147.1.127) by 156.147.23.51 with ESMTP; 21 Jan 2020 10:00:55 +0900 X-Original-SENDERIP: 156.147.1.127 X-Original-MAILFROM: chanho.min@lge.com Received: from unknown (HELO localhost.localdomain) (10.178.31.96) by 156.147.1.127 with ESMTP; 21 Jan 2020 10:00:55 +0900 X-Original-SENDERIP: 10.178.31.96 X-Original-MAILFROM: chanho.min@lge.com From: Chanho Min To: "Rafael J. Wysocki" , Pavel Machek , Len Brown , Greg Kroah-Hartman Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Daewoong Kim , Seokjoo Lee , Lee Gunho , Chanho Min Subject: [PATCH] PM / sleep: fix use-after-free on async resume Date: Tue, 21 Jan 2020 10:00:52 +0900 Message-Id: <1579568452-27253-1-git-send-email-chanho.min@lge.com> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Some device can be released during suspend (e.g. usb disconnection). But, Its child device still use dev->parent's lock in dpm_wait(). It can be ocurred use-after-free as bellows. This is happened during usb resume in practice. device hierarchy: "1-1" <- "1-1:1.2" <- "ep83" device_resume("1-1:1.2") dpm_wait("1-1") device_resume("ep_83"); dpm_wait("1-1:1.2"); usb_disconnect put_device("1-1:1.2") put_device("1-1:1.2") usb_release_interface kfree(intf) <- "1-1:1.2"'s struct device is freed wait_for_common do { ... spin_lock_irq(&x->wait.lock); <- "1-1:1-2"'s lock } while (!x->done && timeout); This is call stack of the system hang caused by freed lock value in practice. Call trace: [] _raw_spin_lock_irq+0x38/0x80 [] wait_for_common+0x12c/0x140 [] wait_for_completion+0x14/0x20 [] dpm_wait+0x5c/0xb0 [] device_resume+0x78/0x320 [] async_resume+0x24/0xe0 [] async_run_entry_fn+0x54/0x158 [] process_one_work+0x1e8/0x4b0 [] worker_thread+0x128/0x4b8 [] kthread+0x10c/0x110 [] ret_from_fork+0x10/0x40 To prevent such use-after-free, dpm_wait_for_parent() keeps parent's reference using get/put_device even if it is disconnected. Signed-off-by: Chanho Min Signed-off-by: Daewoong Kim --- drivers/base/power/main.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index f946511..95a7499 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -234,13 +234,29 @@ static void initcall_debug_report(struct device *dev, ktime_t calltime, * @dev: Device to wait for. * @async: If unset, wait only if the device's power.async_suspend flag is set. */ +static void _dpm_wait(struct device *dev, bool async) +{ + if (async || (pm_async_enabled && dev->power.async_suspend)) + wait_for_completion(&dev->power.completion); +} + static void dpm_wait(struct device *dev, bool async) { if (!dev) return; - if (async || (pm_async_enabled && dev->power.async_suspend)) - wait_for_completion(&dev->power.completion); + _dpm_wait(dev, async); +} + +static void dpm_wait_for_parent(struct device *dev, bool async) +{ + if (dev && dev->parent) { + struct device *dev_p = dev->parent; + + get_device(dev_p); + _dpm_wait(dev_p, async); + put_device(dev_p); + } } static int dpm_wait_fn(struct device *dev, void *async_ptr) @@ -277,7 +293,7 @@ static void dpm_wait_for_suppliers(struct device *dev, bool async) static void dpm_wait_for_superior(struct device *dev, bool async) { - dpm_wait(dev->parent, async); + dpm_wait_for_parent(dev, async); dpm_wait_for_suppliers(dev, async); } -- 2.7.4