Re: [PATCH] drm/ingenic: fix bridge allocation
"H. Nikolaus Schaller" <[email protected]>
| Newsgroups | org.freedesktop.lists.dri-devel,dev.linux.lists.sashiko-reviews |
|---|---|
| Message-ID | <[email protected]> |
(Response created with ChatGPT analyzing patch, drm subsystem, memory management and Sahsiko comments) > Am 23.08.2026 um 11:45 schrieb [email protected]: > > Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: > > New issues: > - [High] The patch introduces a lifecycle mismatch and memory leak by using `devm_` allocations for a DRM bridge inside a component bind function, while attaching it to a `drmm_`-managed encoder. > - [High] Falsely claiming DRM_BRIDGE_OP_EDID and DRM_BRIDGE_OP_DETECT capabilities on a bridge that lacks the corresponding callback implementations causes a NULL pointer dereference. > > Pre-existing issues: > - [High] Unhandled error pointer from devm_drm_panel_bridge_add_typed() leads to invalid memory dereference. > - [High] atomic_check phase corrupts global driver state by directly modifying ib->bus_cfg. > -- > > --- Patch [1]: [PATCH] drm/ingenic: fix bridge allocation --- > commit caf3be8c5a53047a7d5ddaf2c5ee3db764a2f7fb > Author: H. Nikolaus Schaller <[email protected]> > > drm/ingenic: fix bridge allocation > > Bridge allocation API has changed and ingenic/drm was broken leading to > a warning. This patch replaces the embedded drm_bridge structure with a > pointer and uses devm_drm_bridge_alloc() to resolve the issue. Thanks for the review. - The devm_drm_bridge_alloc() lifecycle concern appears not to apply here. The DRM bridge is refcounted, and drm_bridge_attach() takes a reference, so the bridge is not simply freed when the device-managed reference is released. The existing Ingenic component unbind path also unregisters and shuts down the DRM device, allowing the bridge/encoder chain to be cleaned up in the normal DRM lifecycle. - I agree with the DRM_BRIDGE_OP_EDID / DRM_BRIDGE_OP_DETECT finding; these flags are not backed by callbacks in ingenic_drm_bridge_funcs and will be removed in v2. - The devm_drm_panel_bridge_add_typed() error handling and the ib->bus_cfg modification in atomic_check() are pre-existing issues and are unrelated to this patch. BR, Nikolaus > > > >> diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c >> index 738a80b2550ff..91fe0ee7ae9ad 100644 >> --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c >> +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c >> @@ -802,7 +802,7 @@ static int ingenic_drm_bridge_attach(struct drm_bridge *bridge, >> struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(encoder); >> >> return drm_bridge_attach(encoder, ib->next_bridge, >> - &ib->bridge, flags); >> + bridge, flags); >> } >> >> static int ingenic_drm_bridge_atomic_check(struct drm_bridge *bridge, >> struct drm_bridge_state *bridge_state, >> struct drm_crtc_state *crtc_state, >> struct drm_connector_state *conn_state) >> { >> struct drm_display_mode *mode = &crtc_state->adjusted_mode; >> struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder); >> >> ib->bus_cfg = bridge_state->output_bus_cfg; > > [Severity: High] > This is a pre-existing issue, but does modifying ib->bus_cfg here break > the atomic contract? > > Since DRM atomic_check can be called for TEST_ONLY commits that are meant > to be discarded, directly overwriting the global driver state here corrupts > the display configuration if a real commit later relies on this modified > state. > > [ ... ] > >> @@ -1316,10 +1316,26 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) >> >> drm_encoder_helper_add(encoder, &ingenic_drm_encoder_helper_funcs); >> > > [Severity: High] > This is a pre-existing issue, but earlier in this same ingenic_drm_bind() > function, what happens if the panel bridge allocation fails? > > if (panel) { > bridge = devm_drm_panel_bridge_add_typed(dev, panel, > DRM_MODE_CONNECTOR_DPI); > drm_panel_put(panel); > } > > If devm_drm_panel_bridge_add_typed() fails, it returns an ERR_PTR(). This > unvalidated error pointer is saved into bridge, and eventually passed into > drm_bridge_attach() as ib->next_bridge, where it will be dereferenced and > panic the kernel. Should we check this with IS_ERR() here? > >> - ib->bridge.funcs = &ingenic_drm_bridge_funcs; >> + ib->bridge = devm_drm_bridge_alloc(priv->dev, struct drm_bridge, >> + base, &ingenic_drm_bridge_funcs); >> + if (IS_ERR(ib->bridge)) { >> + ret = PTR_ERR(ib->bridge); >> + goto err_drvdata; >> + } >> + >> + ib->bridge->of_node = priv->dev->of_node; >> ib->next_bridge = bridge; >> >> - ret = drm_bridge_attach(encoder, &ib->bridge, NULL, >> + ib->bridge->ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT; > > [Severity: High] > Does this bridge actually implement these operations? > > Setting DRM_BRIDGE_OP_EDID and DRM_BRIDGE_OP_DETECT advertises these > capabilities to the DRM core. However, the ingenic_drm_bridge_funcs > structure lacks the corresponding .detect, .edid_read, or .get_edid > callbacks. > > When the core initializes the bridge connector and queries its state, > it will unconditionally call these missing functions, leading to a NULL > pointer dereference. > >> + ib->bridge->interlace_allowed = true; >> + >> + ret = devm_drm_bridge_add(priv->dev, ib->bridge); >> + if (ret) { >> + dev_err(dev, "Failed to register DRM bridge: %d\n", ret); >> + goto err_drvdata; >> + } >> + >> + ret = drm_bridge_attach(encoder, ib->bridge, NULL, >> DRM_BRIDGE_ATTACH_NO_CONNECTOR); > > [Severity: High] > Can these devm_ allocations cause a use-after-free or a memory leak on > unbind? > > Using devm_drm_bridge_alloc() and devm_drm_bridge_add() inside a component > bind function ties the bridge's lifecycle to device removal, not component > unbind. This means each bind/unbind cycle leaks memory and leaves stale > bridges in the global DRM list. > > Additionally, the parent encoder is allocated via drmm_encoder_alloc(), > tying its lifecycle to the DRM device, which can outlive the platform > device if userspace holds an open file descriptor. When the platform > device is removed, devres frees the bridge early, creating a UAF hazard > when the DRM device later attempts to clean up its encoder bridge chains. > >> if (ret) { >> dev_err(dev, "Unable to attach bridge\n"); > > -- > Sashiko AI review · https://sashiko.dev/#/patchset/400ba2fe0d4f76484e929d2efaa32f67a940163a.1787477392.git.hns@goldelico.com?part=1