All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Anand Moon" <linux.amoon@gmail.com>
Cc: neil.armstrong@linaro.org, linux-media@vger.kernel.org,
	linux-amlogic@lists.infradead.org
Subject: Re: [PATCH v6 3/8] media: meson: vdec: Handle kthread failure and free codec state
Date: Sat, 30 May 2026 10:25:53 +0000	[thread overview]
Message-ID: <20260530102554.313521F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260530094326.11892-4-linux.amoon@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Critical] Double-free of DMA buffers in the new err_cleanup path due to a redundant codec_ops->stop(sess) call.

Pre-existing issues:
- [Critical] Clearing the hardware ownership token `core->cur_sess` before executing `vdec_poweroff(sess)` creates a critical data race with concurrent sessions.
- [High] The concurrent locking patch destroys the STATUS_NEEDS_RESUME state, leading to massive memory leaks during dynamic resolution changes.
--

commit fd226e8b0810c7234d383bfb2d7ea8c103056049
Author: Anand Moon <linux.amoon@gmail.com>

media: meson: vdec: Handle kthread failure and free codec state
    
vdec_start_streaming() launches a recycle thread when required by the
codec. If kthread_run() fails, the previous error path only powered off
the hardware, leaving sess->priv and codec state allocated. This caused
a permanent leak of the codec context and associated DMA buffers.
    
Fix this by introducing a dedicated err_cleanup path:

- Call codec_ops->stop() to release the codec context and clear sess->priv.
- Power off the hardware before freeing buffers to avoid DMA faults.
- Free canvas IDs explicitly and set sess->vififo_vaddr = NULL after
  dma_free_coherent() to guard against double‑free in fallback stop paths.
- Reset core->cur_sess and sess->status to prevent stale references.

Following change closes the memory leak on kthread_run() failure and ensures
robust cleanup of codec resources in both error and stop paths.

Closes: https://lore.kernel.org/all/20260521090944.F35401F00A3D@smtp.kernel.org/
Fixes: 3e7f51bd9607 ("media: meson: add v4l2 m2m video decoder driver")

> diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c
> index 7233000e22323..8a5bf1a96830c 100644
> --- a/drivers/staging/media/meson/vdec/vdec.c
> +++ b/drivers/staging/media/meson/vdec/vdec.c

[ ... ]

> @@ -352,16 +354,31 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
>  
>  	sess->sequence_cap = 0;
>  	sess->sequence_out = 0;
> -	if (vdec_codec_needs_recycle(sess))
> +	if (vdec_codec_needs_recycle(sess)) {
>  		sess->recycle_thread = kthread_run(vdec_recycle_thread, sess,
>  						   "vdec_recycle");
> +		if (IS_ERR(sess->recycle_thread)) {
> +			ret = PTR_ERR(sess->recycle_thread);
> +			sess->recycle_thread = NULL;
> +			goto err_cleanup;
> +		}
> +	}
>  
>  	schedule_work(&sess->esparser_queue_work);
>  	return 0;
>  
> +err_cleanup:
> +	vdec_free_canvas(sess);
> +	vdec_poweroff(sess);
> +	if (codec_ops && codec_ops->stop && sess->priv) {
> +		codec_ops->stop(sess);

[Severity: Critical]
Does this explicitly call codec_ops->stop() a second time, resulting in a
double-free of the codec DMA memory?

Looking at vdec_poweroff() called just above, it internally delegates to
vdec_ops->stop(), which invokes codec_ops->stop(). Codec stop callbacks
free their DMA buffers via dma_free_coherent() but do not set the
pointers to NULL. If it is called again here, wouldn't it attempt to free
them a second time?

> +		kfree(sess->priv);
> +		sess->priv = NULL;
> +	}
>  vififo_free:
>  	dma_free_coherent(sess->core->dev, sess->vififo_size,
>  			  sess->vififo_vaddr, sess->vififo_paddr);
> +	sess->vififo_vaddr = NULL;
>  bufs_done:

[ ... ]

> @@ -441,8 +458,11 @@ static void vdec_stop_streaming(struct vb2_queue *q)
>  
>  		vdec_poweroff(sess);

[Severity: Critical]
This is a pre-existing issue, but could clearing the hardware ownership token
before executing vdec_poweroff() create a data race with concurrent sessions?

Looking earlier in vdec_stop_streaming(), core->cur_sess = NULL is set
inside the mutex, but vdec_poweroff(sess) is executed here after the mutex
is dropped:

	mutex_lock(&core->lock);
	if (core->cur_sess == sess)
		core->cur_sess = NULL;
	mutex_unlock(&core->lock);
    ...
	vdec_poweroff(sess);

This allows a concurrent vdec_start_streaming() from another context to
acquire the lock, claim ownership, and call vdec_poweron(). Since
vdec_poweron() and vdec_poweroff() would execute concurrently on different
sessions, is it possible they will read and write to the exact same global
hardware registers and corrupt the shared hardware state?

>  		vdec_free_canvas(sess);
> -		dma_free_coherent(sess->core->dev, sess->vififo_size,
> -				  sess->vififo_vaddr, sess->vififo_paddr);
> +		if (sess->vififo_vaddr) {
> +			dma_free_coherent(sess->core->dev, sess->vififo_size,
> +					  sess->vififo_vaddr,
> +					  sess->vififo_paddr);
> +		}
>  		vdec_reset_timestamps(sess);
>  		vdec_reset_bufs_recycle(sess);
>  		kfree(sess->priv);

[Severity: High]
This isn't a bug introduced by this patch, but does the recent change to
concurrent locking destroy the STATUS_NEEDS_RESUME state?

Earlier in vdec_stop_streaming(), sess->status is unconditionally overwritten
to STATUS_STOPPED inside the mutex lock:

	mutex_lock(&core->lock);
	old_status = sess->status;
	sess->status = STATUS_STOPPED;
	mutex_unlock(&core->lock);

When the CAPTURE queue is stopped during a source resolution change, the
hardware cleanup block is intentionally skipped because old_status is
STATUS_NEEDS_RESUME. However, when vdec_start_streaming() is later called to
resume the CAPTURE queue, it expects sess->status == STATUS_NEEDS_RESUME.
Since it was forced to STATUS_STOPPED, will the resume check fail and cause
the driver to incorrectly fall through to full initialization, executing
dma_alloc_coherent() over the existing sess->vififo_vaddr and leaking
memory?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260530094326.11892-1-linux.amoon@gmail.com?part=3

WARNING: multiple messages have this Message-ID (diff)
From: sashiko-bot@kernel.org
To: "Anand Moon" <linux.amoon@gmail.com>
Cc: neil.armstrong@linaro.org, linux-media@vger.kernel.org,
	linux-amlogic@lists.infradead.org
Subject: Re: [PATCH v6 3/8] media: meson: vdec: Handle kthread failure and free codec state
Date: Sat, 30 May 2026 10:25:53 +0000	[thread overview]
Message-ID: <20260530102554.313521F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260530094326.11892-4-linux.amoon@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Critical] Double-free of DMA buffers in the new err_cleanup path due to a redundant codec_ops->stop(sess) call.

Pre-existing issues:
- [Critical] Clearing the hardware ownership token `core->cur_sess` before executing `vdec_poweroff(sess)` creates a critical data race with concurrent sessions.
- [High] The concurrent locking patch destroys the STATUS_NEEDS_RESUME state, leading to massive memory leaks during dynamic resolution changes.
--

commit fd226e8b0810c7234d383bfb2d7ea8c103056049
Author: Anand Moon <linux.amoon@gmail.com>

media: meson: vdec: Handle kthread failure and free codec state
    
vdec_start_streaming() launches a recycle thread when required by the
codec. If kthread_run() fails, the previous error path only powered off
the hardware, leaving sess->priv and codec state allocated. This caused
a permanent leak of the codec context and associated DMA buffers.
    
Fix this by introducing a dedicated err_cleanup path:

- Call codec_ops->stop() to release the codec context and clear sess->priv.
- Power off the hardware before freeing buffers to avoid DMA faults.
- Free canvas IDs explicitly and set sess->vififo_vaddr = NULL after
  dma_free_coherent() to guard against double‑free in fallback stop paths.
- Reset core->cur_sess and sess->status to prevent stale references.

Following change closes the memory leak on kthread_run() failure and ensures
robust cleanup of codec resources in both error and stop paths.

Closes: https://lore.kernel.org/all/20260521090944.F35401F00A3D@smtp.kernel.org/
Fixes: 3e7f51bd9607 ("media: meson: add v4l2 m2m video decoder driver")

> diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c
> index 7233000e22323..8a5bf1a96830c 100644
> --- a/drivers/staging/media/meson/vdec/vdec.c
> +++ b/drivers/staging/media/meson/vdec/vdec.c

[ ... ]

> @@ -352,16 +354,31 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
>  
>  	sess->sequence_cap = 0;
>  	sess->sequence_out = 0;
> -	if (vdec_codec_needs_recycle(sess))
> +	if (vdec_codec_needs_recycle(sess)) {
>  		sess->recycle_thread = kthread_run(vdec_recycle_thread, sess,
>  						   "vdec_recycle");
> +		if (IS_ERR(sess->recycle_thread)) {
> +			ret = PTR_ERR(sess->recycle_thread);
> +			sess->recycle_thread = NULL;
> +			goto err_cleanup;
> +		}
> +	}
>  
>  	schedule_work(&sess->esparser_queue_work);
>  	return 0;
>  
> +err_cleanup:
> +	vdec_free_canvas(sess);
> +	vdec_poweroff(sess);
> +	if (codec_ops && codec_ops->stop && sess->priv) {
> +		codec_ops->stop(sess);

[Severity: Critical]
Does this explicitly call codec_ops->stop() a second time, resulting in a
double-free of the codec DMA memory?

Looking at vdec_poweroff() called just above, it internally delegates to
vdec_ops->stop(), which invokes codec_ops->stop(). Codec stop callbacks
free their DMA buffers via dma_free_coherent() but do not set the
pointers to NULL. If it is called again here, wouldn't it attempt to free
them a second time?

> +		kfree(sess->priv);
> +		sess->priv = NULL;
> +	}
>  vififo_free:
>  	dma_free_coherent(sess->core->dev, sess->vififo_size,
>  			  sess->vififo_vaddr, sess->vififo_paddr);
> +	sess->vififo_vaddr = NULL;
>  bufs_done:

[ ... ]

> @@ -441,8 +458,11 @@ static void vdec_stop_streaming(struct vb2_queue *q)
>  
>  		vdec_poweroff(sess);

[Severity: Critical]
This is a pre-existing issue, but could clearing the hardware ownership token
before executing vdec_poweroff() create a data race with concurrent sessions?

Looking earlier in vdec_stop_streaming(), core->cur_sess = NULL is set
inside the mutex, but vdec_poweroff(sess) is executed here after the mutex
is dropped:

	mutex_lock(&core->lock);
	if (core->cur_sess == sess)
		core->cur_sess = NULL;
	mutex_unlock(&core->lock);
    ...
	vdec_poweroff(sess);

This allows a concurrent vdec_start_streaming() from another context to
acquire the lock, claim ownership, and call vdec_poweron(). Since
vdec_poweron() and vdec_poweroff() would execute concurrently on different
sessions, is it possible they will read and write to the exact same global
hardware registers and corrupt the shared hardware state?

>  		vdec_free_canvas(sess);
> -		dma_free_coherent(sess->core->dev, sess->vififo_size,
> -				  sess->vififo_vaddr, sess->vififo_paddr);
> +		if (sess->vififo_vaddr) {
> +			dma_free_coherent(sess->core->dev, sess->vififo_size,
> +					  sess->vififo_vaddr,
> +					  sess->vififo_paddr);
> +		}
>  		vdec_reset_timestamps(sess);
>  		vdec_reset_bufs_recycle(sess);
>  		kfree(sess->priv);

[Severity: High]
This isn't a bug introduced by this patch, but does the recent change to
concurrent locking destroy the STATUS_NEEDS_RESUME state?

Earlier in vdec_stop_streaming(), sess->status is unconditionally overwritten
to STATUS_STOPPED inside the mutex lock:

	mutex_lock(&core->lock);
	old_status = sess->status;
	sess->status = STATUS_STOPPED;
	mutex_unlock(&core->lock);

When the CAPTURE queue is stopped during a source resolution change, the
hardware cleanup block is intentionally skipped because old_status is
STATUS_NEEDS_RESUME. However, when vdec_start_streaming() is later called to
resume the CAPTURE queue, it expects sess->status == STATUS_NEEDS_RESUME.
Since it was forced to STATUS_STOPPED, will the resume check fail and cause
the driver to incorrectly fall through to full initialization, executing
dma_alloc_coherent() over the existing sess->vififo_vaddr and leaking
memory?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260530094326.11892-1-linux.amoon@gmail.com?part=3

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

  reply	other threads:[~2026-05-30 10:25 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-30  9:42 [PATCH v6 0/8] media: meson: Fix memory leak in error path in vdec Anand Moon
2026-05-30  9:42 ` Anand Moon
2026-05-30  9:42 ` Anand Moon
2026-05-30  9:42 ` [PATCH v6 1/8] media: meson: vdec: Fix memory leaks and lifetime of m2m device Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30  9:55   ` sashiko-bot
2026-05-30  9:55     ` sashiko-bot
2026-05-30  9:42 ` [PATCH v6 2/8] media: meson: vdec: Fix concurrent STREAMON / STREAMOFF race conditions Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30 10:08   ` sashiko-bot
2026-05-30 10:08     ` sashiko-bot
2026-05-30  9:42 ` [PATCH v6 3/8] media: meson: vdec: Handle kthread failure and free codec state Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30 10:25   ` sashiko-bot [this message]
2026-05-30 10:25     ` sashiko-bot
2026-05-30  9:42 ` [PATCH v6 4/8] media: meson: vdec: Condition buffer flushing on queue type in start_streaming Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30 10:43   ` sashiko-bot
2026-05-30 10:43     ` sashiko-bot
2026-05-30  9:42 ` [PATCH v6 5/8] media: meson: vdec: Cancel esparser work during teardown Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30 10:59   ` sashiko-bot
2026-05-30 10:59     ` sashiko-bot
2026-05-30  9:42 ` [PATCH v6 6/8] media: meson: vdec: Configure DMA mask and segment size in probe Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30 11:10   ` sashiko-bot
2026-05-30 11:10     ` sashiko-bot
2026-05-30  9:42 ` [PATCH v6 7/8] media: meson: vdec: Fix NULL pointer dereference in ISR handlers Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30 11:23   ` sashiko-bot
2026-05-30 11:23     ` sashiko-bot
2026-05-30  9:42 ` [PATCH v6 8/8] gpu: drm: meson: Fix DMA max segment size for DMABUF imports Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30  9:42   ` Anand Moon
2026-05-30 11:35   ` sashiko-bot
2026-05-30 11:35     ` 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=20260530102554.313521F00893@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-amlogic@lists.infradead.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux.amoon@gmail.com \
    --cc=neil.armstrong@linaro.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 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.