pse_controller_unregister() frees the PI array while the controller is still on pse_controller_list, and only removes it from the list afterwards. of_pse_control_get() walks that list under pse_list_mutex and reads pcdev->pi[i].np in of_pse_match_pi(). A consumer that probes at that moment can read the freed PI array. Remove the controller from the list first, before the worker is drained, the power domains are flushed and the PI array is freed. Both sides take pse_list_mutex, so once the controller is off the list, no new lookup can find it, and a lookup that is already running finishes before the PI array is freed. Found by code inspection. Not reproduced. Fixes: 9be9567a7c59 ("net: pse-pd: Add support for PSE PIs") Reviewed-by: Kory Maincent Acked-by: Oleksij Rempel Signed-off-by: Carlo Szelinsky --- drivers/net/pse-pd/pse_core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/pse-pd/pse_core.c b/drivers/net/pse-pd/pse_core.c index 2dce1f1c4d16..a7dfa7cdbe3a 100644 --- a/drivers/net/pse-pd/pse_core.c +++ b/drivers/net/pse-pd/pse_core.c @@ -1184,13 +1184,16 @@ void pse_controller_unregister(struct pse_controller_dev *pcdev) */ if (pcdev->irq) disable_irq(pcdev->irq); + /* Unlink before the PI array is freed: of_pse_control_get() walks + * the list and reads pcdev->pi[]. + */ + mutex_lock(&pse_list_mutex); + list_del(&pcdev->list); + mutex_unlock(&pse_list_mutex); cancel_work_sync(&pcdev->ntf_work); pse_flush_pw_ds(pcdev); pse_release_pis(pcdev); kfifo_free(&pcdev->ntf_fifo); - mutex_lock(&pse_list_mutex); - list_del(&pcdev->list); - mutex_unlock(&pse_list_mutex); } EXPORT_SYMBOL_GPL(pse_controller_unregister); -- 2.43.0