On 12/14/2018 11:20 AM, Rob Herring wrote: > On Fri, Dec 14, 2018 at 12:43 AM <frowand.list@xxxxxxxxx> wrote: >> >> From: Frank Rowand <frank.rowand@xxxxxxxx> >> >> Non-overlay dynamic devicetree node removal may leave the node in >> the phandle cache. Subsequent calls to of_find_node_by_phandle() >> will incorrectly find the stale entry. Remove the node from the >> cache. >> >> Add paranoia checks in of_find_node_by_phandle() as a second level >> of defense (do not return cached node if detached, do not add node >> to cache if detached). >> >> Reported-by: Michael Bringmann <mwb@xxxxxxxxxxxxxxxxxx> >> Signed-off-by: Frank Rowand <frank.rowand@xxxxxxxx> >> --- >> drivers/of/base.c | 29 ++++++++++++++++++++++++++++- >> drivers/of/dynamic.c | 3 +++ >> drivers/of/of_private.h | 4 ++++ >> 3 files changed, 35 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/of/base.c b/drivers/of/base.c >> index d599367cb92a..34a5125713c8 100644 >> --- a/drivers/of/base.c >> +++ b/drivers/of/base.c >> @@ -162,6 +162,27 @@ int of_free_phandle_cache(void) >> late_initcall_sync(of_free_phandle_cache); >> #endif >> >> +/* >> + * Caller must hold devtree_lock. >> + */ >> +void __of_free_phandle_cache_entry(phandle handle) >> +{ >> + phandle masked_handle; >> + >> + if (!handle) >> + return; >> + >> + masked_handle = handle & phandle_cache_mask; >> + >> + if (phandle_cache) { >> + if (phandle_cache[masked_handle] && >> + handle == phandle_cache[masked_handle]->phandle) { >> + of_node_put(phandle_cache[masked_handle]); >> + phandle_cache[masked_handle] = NULL; >> + } >> + } >> +} >> + >> void of_populate_phandle_cache(void) >> { >> unsigned long flags; >> @@ -1209,11 +1230,17 @@ struct device_node *of_find_node_by_phandle(phandle handle) >> if (phandle_cache[masked_handle] && >> handle == phandle_cache[masked_handle]->phandle) >> np = phandle_cache[masked_handle]; >> + if (np && of_node_check_flag(np, OF_DETACHED)) { >> + of_node_put(np); >> + phandle_cache[masked_handle] = NULL; > > This should never happen, right? Any time we set OF_DETACHED, the > entry should get removed from the cache. I think we want a WARN here > in case we're in an unexpected state. We don't actually remove the pointer from the phandle cache when we set OF_DETACHED in drivers/of/dynamic.c:__of_detach_node. The phandle cache is currently static within drivers/of/base.c. There are a couple of calls to of_populate_phandle_cache / of_free_phandle_cache within drivers/of/overlay.c, but these are not involved in the device tree updates that occur during LPAR migration. A WARN here would only make sense, if we also arrange to clear the handle. > > Rob Michael > > -- Michael W. Bringmann Linux I/O, Networking and Security Development IBM Corporation Tie-Line 363-5196 External: (512) 286-5196 Cell: (512) 466-0650 mwb@xxxxxxxxxxxxxxxxxx