From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BBEF848C8AA; Thu, 11 Jun 2026 20:35:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.10 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781210150; cv=none; b=Z5GH3iuYpOUaZQ72Zq4+g59+NwB6BVUXpuz0EMujEW70ck3hXLpRgqKdup409wpyZihBHPaNXuI/H+a6up2PhSt4zhrtLXJHVKFM9YEZu8lLQwnpyrffOekAaXUU/7VpJ1TPYuQlC1ZF88ul9NgfZNIRWrenP+09pxb5X5hrTO8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781210150; c=relaxed/simple; bh=3Q2YwluvYGccTj8xHDYb4/SxtTFNcPw+qEZ+0VjwhKY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hYRSH2YcavVBLaVeZd/ylSJPwL7rRndVHgzqAGxkTfUzbR9MomN/1TPDSrhIBv7u20kAka4izKVLcD5EWAYRhnhT5RD9wX4Z0Pix/O0zg4cZ5e3q8W3a2NBmq9ZeUkDAlmVRMhWom7RUtl/1hdhSRvRbX6tTIG3Lg5KxZagDse0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=T5EYcKdy; arc=none smtp.client-ip=198.175.65.10 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="T5EYcKdy" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1781210149; x=1812746149; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3Q2YwluvYGccTj8xHDYb4/SxtTFNcPw+qEZ+0VjwhKY=; b=T5EYcKdyoMAnmKRgolDZy6xB1s+gyLtBtewW+58V/yR5PYnjy28un5VF igQuDwOGmElxOP9ovjpjGM9s+JELwTMXT/rMefQn2XiP4l8hr8IuMcbcS Q/lp2sjmpzqp67WtvjpBguJznES/L1XFI9VkFoXRveweutc87hAyKM+y5 Ae4cickn1qwdJFrqzwOc3QSHg8f3JKznrHhXYF4F1uiWqBXUIo1INb599 j204jBVhg34muEW6HFN4qlgGSjA2XW/q1nABRbu10siCBlbALIkfYPWUU N3Al6i4IdOHEe+5k+mAeBl3N2tu+b5U3d/xrCB3K8zBecFrWFCXJobR87 Q==; X-CSE-ConnectionGUID: +FEOgKuGR6CK9KCPmlMymA== X-CSE-MsgGUID: vnyIaqHrTaG6d8mOYAA5Sg== X-IronPort-AV: E=McAfee;i="6800,10657,11813"; a="99456617" X-IronPort-AV: E=Sophos;i="6.24,199,1774335600"; d="scan'208";a="99456617" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by orvoesa102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jun 2026 13:35:46 -0700 X-CSE-ConnectionGUID: ocijLvAbRAahK0j1PpRIkA== X-CSE-MsgGUID: msQIaXvFSYmGwQ2JDyOchg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.24,199,1774335600"; d="scan'208";a="270631217" Received: from black.igk.intel.com ([10.91.253.5]) by fmviesa001.fm.intel.com with ESMTP; 11 Jun 2026 13:35:43 -0700 Received: by black.igk.intel.com (Postfix, from userid 1003) id C801698; Thu, 11 Jun 2026 22:35:42 +0200 (CEST) From: Andy Shevchenko To: Andy Shevchenko , Xu Yang , linux-acpi@vger.kernel.org, driver-core@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Daniel Scally , Heikki Krogerus , Sakari Ailus , Greg Kroah-Hartman , "Rafael J. Wysocki" , Danilo Krummrich , stable@vger.kernel.org Subject: [PATCH v4 1/3] device property: fix infinite loop in fwnode_for_each_child_node() Date: Thu, 11 Jun 2026 22:31:06 +0200 Message-ID: <20260611203537.1786399-2-andriy.shevchenko@linux.intel.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260611203537.1786399-1-andriy.shevchenko@linux.intel.com> References: <20260611203537.1786399-1-andriy.shevchenko@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Xu Yang When iterate over children of a fwnode that has a secondary fwnode, fwnode_get_next_child_node() can enter an infinite loop if the secondary fwnode has more than one child. Parent Child (Primary fwnode) FWa: {FWa1, FWa2, FWa3} (Secondary fwnode) FWb: {FWb1, FWb2} In this case: ┌─> fwnode_get_next_child_node(FWa, FWa1) │ - fwnode_call_ptr_op(FWa, get_next_child_node, FWa1) returns FWa2 │ │ ... │ │ fwnode_get_next_child_node(FWa, FWa3) │ - fwnode_call_ptr_op(FWa, get_next_child_node, FWa3) returns NULL │ - fwnode_call_ptr_op(FWb, get_next_child_node, FWa3) returns FWb1 │ │ fwnode_get_next_child_node(FWa, FWb1) │ - fwnode_call_ptr_op(FWa, get_next_child_node, FWb1) returns FWa1 └────┘ This cause fwnode_for_each_child_node() to loop indefinitely, reapeatedly output {FWa1, FWa2, FWa3, FWb1, FWa1, ...}. The root cause is that when the current child (FWb1) belongs to the secondary fwnode, calling get_next_child_node() on the parimary fwnode incorrectly returns the first child (FWa1) again instead of NULL. Fix this by dynamically checking the parent fwnode of the current child before calling get_next_child_node(). This approach follows the pattern established in commit b5b41ab6b0c1 ("device property: Check fwnode->secondary in fwnode_graph_get_next_endpoint()"). Fixes: 2692c614f8f0 ("device property: Allow secondary lookup in fwnode_get_next_child_node()") Cc: stable@vger.kernel.org Signed-off-by: Xu Yang Tested-by: Andy Shevchenko Signed-off-by: Andy Shevchenko --- drivers/base/property.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/base/property.c b/drivers/base/property.c index 8e0148a37fff..f7b30d9c8716 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -807,18 +807,31 @@ struct fwnode_handle * fwnode_get_next_child_node(const struct fwnode_handle *fwnode, struct fwnode_handle *child) { + const struct fwnode_handle *parent; + struct fwnode_handle *child_parent __free(fwnode_handle) = NULL; struct fwnode_handle *next; - if (IS_ERR_OR_NULL(fwnode)) + /* + * If this function is in a loop and the previous iteration returned + * an child from fwnode->secondary, then we need to use the secondary + * as parent rather than @fwnode. + */ + if (child) { + child_parent = fwnode_get_parent(child); + parent = child_parent; + } else { + parent = fwnode; + } + if (IS_ERR_OR_NULL(parent)) return NULL; /* Try to find a child in primary fwnode */ - next = fwnode_call_ptr_op(fwnode, get_next_child_node, child); + next = fwnode_call_ptr_op(parent, get_next_child_node, child); if (next) return next; /* When no more children in primary, continue with secondary */ - return fwnode_call_ptr_op(fwnode->secondary, get_next_child_node, child); + return fwnode_get_next_child_node(parent->secondary, NULL); } EXPORT_SYMBOL_GPL(fwnode_get_next_child_node); -- 2.50.1