Message ID | 20240217150228.5788-5-johan+linaro@kernel.org |
---|---|
State | Handled Elsewhere |
Headers | show |
Series | soc: qcom: pmic_glink_altmode: fix drm bridge use-after-free | expand |
On Sat, Feb 17, 2024 at 04:02:26PM +0100, Johan Hovold wrote: > From: Rob Clark <robdclark@chromium.org> > > We need to bail out before adding/removing devices if we are going to > -EPROBE_DEFER. Otherwise boot can get stuck in a probe deferral loop due > to a long-standing issue in driver core (see fbc35b45f9f6 ("Add > documentation on meaning of -EPROBE_DEFER")). > > Deregistering the altmode child device can potentially also trigger bugs > in the DRM bridge implementation, which does not expect bridges to go > away. > > Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> > Signed-off-by: Rob Clark <robdclark@chromium.org> > Link: https://lore.kernel.org/r/20231213210644.8702-1-robdclark@gmail.com > [ johan: rebase on 6.8-rc4, amend commit message and mention DRM ] > Fixes: 58ef4ece1e41 ("soc: qcom: pmic_glink: Introduce base PMIC GLINK driver") > Cc: stable@vger.kernel.org # 6.3 > Cc: Bjorn Andersson <andersson@kernel.org> > Signed-off-by: Johan Hovold <johan+linaro@kernel.org> Reviewed-by: Bjorn Andersson <andersson@kernel.org> Regards, Bjorn > --- > drivers/soc/qcom/pmic_glink.c | 21 +++++++++++---------- > 1 file changed, 11 insertions(+), 10 deletions(-) > > diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c > index f4bfd24386f1..f913e9bd57ed 100644 > --- a/drivers/soc/qcom/pmic_glink.c > +++ b/drivers/soc/qcom/pmic_glink.c > @@ -265,10 +265,17 @@ static int pmic_glink_probe(struct platform_device *pdev) > > pg->client_mask = *match_data; > > + pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg); > + if (IS_ERR(pg->pdr)) { > + ret = dev_err_probe(&pdev->dev, PTR_ERR(pg->pdr), > + "failed to initialize pdr\n"); > + return ret; > + } > + > if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) { > ret = pmic_glink_add_aux_device(pg, &pg->ucsi_aux, "ucsi"); > if (ret) > - return ret; > + goto out_release_pdr_handle; > } > if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) { > ret = pmic_glink_add_aux_device(pg, &pg->altmode_aux, "altmode"); > @@ -281,17 +288,11 @@ static int pmic_glink_probe(struct platform_device *pdev) > goto out_release_altmode_aux; > } > > - pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg); > - if (IS_ERR(pg->pdr)) { > - ret = dev_err_probe(&pdev->dev, PTR_ERR(pg->pdr), "failed to initialize pdr\n"); > - goto out_release_aux_devices; > - } > - > service = pdr_add_lookup(pg->pdr, "tms/servreg", "msm/adsp/charger_pd"); > if (IS_ERR(service)) { > ret = dev_err_probe(&pdev->dev, PTR_ERR(service), > "failed adding pdr lookup for charger_pd\n"); > - goto out_release_pdr_handle; > + goto out_release_aux_devices; > } > > mutex_lock(&__pmic_glink_lock); > @@ -300,8 +301,6 @@ static int pmic_glink_probe(struct platform_device *pdev) > > return 0; > > -out_release_pdr_handle: > - pdr_handle_release(pg->pdr); > out_release_aux_devices: > if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) > pmic_glink_del_aux_device(pg, &pg->ps_aux); > @@ -311,6 +310,8 @@ static int pmic_glink_probe(struct platform_device *pdev) > out_release_ucsi_aux: > if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) > pmic_glink_del_aux_device(pg, &pg->ucsi_aux); > +out_release_pdr_handle: > + pdr_handle_release(pg->pdr); > > return ret; > } > -- > 2.43.0 >
On Sat, 17 Feb 2024 at 17:03, Johan Hovold <johan+linaro@kernel.org> wrote: > > From: Rob Clark <robdclark@chromium.org> > > We need to bail out before adding/removing devices if we are going to > -EPROBE_DEFER. Otherwise boot can get stuck in a probe deferral loop due > to a long-standing issue in driver core (see fbc35b45f9f6 ("Add > documentation on meaning of -EPROBE_DEFER")). > > Deregistering the altmode child device can potentially also trigger bugs > in the DRM bridge implementation, which does not expect bridges to go > away. > > Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> > Signed-off-by: Rob Clark <robdclark@chromium.org> > Link: https://lore.kernel.org/r/20231213210644.8702-1-robdclark@gmail.com > [ johan: rebase on 6.8-rc4, amend commit message and mention DRM ] > Fixes: 58ef4ece1e41 ("soc: qcom: pmic_glink: Introduce base PMIC GLINK driver") > Cc: stable@vger.kernel.org # 6.3 > Cc: Bjorn Andersson <andersson@kernel.org> > Signed-off-by: Johan Hovold <johan+linaro@kernel.org> > --- > drivers/soc/qcom/pmic_glink.c | 21 +++++++++++---------- > 1 file changed, 11 insertions(+), 10 deletions(-) > Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
On 17/02/2024 16:02, Johan Hovold wrote: > From: Rob Clark <robdclark@chromium.org> > > We need to bail out before adding/removing devices if we are going to > -EPROBE_DEFER. Otherwise boot can get stuck in a probe deferral loop due > to a long-standing issue in driver core (see fbc35b45f9f6 ("Add > documentation on meaning of -EPROBE_DEFER")). > > Deregistering the altmode child device can potentially also trigger bugs > in the DRM bridge implementation, which does not expect bridges to go > away. > > Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> > Signed-off-by: Rob Clark <robdclark@chromium.org> > Link: https://lore.kernel.org/r/20231213210644.8702-1-robdclark@gmail.com > [ johan: rebase on 6.8-rc4, amend commit message and mention DRM ] > Fixes: 58ef4ece1e41 ("soc: qcom: pmic_glink: Introduce base PMIC GLINK driver") > Cc: stable@vger.kernel.org # 6.3 > Cc: Bjorn Andersson <andersson@kernel.org> > Signed-off-by: Johan Hovold <johan+linaro@kernel.org> > --- > drivers/soc/qcom/pmic_glink.c | 21 +++++++++++---------- > 1 file changed, 11 insertions(+), 10 deletions(-) > > diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c > index f4bfd24386f1..f913e9bd57ed 100644 > --- a/drivers/soc/qcom/pmic_glink.c > +++ b/drivers/soc/qcom/pmic_glink.c > @@ -265,10 +265,17 @@ static int pmic_glink_probe(struct platform_device *pdev) > > pg->client_mask = *match_data; > > + pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg); > + if (IS_ERR(pg->pdr)) { > + ret = dev_err_probe(&pdev->dev, PTR_ERR(pg->pdr), > + "failed to initialize pdr\n"); > + return ret; > + } > + > if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) { > ret = pmic_glink_add_aux_device(pg, &pg->ucsi_aux, "ucsi"); > if (ret) > - return ret; > + goto out_release_pdr_handle; > } > if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) { > ret = pmic_glink_add_aux_device(pg, &pg->altmode_aux, "altmode"); > @@ -281,17 +288,11 @@ static int pmic_glink_probe(struct platform_device *pdev) > goto out_release_altmode_aux; > } > > - pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg); > - if (IS_ERR(pg->pdr)) { > - ret = dev_err_probe(&pdev->dev, PTR_ERR(pg->pdr), "failed to initialize pdr\n"); > - goto out_release_aux_devices; > - } > - > service = pdr_add_lookup(pg->pdr, "tms/servreg", "msm/adsp/charger_pd"); > if (IS_ERR(service)) { > ret = dev_err_probe(&pdev->dev, PTR_ERR(service), > "failed adding pdr lookup for charger_pd\n"); > - goto out_release_pdr_handle; > + goto out_release_aux_devices; > } > > mutex_lock(&__pmic_glink_lock); > @@ -300,8 +301,6 @@ static int pmic_glink_probe(struct platform_device *pdev) > > return 0; > > -out_release_pdr_handle: > - pdr_handle_release(pg->pdr); > out_release_aux_devices: > if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) > pmic_glink_del_aux_device(pg, &pg->ps_aux); > @@ -311,6 +310,8 @@ static int pmic_glink_probe(struct platform_device *pdev) > out_release_ucsi_aux: > if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) > pmic_glink_del_aux_device(pg, &pg->ucsi_aux); > +out_release_pdr_handle: > + pdr_handle_release(pg->pdr); > > return ret; > } Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index f4bfd24386f1..f913e9bd57ed 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -265,10 +265,17 @@ static int pmic_glink_probe(struct platform_device *pdev) pg->client_mask = *match_data; + pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg); + if (IS_ERR(pg->pdr)) { + ret = dev_err_probe(&pdev->dev, PTR_ERR(pg->pdr), + "failed to initialize pdr\n"); + return ret; + } + if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) { ret = pmic_glink_add_aux_device(pg, &pg->ucsi_aux, "ucsi"); if (ret) - return ret; + goto out_release_pdr_handle; } if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) { ret = pmic_glink_add_aux_device(pg, &pg->altmode_aux, "altmode"); @@ -281,17 +288,11 @@ static int pmic_glink_probe(struct platform_device *pdev) goto out_release_altmode_aux; } - pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg); - if (IS_ERR(pg->pdr)) { - ret = dev_err_probe(&pdev->dev, PTR_ERR(pg->pdr), "failed to initialize pdr\n"); - goto out_release_aux_devices; - } - service = pdr_add_lookup(pg->pdr, "tms/servreg", "msm/adsp/charger_pd"); if (IS_ERR(service)) { ret = dev_err_probe(&pdev->dev, PTR_ERR(service), "failed adding pdr lookup for charger_pd\n"); - goto out_release_pdr_handle; + goto out_release_aux_devices; } mutex_lock(&__pmic_glink_lock); @@ -300,8 +301,6 @@ static int pmic_glink_probe(struct platform_device *pdev) return 0; -out_release_pdr_handle: - pdr_handle_release(pg->pdr); out_release_aux_devices: if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) pmic_glink_del_aux_device(pg, &pg->ps_aux); @@ -311,6 +310,8 @@ static int pmic_glink_probe(struct platform_device *pdev) out_release_ucsi_aux: if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) pmic_glink_del_aux_device(pg, &pg->ucsi_aux); +out_release_pdr_handle: + pdr_handle_release(pg->pdr); return ret; }