Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp647670imu; Fri, 11 Jan 2019 06:46:04 -0800 (PST) X-Google-Smtp-Source: ALg8bN5DXzO6djG8/n74ixGVWjeAGUa+3kzuXvDcwbg4ZYkpe21nwSxpEBRGIx9162E3CxV4HD6K X-Received: by 2002:a62:1a91:: with SMTP id a139mr15332269pfa.64.1547217964376; Fri, 11 Jan 2019 06:46:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1547217964; cv=none; d=google.com; s=arc-20160816; b=B9BnrR6CTnK4PNqNyv++9Lqd7HVBCHIOgGMUbLFolyuYn/JpGcCUdi+SsUCwbACE3p /Hjzzhc28Yi+nHftWWopIhulUiXcXuq/meTtWhBDqhm2hcTSi7ivbQoZ/55tEFiOOs1R Qhobtkzccitrb8g2YWLZjNddn1Zm5XBAsQINz+ZxeY06mvn7GuidEIY6IUm8Tbystwax uNtUgLijmdV9Qze3Nx06CsKX8lMaQ02yZAUDoZVAXqsPmEt3cS7KVBBv5Z98/3ltqnlj OX1kg52aRjISfG2EVjLWfImxmQ3dfgR+bkmQBuZ/ERc8PtzQBMsl5n3P9MZDkIXMEIIA NojQ== 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=CmQzZBzY7Jv8X0M+Rut3eObUS4azsYfkb6t8Ro8Id7M=; b=SnXCjP+RwXNjQegzk1gJd7P/P4VT8XF1ZeVraz7F0hCx/vM1qzgys5NYc0jg2Ec8Ch bAJCM3V7V4+uUoSdnwrLm2Xd2FuUdLJNt2ZKnGyBGqwCSuf8RJ6vc/vqVw4uoX2Y1oBR SHOj/cvcwg9xHIESY/04SS3hM5ItXKKHtYQAXZWOxjoLLxNG/hke7GopymzIjqoK+LSm 0+0F9gCtO7N6EY+APiIvjXEzp8Gfq/nmjifkV93dOdHpfUbSgaFs0Y1tG6tIVAXvAAJu VNPG0rIq0TFfxgUQ2/67BjbRWmi5dL+5IRuz7mCGF9kWExjnnhtmxF4xO5fA/2yi4e0v 12Tw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=cYLyu877; 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 u131si6368472pgb.594.2019.01.11.06.45.49; Fri, 11 Jan 2019 06:46:04 -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=cYLyu877; 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 S2404531AbfAKOoD (ORCPT + 99 others); Fri, 11 Jan 2019 09:44:03 -0500 Received: from mail.kernel.org ([198.145.29.99]:36948 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404511AbfAKOoB (ORCPT ); Fri, 11 Jan 2019 09:44:01 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.ziggo.nl [83.86.89.107]) (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 504BD20872; Fri, 11 Jan 2019 14:43:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1547217839; bh=U3SdtHn4S4IVWJICZtxCRm9CZH42ikI5CmkgtN3P4Ts=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cYLyu877SPUzOki7l39X+Hm2Q3vfc4wo+uNnSXT684bdsMzuOW9pYxDlzbi4nyNKO 1Y+LrOW1AKmzvGeu2HTYL3PYKWVr8tvdM0h4t6yybdu1dapw1/KIk8IbD6C94gJ9BW BzXRolnDhgqHGgFLm/Oy3sie0RKzGkpSvKrH7YyI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Frank Rowand , Rob Herring Subject: [PATCH 4.20 60/65] of: of_node_get()/of_node_put() nodes held in phandle cache Date: Fri, 11 Jan 2019 15:15:46 +0100 Message-Id: <20190111131104.084979597@linuxfoundation.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190111131055.331350141@linuxfoundation.org> References: <20190111131055.331350141@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review X-Patchwork-Hint: ignore 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 4.20-stable review patch. If anyone has any objections, please let me know. ------------------ From: Frank Rowand commit b8a9ac1a5b99a2fcbed19fd29d2d59270c281a31 upstream. The phandle cache contains struct device_node pointers. The refcount of the pointers was not incremented while in the cache, allowing use after free error after kfree() of the node. Add the proper increment and decrement of the use count. Fixes: 0b3ce78e90fc ("of: cache phandle nodes to reduce cost of of_find_node_by_phandle()") Cc: stable@vger.kernel.org # v4.17+ Signed-off-by: Frank Rowand Signed-off-by: Rob Herring Signed-off-by: Greg Kroah-Hartman --- drivers/of/base.c | 70 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 24 deletions(-) --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -116,9 +116,6 @@ int __weak of_node_to_nid(struct device_ } #endif -static struct device_node **phandle_cache; -static u32 phandle_cache_mask; - /* * Assumptions behind phandle_cache implementation: * - phandle property values are in a contiguous range of 1..n @@ -127,6 +124,44 @@ static u32 phandle_cache_mask; * - the phandle lookup overhead reduction provided by the cache * will likely be less */ + +static struct device_node **phandle_cache; +static u32 phandle_cache_mask; + +/* + * Caller must hold devtree_lock. + */ +static void __of_free_phandle_cache(void) +{ + u32 cache_entries = phandle_cache_mask + 1; + u32 k; + + if (!phandle_cache) + return; + + for (k = 0; k < cache_entries; k++) + of_node_put(phandle_cache[k]); + + kfree(phandle_cache); + phandle_cache = NULL; +} + +int of_free_phandle_cache(void) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&devtree_lock, flags); + + __of_free_phandle_cache(); + + raw_spin_unlock_irqrestore(&devtree_lock, flags); + + return 0; +} +#if !defined(CONFIG_MODULES) +late_initcall_sync(of_free_phandle_cache); +#endif + void of_populate_phandle_cache(void) { unsigned long flags; @@ -136,8 +171,7 @@ void of_populate_phandle_cache(void) raw_spin_lock_irqsave(&devtree_lock, flags); - kfree(phandle_cache); - phandle_cache = NULL; + __of_free_phandle_cache(); for_each_of_allnodes(np) if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL) @@ -155,30 +189,15 @@ void of_populate_phandle_cache(void) goto out; for_each_of_allnodes(np) - if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL) + if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL) { + of_node_get(np); phandle_cache[np->phandle & phandle_cache_mask] = np; + } out: raw_spin_unlock_irqrestore(&devtree_lock, flags); } -int of_free_phandle_cache(void) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&devtree_lock, flags); - - kfree(phandle_cache); - phandle_cache = NULL; - - raw_spin_unlock_irqrestore(&devtree_lock, flags); - - return 0; -} -#if !defined(CONFIG_MODULES) -late_initcall_sync(of_free_phandle_cache); -#endif - void __init of_core_init(void) { struct device_node *np; @@ -1195,8 +1214,11 @@ struct device_node *of_find_node_by_phan if (!np) { for_each_of_allnodes(np) if (np->phandle == handle) { - if (phandle_cache) + if (phandle_cache) { + /* will put when removed from cache */ + of_node_get(np); phandle_cache[masked_handle] = np; + } break; } }