public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Cássio Gabriel" <cassiogabrielcontato@gmail.com>
To: Takashi Iwai <tiwai@suse.com>
Cc: Jaroslav Kysela <perex@perex.cz>,
	linux-sound@vger.kernel.org,  linux-kernel@vger.kernel.org
Subject: Re: [PATCH] ALSA: pcm: reconstruct compat appl_ptr in SYNC_PTR ioctl
Date: Sat, 21 Mar 2026 02:19:46 -0300	[thread overview]
Message-ID: <ab4qBUW2lnc1_PyX@ortodist> (raw)
In-Reply-To: <20260319-alsa-pcm-compat-syncptr-boundary-v1-1-ce2b2a61f167@gmail.com>

On Thu, Mar 19, 2026 at 01:23:40AM -0300, Cássio Gabriel wrote:
> The compat SYNC_PTR ioctl exposes appl_ptr and hw_ptr in a reduced
> 32-bit boundary domain. However, when compat user space passes appl_ptr
> back to the kernel, the value is currently fed to pcm_lib_apply_appl_ptr()
> as if it were already in the native runtime->boundary domain.
> 
> This leaves the compat SYNC_PTR path asymmetric: appl_ptr is exported to
> compat user space modulo the compat boundary, but the value written back
> is not reconstructed in the native boundary domain before being applied.
> 
> The mismatch becomes visible after appl_ptr wraps in the compat
> boundary. At that point, compat user space sends a small appl_ptr value
> again, but the kernel may interpret it as a different native appl_ptr
> position instead of the nearest congruent position around the current
> control->appl_ptr.
> 
> Fix this by reconstructing the compat appl_ptr in the native runtime
> boundary before passing it to pcm_lib_apply_appl_ptr().
> 
> Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
> ---
>  sound/core/pcm_native.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 46 insertions(+), 4 deletions(-)
> 
> diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> index 674b50c7c5f6..f2e2854847ae 100644
> --- a/sound/core/pcm_native.c
> +++ b/sound/core/pcm_native.c
> @@ -3228,6 +3228,45 @@ static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)
>  		return boundary / 2;
>  }
>  
> +/*
> + * Reconstruct the nearest native appl_ptr for a compat appl_ptr
> + * value modulo compat_boundary.
> + */
> +static snd_pcm_uframes_t
> +snd_pcm_compat_reconstruct_appl_ptr(struct snd_pcm_runtime *runtime,
> +				    snd_pcm_uframes_t compat_boundary,
> +				    u32 appl_ptr)
> +{
> +	snd_pcm_uframes_t cur = runtime->control->appl_ptr;
> +	snd_pcm_sframes_t rel; /* relative offset */
> +	snd_pcm_sframes_t new_appl_ptr;
> +
> +	if (!compat_boundary || compat_boundary >= runtime->boundary)
> +		return appl_ptr;
> +
> +	appl_ptr %= compat_boundary;
> +	rel = (snd_pcm_sframes_t)appl_ptr -
> +	      (snd_pcm_sframes_t)(cur % compat_boundary);
> +
> +	/*
> +	 * Pick the shortest relative distance in the compat ring so the
> +	 * reconstructed native appl_ptr stays nearest to the current
> +	 * position.
> +	 */
> +	if (rel > (snd_pcm_sframes_t)(compat_boundary / 2))
> +		rel -= compat_boundary;
> +	else if (rel < -(snd_pcm_sframes_t)(compat_boundary / 2))
> +		rel += compat_boundary;
> +
> +	new_appl_ptr = (snd_pcm_sframes_t)cur + rel;
> +	if (new_appl_ptr < 0)
> +		new_appl_ptr += runtime->boundary;
> +	else if ((snd_pcm_uframes_t)new_appl_ptr >= runtime->boundary)
> +		new_appl_ptr -= runtime->boundary;
> +
> +	return (snd_pcm_uframes_t)new_appl_ptr;
> +}
> +
>  static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
>  					 struct snd_pcm_sync_ptr32 __user *src)
>  {
> @@ -3253,13 +3292,16 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
>  	status = runtime->status;
>  	control = runtime->control;
>  	boundary = recalculate_boundary(runtime);
> -	if (! boundary)
> +	if (!boundary)
>  		boundary = 0x7fffffff;
>  	scoped_guard(pcm_stream_lock_irq, substream) {
> -		/* FIXME: we should consider the boundary for the sync from app */
>  		if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) {
> -			err = pcm_lib_apply_appl_ptr(substream,
> -						     scontrol.appl_ptr);
> +			err = pcm_lib_apply_appl_ptr
> +				(substream,
> +				 snd_pcm_compat_reconstruct_appl_ptr
> +					(runtime,
> +					 boundary,
> +					 scontrol.appl_ptr));
>  			if (err < 0)
>  				return err;
>  		} else
> 
> ---
> base-commit: b3c48fa1fb397b490101785ddd87caf2e5513a66
> change-id: 20260318-alsa-pcm-compat-syncptr-boundary-0d52d2f8dc7e
> 
> Best regards,
> -- 
> Cássio Gabriel <cassiogabrielcontato@gmail.com>
> 

Please disregard this patch.

After further analysis, I concluded that the supported 32-bit
compat flow already handles the boundary correctly.

Although native PCM setup creates a large runtime->boundary on
64-bit kernels, the HW_PARAMS32 compat path reduces it to a
compat-safe value, and the SYNC_PTR32 path passes appl_ptr
through pcm_lib_apply_appl_ptr(), which already rejects values
greater than or equal to runtime->boundary.

So, in practice, the compat sync-from-user path already accounts
for the reduced boundary correctly.

      reply	other threads:[~2026-03-21  5:19 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-19  4:23 [PATCH] ALSA: pcm: reconstruct compat appl_ptr in SYNC_PTR ioctl Cássio Gabriel
2026-03-21  5:19 ` Cássio Gabriel [this message]

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=ab4qBUW2lnc1_PyX@ortodist \
    --to=cassiogabrielcontato@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.com \
    /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