* [PATCH] drm/msm: don't tear down KMS twice when KMS init fails
@ 2026-07-23 9:52 Dmitry Baryshkov
2026-07-23 10:04 ` Konrad Dybcio
2026-07-23 10:18 ` sashiko-bot
0 siblings, 2 replies; 3+ messages in thread
From: Dmitry Baryshkov @ 2026-07-23 9:52 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Sean Paul, Marijn Suijten, David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
When priv->kms_init() (mdp4_kms_init() / mdp5_kms_init()) fails partway
through, both display drivers already tear their KMS state down via
mdp4_destroy() / mdp5_kms_destroy() before returning the error. The
common error path in msm_drm_init() then runs msm_drm_uninit() ->
msm_drm_kms_uninit(), which tries to destroy the very same KMS a second
time, which causes a use-after-free crash.
Bring MDP4/MDP5 in line with the DPU driver whose dpu_kms_init() doesn't
perform error cleanup on the failure. Let the common path own the
cleanup, instead of freeing the KMS from their error paths.
The crash trace for the reference:
__lock_acquire from lock_acquire (kernel/locking/lockdep.c:5906 kernel/locking/lockdep.c:5863)
lock_acquire from touch_wq_lockdep_map (kernel/workqueue.c:4094 (discriminator 1))
touch_wq_lockdep_map from __flush_workqueue (kernel/workqueue.c:4136)
__flush_workqueue from msm_drm_kms_uninit (drivers/gpu/drm/msm/msm_kms.c:243 (discriminator 33))
msm_drm_kms_uninit from msm_drm_uninit (drivers/gpu/drm/msm/msm_drv.c:93)
msm_drm_uninit from msm_drm_init (drivers/gpu/drm/msm/msm_drv.c:184)
msm_drm_init from try_to_bring_up_aggregate_device (drivers/base/component.c:249 drivers/base/component.c:227)
try_to_bring_up_aggregate_device from __component_add (drivers/base/component.c:269 drivers/base/component.c:748)
__component_add from dsi_host_attach (drivers/gpu/drm/msm/dsi/dsi_host.c:1739)
dsi_host_attach from mipi_dsi_attach (drivers/gpu/drm/drm_mipi_dsi.c:383)
mipi_dsi_attach from sharp_nt_panel_probe (drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c:247)
Fixes: 506efcba3129 ("drm/msm: carve out KMS code from msm_drv.c")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 22 ++++++++--------------
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 11 +++--------
2 files changed, 11 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
index 7726edb0d4ed..6ae49f94fea7 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
@@ -398,7 +398,7 @@ static int mdp4_kms_init(struct drm_device *dev)
ret = mdp_kms_init(&mdp4_kms->base, &kms_funcs);
if (ret) {
DRM_DEV_ERROR(dev->dev, "failed to init kms\n");
- goto fail;
+ return ret;
}
kms = priv->kms;
@@ -409,7 +409,7 @@ static int mdp4_kms_init(struct drm_device *dev)
ret = regulator_enable(mdp4_kms->vdd);
if (ret) {
DRM_DEV_ERROR(dev->dev, "failed to enable regulator vdd: %d\n", ret);
- goto fail;
+ return ret;
}
}
@@ -421,7 +421,7 @@ static int mdp4_kms_init(struct drm_device *dev)
DRM_DEV_ERROR(dev->dev, "unexpected MDP version: v%d.%d\n",
major, minor);
ret = -ENXIO;
- goto fail;
+ return ret;
}
mdp4_kms->rev = minor;
@@ -430,7 +430,7 @@ static int mdp4_kms_init(struct drm_device *dev)
if (!mdp4_kms->lut_clk) {
DRM_DEV_ERROR(dev->dev, "failed to get lut_clk\n");
ret = -ENODEV;
- goto fail;
+ return ret;
}
clk_set_rate(mdp4_kms->lut_clk, max_clk);
}
@@ -452,7 +452,7 @@ static int mdp4_kms_init(struct drm_device *dev)
vm = msm_kms_init_vm(mdp4_kms->dev, NULL);
if (IS_ERR(vm)) {
ret = PTR_ERR(vm);
- goto fail;
+ return ret;
}
kms->vm = vm;
@@ -460,7 +460,7 @@ static int mdp4_kms_init(struct drm_device *dev)
ret = modeset_init(mdp4_kms);
if (ret) {
DRM_DEV_ERROR(dev->dev, "modeset_init failed: %d\n", ret);
- goto fail;
+ return ret;
}
mdp4_kms->blank_cursor_bo = msm_gem_new(dev, SZ_16K, MSM_BO_WC | MSM_BO_SCANOUT);
@@ -468,14 +468,14 @@ static int mdp4_kms_init(struct drm_device *dev)
ret = PTR_ERR(mdp4_kms->blank_cursor_bo);
DRM_DEV_ERROR(dev->dev, "could not allocate blank-cursor bo: %d\n", ret);
mdp4_kms->blank_cursor_bo = NULL;
- goto fail;
+ return ret;
}
ret = msm_gem_get_and_pin_iova(mdp4_kms->blank_cursor_bo, kms->vm,
&mdp4_kms->blank_cursor_iova);
if (ret) {
DRM_DEV_ERROR(dev->dev, "could not pin blank-cursor bo: %d\n", ret);
- goto fail;
+ return ret;
}
dev->mode_config.min_width = 0;
@@ -484,12 +484,6 @@ static int mdp4_kms_init(struct drm_device *dev)
dev->mode_config.max_height = 2048;
return 0;
-
-fail:
- if (kms)
- mdp4_destroy(kms);
-
- return ret;
}
static const struct dev_pm_ops mdp4_pm_ops = {
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 0a004ab9fc85..3934cd060b27 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -517,7 +517,7 @@ static int mdp5_kms_init(struct drm_device *dev)
ret = mdp_kms_init(&mdp5_kms->base, &kms_funcs);
if (ret) {
DRM_DEV_ERROR(&pdev->dev, "failed to init kms\n");
- goto fail;
+ return ret;
}
config = mdp5_cfg_get_config(mdp5_kms->cfg);
@@ -540,7 +540,7 @@ static int mdp5_kms_init(struct drm_device *dev)
vm = msm_kms_init_vm(mdp5_kms->dev, pdev->dev.parent);
if (IS_ERR(vm)) {
ret = PTR_ERR(vm);
- goto fail;
+ return ret;
}
kms->vm = vm;
@@ -550,7 +550,7 @@ static int mdp5_kms_init(struct drm_device *dev)
ret = modeset_init(mdp5_kms);
if (ret) {
DRM_DEV_ERROR(&pdev->dev, "modeset_init failed: %d\n", ret);
- goto fail;
+ return ret;
}
dev->mode_config.min_width = 0;
@@ -562,11 +562,6 @@ static int mdp5_kms_init(struct drm_device *dev)
dev->vblank_disable_immediate = true;
return 0;
-fail:
- if (kms)
- mdp5_kms_destroy(kms);
-
- return ret;
}
static void mdp5_destroy(struct mdp5_kms *mdp5_kms)
---
base-commit: b9810cd75b9fb56a3425d391cba3f608502bd474
change-id: 20260723-msm-fix-crash-8c13220d9465
Best regards,
--
With best wishes
Dmitry
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] drm/msm: don't tear down KMS twice when KMS init fails
2026-07-23 9:52 [PATCH] drm/msm: don't tear down KMS twice when KMS init fails Dmitry Baryshkov
@ 2026-07-23 10:04 ` Konrad Dybcio
2026-07-23 10:18 ` sashiko-bot
1 sibling, 0 replies; 3+ messages in thread
From: Konrad Dybcio @ 2026-07-23 10:04 UTC (permalink / raw)
To: Dmitry Baryshkov, Rob Clark, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie,
Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 7/23/26 11:52 AM, Dmitry Baryshkov wrote:
> When priv->kms_init() (mdp4_kms_init() / mdp5_kms_init()) fails partway
> through, both display drivers already tear their KMS state down via
> mdp4_destroy() / mdp5_kms_destroy() before returning the error. The
> common error path in msm_drm_init() then runs msm_drm_uninit() ->
> msm_drm_kms_uninit(), which tries to destroy the very same KMS a second
> time, which causes a use-after-free crash.
>
> Bring MDP4/MDP5 in line with the DPU driver whose dpu_kms_init() doesn't
> perform error cleanup on the failure. Let the common path own the
> cleanup, instead of freeing the KMS from their error paths.
>
> The crash trace for the reference:
>
> __lock_acquire from lock_acquire (kernel/locking/lockdep.c:5906 kernel/locking/lockdep.c:5863)
> lock_acquire from touch_wq_lockdep_map (kernel/workqueue.c:4094 (discriminator 1))
> touch_wq_lockdep_map from __flush_workqueue (kernel/workqueue.c:4136)
> __flush_workqueue from msm_drm_kms_uninit (drivers/gpu/drm/msm/msm_kms.c:243 (discriminator 33))
> msm_drm_kms_uninit from msm_drm_uninit (drivers/gpu/drm/msm/msm_drv.c:93)
> msm_drm_uninit from msm_drm_init (drivers/gpu/drm/msm/msm_drv.c:184)
> msm_drm_init from try_to_bring_up_aggregate_device (drivers/base/component.c:249 drivers/base/component.c:227)
> try_to_bring_up_aggregate_device from __component_add (drivers/base/component.c:269 drivers/base/component.c:748)
> __component_add from dsi_host_attach (drivers/gpu/drm/msm/dsi/dsi_host.c:1739)
> dsi_host_attach from mipi_dsi_attach (drivers/gpu/drm/drm_mipi_dsi.c:383)
> mipi_dsi_attach from sharp_nt_panel_probe (drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c:247)
>
> Fixes: 506efcba3129 ("drm/msm: carve out KMS code from msm_drv.c")
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] drm/msm: don't tear down KMS twice when KMS init fails
2026-07-23 9:52 [PATCH] drm/msm: don't tear down KMS twice when KMS init fails Dmitry Baryshkov
2026-07-23 10:04 ` Konrad Dybcio
@ 2026-07-23 10:18 ` sashiko-bot
1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-07-23 10:18 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Kernel panics in common KMS teardown path due to unconditional dereference of partially-initialized structures on early probe failures.
--
--- Patch [1]: [PATCH] drm/msm: don't tear down KMS twice when KMS init fails ---
commit dccb630956dd40369b4b75f78b147548c8331788
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
drm/msm: don't tear down KMS twice when KMS init fails
This commit removes the local KMS teardown from the mdp4 and mdp5 error
paths. It instead relies on the common msm_drm_kms_uninit() path to handle
cleanup on failure, preventing a use-after-free crash.
> diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
> --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
> +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
> @@ -398,7 +398,7 @@ static int mdp4_kms_init(struct drm_device *dev)
> ret = mdp_kms_init(&mdp4_kms->base, &kms_funcs);
> if (ret) {
> DRM_DEV_ERROR(dev->dev, "failed to init kms\n");
> - goto fail;
> + return ret;
> }
[Severity: High]
This is a pre-existing issue, but by delegating all cleanup to the common
path on early failures, do we risk kernel panics from dereferencing
uninitialized pointers?
If mdp_kms_init() fails here, msm_drm_kms_uninit() will be called to clean up.
However, if kms->wq was never allocated, won't flush_workqueue(kms->wq)
trigger a panic inside __flush_workqueue() when it attempts to dereference
the workqueue?
Similarly, if initialization fails before kms->funcs is populated,
could msm_irq_uninstall() trigger a NULL pointer dereference when executing
kms->funcs->irq_uninstall(kms)?
Additionally, when kms->funcs->destroy(kms) eventually calls mdp4_destroy(),
would this unconditionally dereference mdp4_kms->dev->dev, where
mdp4_kms->dev remains NULL because mdp_kms_init() failed?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260723-msm-fix-crash-v1-1-78fb4721c2d9@oss.qualcomm.com?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-23 10:18 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-23 9:52 [PATCH] drm/msm: don't tear down KMS twice when KMS init fails Dmitry Baryshkov
2026-07-23 10:04 ` Konrad Dybcio
2026-07-23 10:18 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.