Linux Sound subsystem development
 help / color / mirror / Atom feed
* [PATCH] ALSA: hdsp: Fix divide-by-zero in DDS offset control
@ 2026-11-04  8:30 songxiebing
  2026-11-04  8:39 ` sashiko-bot
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: songxiebing @ 2026-11-04  8:30 UTC (permalink / raw)
  To: tiwai, perex; +Cc: linux-sound, linux-kernel, songxiebing, stable

From: Bob Song <songxiebing@kylinos.cn>

hdsp_set_dds_offset() computes the target rate as
system_sample_rate + offset_hz without validating the result.  A user
can set the DDS offset to -system_sample_rate through the control API,
making rate zero and causing div_u64() in hdsp_set_dds_value() to
divide by zero.

Reject non-positive rates before programming the DDS value.

Fixes: e4b6088c8cf1 ("[ALSA] hdsp - Add support for fine tuning of sample rate support to HDSP 9632")
Cc: <stable@vger.kernel.org>
Signed-off-by: Bob Song <songxiebing@kylinos.cn>
---
 sound/pci/rme9652/hdsp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 7dce548b9f36..694816f966d2 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -2802,6 +2802,9 @@ static int hdsp_dds_offset(struct hdsp *hdsp)
 static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz)
 {
 	int rate = hdsp->system_sample_rate + offset_hz;
+
+	if (rate <= 0)
+		return -EINVAL;
 	hdsp_set_dds_value(hdsp, rate);
 	return 0;
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] ALSA: hdsp: Fix divide-by-zero in DDS offset control
  2026-11-04  8:30 [PATCH] ALSA: hdsp: Fix divide-by-zero in DDS offset control songxiebing
@ 2026-11-04  8:39 ` sashiko-bot
  2026-11-04  9:00 ` [PATCH v2] ALSA: hdsp: Validate DDS offset range and propagate errors songxiebing
  2026-11-04 10:09 ` [PATCH] ALSA: hdsp: Fix divide-by-zero in DDS offset control Takashi Iwai
  2 siblings, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-11-04  8:39 UTC (permalink / raw)
  To: songxiebing; +Cc: linux-sound

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] ALSA: hdsp: incomplete offset validation in hdsp_set_dds_offset()
--

commit a91b0358087c1f7f09a07e8d353cc380f3a7e223
Author: Bob Song <songxiebing@kylinos.cn>

ALSA: hdsp: Fix divide-by-zero in DDS offset control

This commit updates hdsp_set_dds_offset() to reject non-positive target
sample rates with -EINVAL before calling hdsp_set_dds_value() to prevent a
divide-by-zero in div_u64().

> diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
> index 7dce548b9f363..694816f966d29 100644
> --- a/sound/pci/rme9652/hdsp.c
> +++ b/sound/pci/rme9652/hdsp.c
> @@ -2802,6 +2802,9 @@ static int hdsp_dds_offset(struct hdsp *hdsp)
>  static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz)
>  {
>  	int rate = hdsp->system_sample_rate + offset_hz;
> +
> +	if (rate <= 0)
> +		return -EINVAL;

[Severity: Medium]
Is checking rate <= 0 sufficient to validate offset_hz here?

When snd_hdsp_put_dds_offset() calls hdsp_set_dds_offset(), offset_hz comes
from ucontrol->value.integer.value[0] without enforcing the [-5000, 5000]
range declared in snd_hdsp_info_dds_offset():

sound/pci/rme9652/hdsp.c:snd_hdsp_info_dds_offset() {
	...
	uinfo->value.integer.min = -5000;
	uinfo->value.integer.max = 5000;
	return 0;
}

First, adding an unvalidated positive offset_hz to hdsp->system_sample_rate
can overflow a signed 32-bit int.

Second, a positive rate in the range 1..24414 (for example, passing
offset_hz = 1 - hdsp->system_sample_rate) still passes the rate <= 0 check
and reaches hdsp_set_dds_value():

sound/pci/rme9652/hdsp.c:hdsp_set_dds_value() {
	...
	n = DDS_NUMERATOR;
	n = div_u64(n, rate);
	/* n should be less than 2^32 for being written to FREQ register */
	snd_BUG_ON(n >> 32);
	/* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS
	   value to write it after a reset */
	hdsp->dds_value = n;
	hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value);
}

Because DDS_NUMERATOR is 104857600000000ULL, any rate in 1..24414 produces
n >= 2^32, which triggers snd_BUG_ON(n >> 32) and truncates n when writing
hdsp->dds_value and HDSP_freqReg. Offsets outside [-5000, 5000] can also
cross the 56000 or 112000 thresholds in hdsp_set_dds_value(), whereas
hdsp_dds_offset() chooses the 2x or 4x multiplier based on
hdsp->system_sample_rate.

In addition, when hdsp_set_dds_offset() returns -EINVAL, its caller
snd_hdsp_put_dds_offset() drops the error code:

sound/pci/rme9652/hdsp.c:snd_hdsp_put_dds_offset() {
	...
	if (val != hdsp_dds_offset(hdsp))
		change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
	...
	return change;
}

Should hdsp_set_dds_offset() validate that offset_hz is within
[-5000, 5000] before computing rate, and should snd_hdsp_put_dds_offset()
propagate negative error codes from hdsp_set_dds_offset()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261104083045.1939479-1-songxiebing@kylinos.cn?part=1

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2] ALSA: hdsp: Validate DDS offset range and propagate errors
  2026-11-04  8:30 [PATCH] ALSA: hdsp: Fix divide-by-zero in DDS offset control songxiebing
  2026-11-04  8:39 ` sashiko-bot
@ 2026-11-04  9:00 ` songxiebing
  2026-11-04 10:09 ` [PATCH] ALSA: hdsp: Fix divide-by-zero in DDS offset control Takashi Iwai
  2 siblings, 0 replies; 4+ messages in thread
From: songxiebing @ 2026-11-04  9:00 UTC (permalink / raw)
  To: tiwai, perex; +Cc: linux-sound, linux-kernel, songxiebing, stable

From: Bob Song <songxiebing@kylinos.cn>

hdsp_set_dds_offset() computes the target rate as
system_sample_rate + offset_hz without validating the result.  A user
can set the DDS offset to -system_sample_rate through the control API,
making rate zero and causing div_u64() in hdsp_set_dds_value() to
divide by zero.  Larger offsets can also overflow the rate calculation
or push the DDS value out of range.

Validate offset_hz against the [-5000, 5000] range advertised by the
control, keep the non-positive rate check as a safety net, and
propagate the error from snd_hdsp_put_dds_offset() instead of
reporting success.

Fixes: e4b6088c8cf1 ("[ALSA] hdsp - Add support for fine tuning of sample rate support to HDSP 9632")
Cc: <stable@vger.kernel.org>
Signed-off-by: Bob Song <songxiebing@kylinos.cn>
---
 sound/pci/rme9652/hdsp.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 7dce548b9f36..467121a5fb4f 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -2768,6 +2768,9 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn
 	return 0;
 }
 
+#define HDSP_DDS_OFFSET_MIN	-5000
+#define HDSP_DDS_OFFSET_MAX	5000
+
 #define HDSP_DDS_OFFSET(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -2801,7 +2804,15 @@ static int hdsp_dds_offset(struct hdsp *hdsp)
 
 static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz)
 {
-	int rate = hdsp->system_sample_rate + offset_hz;
+	int rate;
+
+	if (offset_hz < HDSP_DDS_OFFSET_MIN ||
+	    offset_hz > HDSP_DDS_OFFSET_MAX)
+		return -EINVAL;
+
+	rate = hdsp->system_sample_rate + offset_hz;
+	if (rate <= 0)
+		return -EINVAL;
 	hdsp_set_dds_value(hdsp, rate);
 	return 0;
 }
@@ -2810,8 +2821,8 @@ static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ct
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 1;
-	uinfo->value.integer.min = -5000;
-	uinfo->value.integer.max = 5000;
+	uinfo->value.integer.min = HDSP_DDS_OFFSET_MIN;
+	uinfo->value.integer.max = HDSP_DDS_OFFSET_MAX;
 	return 0;
 }
 
@@ -2833,10 +2844,14 @@ static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0];
 	guard(spinlock_irq)(&hdsp->lock);
-	if (val != hdsp_dds_offset(hdsp))
-		change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
-	else
+	if (val != hdsp_dds_offset(hdsp)) {
+		change = hdsp_set_dds_offset(hdsp, val);
+		if (change < 0)
+			return change;
+		change = 1;
+	} else {
 		change = 0;
+	}
 	return change;
 }
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] ALSA: hdsp: Fix divide-by-zero in DDS offset control
  2026-11-04  8:30 [PATCH] ALSA: hdsp: Fix divide-by-zero in DDS offset control songxiebing
  2026-11-04  8:39 ` sashiko-bot
  2026-11-04  9:00 ` [PATCH v2] ALSA: hdsp: Validate DDS offset range and propagate errors songxiebing
@ 2026-11-04 10:09 ` Takashi Iwai
  2 siblings, 0 replies; 4+ messages in thread
From: Takashi Iwai @ 2026-11-04 10:09 UTC (permalink / raw)
  To: songxiebing; +Cc: tiwai, perex, linux-sound, linux-kernel, stable

On Wed, 04 Nov 2026 09:30:45 +0100,
songxiebing wrote:
> 
> From: Bob Song <songxiebing@kylinos.cn>
> 
> hdsp_set_dds_offset() computes the target rate as
> system_sample_rate + offset_hz without validating the result.  A user
> can set the DDS offset to -system_sample_rate through the control API,
> making rate zero and causing div_u64() in hdsp_set_dds_value() to
> divide by zero.
> 
> Reject non-positive rates before programming the DDS value.
> 
> Fixes: e4b6088c8cf1 ("[ALSA] hdsp - Add support for fine tuning of sample rate support to HDSP 9632")
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Bob Song <songxiebing@kylinos.cn>
> ---
>  sound/pci/rme9652/hdsp.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
> index 7dce548b9f36..694816f966d2 100644
> --- a/sound/pci/rme9652/hdsp.c
> +++ b/sound/pci/rme9652/hdsp.c
> @@ -2802,6 +2802,9 @@ static int hdsp_dds_offset(struct hdsp *hdsp)
>  static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz)
>  {
>  	int rate = hdsp->system_sample_rate + offset_hz;
> +
> +	if (rate <= 0)
> +		return -EINVAL;
>  	hdsp_set_dds_value(hdsp, rate);
>  	return 0;
>  }

The caller doesn't check the error case properly.
Please fix the caller side, too.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-11-04 10:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-04  8:30 [PATCH] ALSA: hdsp: Fix divide-by-zero in DDS offset control songxiebing
2026-11-04  8:39 ` sashiko-bot
2026-11-04  9:00 ` [PATCH v2] ALSA: hdsp: Validate DDS offset range and propagate errors songxiebing
2026-11-04 10:09 ` [PATCH] ALSA: hdsp: Fix divide-by-zero in DDS offset control Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox