From: sashiko-bot@kernel.org
To: "Dmitry Baryshkov" <dmitry.baryshkov@oss.qualcomm.com>
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH 1/2] drm/msm: fix framebuffer pin refcount leak on prepare failure
Date: Thu, 03 Sep 2026 13:35:33 +0000 [thread overview]
Message-ID: <20260903133534.494BB1F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260903-fd-kms-fix-smmu-v1-1-608d02491666@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] Unwinding a failed framebuffer prepare while a concurrent prepare exists causes a double-unpin and refcount underflow.
Pre-existing issues:
- [High] Concurrent `msm_framebuffer_prepare` calls for the same framebuffer can race due to lockless `prepare_count`, leading to uninitialized `iova` access and IOMMU faults.
--
commit 4b106914920d42508f14e872754ef791f46ae379
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
drm/msm: fix framebuffer pin refcount leak on prepare failure
This commit addresses a resource leak in msm_framebuffer_prepare() by
unwinding successfully pinned planes and releasing the vma reference when
a subsequent plane fails to pin.
[Severity: High]
This is a pre-existing issue, but can concurrent msm_framebuffer_prepare()
calls for the same framebuffer race due to the lockless prepare_count check?
Looking at msm_framebuffer_prepare() in drivers/gpu/drm/msm/msm_fb.c:
if (atomic_inc_return(&msm_fb->prepare_count) > 1)
return 0;
If userspace issues concurrent atomic commits for different CRTCs sharing the
same framebuffer, Thread A could increment prepare_count to 1 and start
pinning planes. Thread B could concurrently increment prepare_count to 2, hit
this lockless fast-path, and return success immediately before Thread A has
finished populating the iova array.
Thread B's commit might then proceed to scanout using uninitialized memory
addresses (zeros) for DMA, which could cause an IOMMU unhandled context fault.
Could msm_framebuffer_cleanup() also race in a similar way?
if (atomic_dec_return(&msm_fb->prepare_count))
return;
memset(msm_fb->iova, 0, sizeof(msm_fb->iova));
This lockless memset could race with a concurrent prepare_fb from Thread A,
overwriting a newly pinned IOVA with zero.
> diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
> index 60c108d35d2a1..934337202afd4 100644
> --- a/drivers/gpu/drm/msm/msm_fb.c
> +++ b/drivers/gpu/drm/msm/msm_fb.c
> @@ -89,11 +89,27 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb, bool needs_dirtyfb)
[ ... ]
> return 0;
> +
> +unwind:
> + while (i--) {
> + msm_gem_unpin_iova(fb->obj[i], vm);
> + msm_gem_vma_put(fb->obj[i]);
> + }
> +
> + memset(msm_fb->iova, 0, sizeof(msm_fb->iova));
> +
> + atomic_dec(&msm_fb->prepare_count);
[Severity: High]
Does this unwind path create a double-unpin if there is a concurrent
prepare that succeeded via the fast-path?
If Thread A and B enter msm_framebuffer_prepare() concurrently, Thread A
increments prepare_count to 1 and begins pinning. Thread B increments it
to 2 and returns success.
If Thread A encounters an error, it enters this newly added unwind block,
unpins the planes it successfully pinned, and decrements prepare_count from
2 to 1.
When Thread B's commit succeeds and later calls msm_framebuffer_cleanup(),
it will decrement prepare_count from 1 to 0. Since it reaches 0, Thread B
will unconditionally unpin all planes:
drivers/gpu/drm/msm/msm_fb.c:msm_framebuffer_cleanup() {
...
if (atomic_dec_return(&msm_fb->prepare_count))
return;
memset(msm_fb->iova, 0, sizeof(msm_fb->iova));
if (crtc && msm_crtc_queue_fb_unpin(crtc, fb))
return;
for (i = 0; i < n; i++) {
msm_gem_unpin_iova(fb->obj[i], vm);
msm_gem_vma_put(fb->obj[i]);
}
}
Because Thread A already unpinned the planes it originally pinned, Thread
B's cleanup would result in a double-unpin, causing vma_ref and pin_count
underflows, and potentially a use-after-free of GEM memory.
> + if (needs_dirtyfb)
> + refcount_dec(&msm_fb->dirtyfb);
> +
> + return ret;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260903-fd-kms-fix-smmu-v1-0-608d02491666@oss.qualcomm.com?part=1
next prev parent reply other threads:[~2026-09-03 13:35 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 13:23 [PATCH 0/2] drm/msm: fix SMMU fault dumps Dmitry Baryshkov
2026-09-03 13:23 ` [PATCH 1/2] drm/msm: fix framebuffer pin refcount leak on prepare failure Dmitry Baryshkov
2026-09-03 13:35 ` sashiko-bot [this message]
2026-09-03 13:23 ` [PATCH 2/2] drm/msm: release scanout framebuffers only after a vblank Dmitry Baryshkov
2026-09-03 13:39 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260903133534.494BB1F00A3A@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dmitry.baryshkov@oss.qualcomm.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox