Message ID | 20241213081550.3388074-1-joe@pf.is.s.u-tokyo.ac.jp (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/bridge: display-connector: implement the error path of .probe() | expand |
Hi Joe, Thank you for the patch. On Fri, Dec 13, 2024 at 05:15:50PM +0900, Joe Hattori wrote: > Current implementation of .probe() leaks a reference of i2c_adapter. > Implement an error path and call put_device() on the obtained > i2c_adapter in it to fix this refcount bug. > > This bug was found by an experimental static analysis tool that I am > developing. > > Fixes: 0c275c30176b ("drm/bridge: Add bridge driver for display connectors") > Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp> > --- > drivers/gpu/drm/bridge/display-connector.c | 25 ++++++++++++++++------ > 1 file changed, 19 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c > index 72bc508d4e6e..84f1c3798d32 100644 > --- a/drivers/gpu/drm/bridge/display-connector.c > +++ b/drivers/gpu/drm/bridge/display-connector.c > @@ -332,8 +332,11 @@ static int display_connector_probe(struct platform_device *pdev) > int ret; > > ret = display_connector_get_supply(pdev, conn, "dp-pwr"); > - if (ret < 0) > - return dev_err_probe(&pdev->dev, ret, "failed to get DP PWR regulator\n"); > + if (ret < 0) { > + ret = dev_err_probe(&pdev->dev, ret, > + "failed to get DP PWR regulator\n"); > + goto err_put; > + } > } > > /* enable DDC */ > @@ -345,19 +348,24 @@ static int display_connector_probe(struct platform_device *pdev) > > if (IS_ERR(conn->ddc_en)) { > dev_err(&pdev->dev, "Couldn't get ddc-en gpio\n"); > - return PTR_ERR(conn->ddc_en); > + ret = PTR_ERR(conn->ddc_en); > + goto err_put; > } > > ret = display_connector_get_supply(pdev, conn, "hdmi-pwr"); > - if (ret < 0) > - return dev_err_probe(&pdev->dev, ret, "failed to get HDMI +5V Power regulator\n"); > + if (ret < 0) { > + ret = dev_err_probe( > + &pdev->dev, ret, > + "failed to get HDMI +5V Power regulator\n"); ret = dev_err_probe(&pdev->dev, ret, "failed to get HDMI +5V Power regulator\n"); > + goto err_put; > + } > } > > if (conn->supply) { > ret = regulator_enable(conn->supply); > if (ret) { > dev_err(&pdev->dev, "failed to enable PWR regulator: %d\n", ret); > - return ret; > + goto err_put; > } > } > > @@ -383,6 +391,11 @@ static int display_connector_probe(struct platform_device *pdev) > drm_bridge_add(&conn->bridge); > > return 0; > + > +err_put: > + if (conn->bridge.ddc) i2c_put_adapter() already has a NULL check. > + i2c_put_adapter(conn->bridge.ddc); > + return ret; > } > > static void display_connector_remove(struct platform_device *pdev)
Hi Laurent, Thank you for your review. On Fri, Dec 13, 2024 at 6:33 PM Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote: > > Hi Joe, > > Thank you for the patch. > > On Fri, Dec 13, 2024 at 05:15:50PM +0900, Joe Hattori wrote: > > Current implementation of .probe() leaks a reference of i2c_adapter. > > Implement an error path and call put_device() on the obtained > > i2c_adapter in it to fix this refcount bug. > > > > This bug was found by an experimental static analysis tool that I am > > developing. > > > > Fixes: 0c275c30176b ("drm/bridge: Add bridge driver for display connectors") > > Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp> > > --- > > drivers/gpu/drm/bridge/display-connector.c | 25 ++++++++++++++++------ > > 1 file changed, 19 insertions(+), 6 deletions(-) > > > > diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c > > index 72bc508d4e6e..84f1c3798d32 100644 > > --- a/drivers/gpu/drm/bridge/display-connector.c > > +++ b/drivers/gpu/drm/bridge/display-connector.c > > @@ -332,8 +332,11 @@ static int display_connector_probe(struct platform_device *pdev) > > int ret; > > > > ret = display_connector_get_supply(pdev, conn, "dp-pwr"); > > - if (ret < 0) > > - return dev_err_probe(&pdev->dev, ret, "failed to get DP PWR regulator\n"); > > + if (ret < 0) { > > + ret = dev_err_probe(&pdev->dev, ret, > > + "failed to get DP PWR regulator\n"); > > + goto err_put; > > + } > > } > > > > /* enable DDC */ > > @@ -345,19 +348,24 @@ static int display_connector_probe(struct platform_device *pdev) > > > > if (IS_ERR(conn->ddc_en)) { > > dev_err(&pdev->dev, "Couldn't get ddc-en gpio\n"); > > - return PTR_ERR(conn->ddc_en); > > + ret = PTR_ERR(conn->ddc_en); > > + goto err_put; > > } > > > > ret = display_connector_get_supply(pdev, conn, "hdmi-pwr"); > > - if (ret < 0) > > - return dev_err_probe(&pdev->dev, ret, "failed to get HDMI +5V Power regulator\n"); > > + if (ret < 0) { > > + ret = dev_err_probe( > > + &pdev->dev, ret, > > + "failed to get HDMI +5V Power regulator\n"); > > ret = dev_err_probe(&pdev->dev, ret, > "failed to get HDMI +5V Power regulator\n"); > > > + goto err_put; > > + } > > } > > > > if (conn->supply) { > > ret = regulator_enable(conn->supply); > > if (ret) { > > dev_err(&pdev->dev, "failed to enable PWR regulator: %d\n", ret); > > - return ret; > > + goto err_put; > > } > > } > > > > @@ -383,6 +391,11 @@ static int display_connector_probe(struct platform_device *pdev) > > drm_bridge_add(&conn->bridge); > > > > return 0; > > + > > +err_put: > > + if (conn->bridge.ddc) > > i2c_put_adapter() already has a NULL check. Yes, fixed in the v2 patch. > > > + i2c_put_adapter(conn->bridge.ddc); > > + return ret; > > } > > > > static void display_connector_remove(struct platform_device *pdev) > > -- > Regards, > > Laurent Pinchart Best, Joe
diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c index 72bc508d4e6e..84f1c3798d32 100644 --- a/drivers/gpu/drm/bridge/display-connector.c +++ b/drivers/gpu/drm/bridge/display-connector.c @@ -332,8 +332,11 @@ static int display_connector_probe(struct platform_device *pdev) int ret; ret = display_connector_get_supply(pdev, conn, "dp-pwr"); - if (ret < 0) - return dev_err_probe(&pdev->dev, ret, "failed to get DP PWR regulator\n"); + if (ret < 0) { + ret = dev_err_probe(&pdev->dev, ret, + "failed to get DP PWR regulator\n"); + goto err_put; + } } /* enable DDC */ @@ -345,19 +348,24 @@ static int display_connector_probe(struct platform_device *pdev) if (IS_ERR(conn->ddc_en)) { dev_err(&pdev->dev, "Couldn't get ddc-en gpio\n"); - return PTR_ERR(conn->ddc_en); + ret = PTR_ERR(conn->ddc_en); + goto err_put; } ret = display_connector_get_supply(pdev, conn, "hdmi-pwr"); - if (ret < 0) - return dev_err_probe(&pdev->dev, ret, "failed to get HDMI +5V Power regulator\n"); + if (ret < 0) { + ret = dev_err_probe( + &pdev->dev, ret, + "failed to get HDMI +5V Power regulator\n"); + goto err_put; + } } if (conn->supply) { ret = regulator_enable(conn->supply); if (ret) { dev_err(&pdev->dev, "failed to enable PWR regulator: %d\n", ret); - return ret; + goto err_put; } } @@ -383,6 +391,11 @@ static int display_connector_probe(struct platform_device *pdev) drm_bridge_add(&conn->bridge); return 0; + +err_put: + if (conn->bridge.ddc) + i2c_put_adapter(conn->bridge.ddc); + return ret; } static void display_connector_remove(struct platform_device *pdev)
Current implementation of .probe() leaks a reference of i2c_adapter. Implement an error path and call put_device() on the obtained i2c_adapter in it to fix this refcount bug. This bug was found by an experimental static analysis tool that I am developing. Fixes: 0c275c30176b ("drm/bridge: Add bridge driver for display connectors") Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp> --- drivers/gpu/drm/bridge/display-connector.c | 25 ++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-)