Received: by 2002:ac0:8c9a:0:0:0:0:0 with SMTP id r26csp306425ima; Thu, 31 Jan 2019 17:13:08 -0800 (PST) X-Google-Smtp-Source: ALg8bN511573If4LWQ4gPAp+ZuLSMCeUywFZJ5jkmwMrZ6UWGXMygbK2R6rYoki5Uq+k/yJKSddL X-Received: by 2002:a17:902:a50a:: with SMTP id s10mr35394395plq.278.1548983588332; Thu, 31 Jan 2019 17:13:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1548983588; cv=none; d=google.com; s=arc-20160816; b=DDvyPq3AhVvl5zWHrdgSdRUFTrMMcC4gTavhWFJ9CmuG3HnHFu5xq5EgY7cPnCgXoI N5gwvCr9FUL44RCHKgE/viWL8/Igp4MOAq5pHfFxIWU2tu+OHTU+0kEjBS29NKPkyep/ DGn9tiTjqgQbzbBEcrm+yBBH9HenjY4xghbtEf6iY9bLmGap34npUe2x7AmZfbaVZuPs pJ87V+a0Y9KyysWvvnYpuUWQac+y6mXdGa9/Fsu+2KfZfn/Nb9yv3oEKMU4cFA7ZwnI7 k1Lf+zBdMadNPut0BBHacDwVoo1T4QEH093HXaKh04W29XSfLLEWIHT19ARpvI1DoQuo GOgA== 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 :references:in-reply-to:message-id:date:subject:cc:to:from; bh=UBvzdf3Sx3TWcyELSVgZvDPrCAmfzH/ctwhv/ietxFc=; b=n1saT/nHIjBuKZ3VY3G4meLiqqU9DxkghWsfQlP/gejnB/u1uy2qpawDdujiTx8maa 3hyh/UDiehJMu9sJ0VwQRxmnPuaXDMubC4W8lxKreEgytTLbp6d/19QnaH0E7IxK2hED x/RpHQHKN/FOdexEU9tnPaOnw3TorLxMqUkjV7fI1KP8eFr7IEMXeD8Ph5HEko2gKSDD ez6/Xf6S3utI4Soy7FWAqmyZbrllrn/mKvcuz9dW8Y1POzlWObtiWA0KXNgakCark2du 5bPrL3ltJzJ1bIF/tQHhaYZKy85AFD1r/u1vi9ZzypjV274AQaVb/LIex6DLimj7F13l y49w== 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 a18si5133439pgj.77.2019.01.31.17.12.52; Thu, 31 Jan 2019 17:13:08 -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 S1728718AbfBABEN (ORCPT + 99 others); Thu, 31 Jan 2019 20:04:13 -0500 Received: from cloudserver094114.home.pl ([79.96.170.134]:64615 "EHLO cloudserver094114.home.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727737AbfBABEF (ORCPT ); Thu, 31 Jan 2019 20:04:05 -0500 Received: from 79.184.255.169.ipv4.supernova.orange.pl (79.184.255.169) (HELO aspire.rjw.lan) by serwer1319399.home.pl (79.96.170.134) with SMTP (IdeaSmtpServer 0.83.183) id 29387df70406e268; Fri, 1 Feb 2019 02:04:03 +0100 From: "Rafael J. Wysocki" To: Greg Kroah-Hartman Cc: LKML , Linux PM , Ulf Hansson , Daniel Vetter , Lukas Wunner , Andrzej Hajda , Russell King - ARM Linux , Lucas Stach , Linus Walleij , Thierry Reding , Laurent Pinchart , Marek Szyprowski , Joerg Roedel Subject: [PATCH v2 1/9] driver core: Fix DL_FLAG_AUTOREMOVE_SUPPLIER device link flag handling Date: Fri, 01 Feb 2019 01:45:55 +0100 Message-ID: <1798513.IhqZgjcq75@aspire.rjw.lan> In-Reply-To: <1952449.TVsm6CJCTy@aspire.rjw.lan> References: <1952449.TVsm6CJCTy@aspire.rjw.lan> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit 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 From: Rafael J. Wysocki Change the list walk in device_links_driver_cleanup() to a safe one to avoid use-after-free when dropping a link from the list during the walk. Also, while at it, fix device_link_add() to refuse to create stateless device links with DL_FLAG_AUTOREMOVE_SUPPLIER set, which is an invalid combination (setting that flag means that the driver core should manage the link, so it cannot be stateless), and extend the kerneldoc comment of device_link_add() to cover the DL_FLAG_AUTOREMOVE_SUPPLIER flag properly too. Fixes: 1689cac5b32a ("driver core: Add flag to autoremove device link on supplier unbind") Signed-off-by: Rafael J. Wysocki --- drivers/base/core.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) Index: linux-pm/drivers/base/core.c =================================================================== --- linux-pm.orig/drivers/base/core.c +++ linux-pm/drivers/base/core.c @@ -179,10 +179,14 @@ void device_pm_move_to_tail(struct devic * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be * ignored. * - * If the DL_FLAG_AUTOREMOVE_CONSUMER is set, the link will be removed - * automatically when the consumer device driver unbinds from it. - * The combination of both DL_FLAG_AUTOREMOVE_CONSUMER and DL_FLAG_STATELESS - * set is invalid and will cause NULL to be returned. + * If the DL_FLAG_AUTOREMOVE_CONSUMER flag is set, the link will be removed + * automatically when the consumer device driver unbinds from it. Analogously, + * if DL_FLAG_AUTOREMOVE_SUPPLIER is set in @flags, the link will be removed + * automatically when the supplier device driver unbinds from it. + * + * The combination of DL_FLAG_STATELESS and either DL_FLAG_AUTOREMOVE_CONSUMER + * or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and + * will cause NULL to be returned upfront. * * A side effect of the link creation is re-ordering of dpm_list and the * devices_kset list by moving the consumer device and all devices depending @@ -199,8 +203,8 @@ struct device_link *device_link_add(stru struct device_link *link; if (!consumer || !supplier || - ((flags & DL_FLAG_STATELESS) && - (flags & DL_FLAG_AUTOREMOVE_CONSUMER))) + (flags & DL_FLAG_STATELESS && + flags & (DL_FLAG_AUTOREMOVE_CONSUMER | DL_FLAG_AUTOREMOVE_SUPPLIER))) return NULL; device_links_write_lock(); @@ -539,11 +543,11 @@ void device_links_no_driver(struct devic */ void device_links_driver_cleanup(struct device *dev) { - struct device_link *link; + struct device_link *link, *ln; device_links_write_lock(); - list_for_each_entry(link, &dev->links.consumers, s_node) { + list_for_each_entry_safe(link, ln, &dev->links.consumers, s_node) { if (link->flags & DL_FLAG_STATELESS) continue;