mirror of https://lore.kernel.org/lkml/
 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  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
  0 siblings, 2 replies; 3+ 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	[flat|nested] 3+ 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  9:00 ` songxiebing
  2026-11-04 10:09 ` [PATCH] ALSA: hdsp: Fix divide-by-zero in DDS offset control Takashi Iwai
  1 sibling, 0 replies; 3+ 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	[flat|nested] 3+ 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  9:00 ` [PATCH v2] ALSA: hdsp: Validate DDS offset range and propagate errors songxiebing
@ 2026-11-04 10:09 ` Takashi Iwai
  1 sibling, 0 replies; 3+ 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] 3+ messages in thread

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

Thread overview: 3+ 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  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

all inboxes | Powered by JetHome®