summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-10 10:16:04 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-10 10:16:04 -0700
commit7aa1cf254ca66bc9602bc5adef5bf1d611869a69 (patch)
tree91cb4c568dfe754b4aab78d9d4279297ce4b0188
parentd36260050e1881dce09625a9352d8729c911a6e3 (diff)
parente1a3a981e320a6916b30ff53571ba144274def0e (diff)
downloadlinux-7aa1cf254ca66bc9602bc5adef5bf1d611869a69.tar.bz2
Merge tag 'sound-fix-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai: "The main purpose of this pull request is a fix for a regression in the recent PCM OSS emulation code that may lead to RCU stall. Since syzkaller hits this too often, I send the pull request now with a minimal collection. Possibly another pull request may follow before RC1. The other fixes here are for USB-audio class 2 and 3 to improve the parser for the clock descriptors. These are rather cleanups but good for security, too. Last but not least, another included fix is the trivial one to remove superfluous WARN_ON() that annoyed syzbot" * tag 'sound-fix-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: pcm: Remove WARN_ON() at snd_pcm_hw_params() error ALSA: pcm: Fix endless loop for XRUN recovery in OSS emulation ALSA: usb-audio: Add sanity checks in UAC3 clock parsers ALSA: usb-audio: More strict sanity checks for clock parsers ALSA: usb-audio: Refactor clock finder helpers
-rw-r--r--sound/core/oss/pcm_oss.c5
-rw-r--r--sound/core/pcm_native.c2
-rw-r--r--sound/usb/clock.c128
3 files changed, 58 insertions, 77 deletions
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 481ab0e94ffa..1980f68246cb 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1128,13 +1128,14 @@ static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_fil
}
/* call with params_lock held */
+/* NOTE: this always call PREPARE unconditionally no matter whether
+ * runtime->oss.prepare is set or not
+ */
static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream)
{
int err;
struct snd_pcm_runtime *runtime = substream->runtime;
- if (!runtime->oss.prepare)
- return 0;
err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
if (err < 0) {
pcm_dbg(substream->pcm,
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index b84554893fab..35ffccea94c3 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -617,7 +617,7 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
changed = snd_pcm_hw_param_first(pcm, params, *v, NULL);
else
changed = snd_pcm_hw_param_last(pcm, params, *v, NULL);
- if (snd_BUG_ON(changed < 0))
+ if (changed < 0)
return changed;
if (changed == 0)
continue;
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index ab39ccb974c6..0b030d8fe3fa 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -35,105 +35,85 @@
#include "clock.h"
#include "quirks.h"
-static struct uac_clock_source_descriptor *
- snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface,
- int clock_id)
+static void *find_uac_clock_desc(struct usb_host_interface *iface, int id,
+ bool (*validator)(void *, int), u8 type)
{
- struct uac_clock_source_descriptor *cs = NULL;
+ void *cs = NULL;
- while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
- ctrl_iface->extralen,
- cs, UAC2_CLOCK_SOURCE))) {
- if (cs->bLength >= sizeof(*cs) && cs->bClockID == clock_id)
+ while ((cs = snd_usb_find_csint_desc(iface->extra, iface->extralen,
+ cs, type))) {
+ if (validator(cs, id))
return cs;
}
return NULL;
}
-static struct uac3_clock_source_descriptor *
- snd_usb_find_clock_source_v3(struct usb_host_interface *ctrl_iface,
- int clock_id)
+static bool validate_clock_source_v2(void *p, int id)
{
- struct uac3_clock_source_descriptor *cs = NULL;
-
- while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
- ctrl_iface->extralen,
- cs, UAC3_CLOCK_SOURCE))) {
- if (cs->bClockID == clock_id)
- return cs;
- }
-
- return NULL;
+ struct uac_clock_source_descriptor *cs = p;
+ return cs->bLength == sizeof(*cs) && cs->bClockID == id;
}
-static struct uac_clock_selector_descriptor *
- snd_usb_find_clock_selector(struct usb_host_interface *ctrl_iface,
- int clock_id)
+static bool validate_clock_source_v3(void *p, int id)
{
- struct uac_clock_selector_descriptor *cs = NULL;
-
- while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
- ctrl_iface->extralen,
- cs, UAC2_CLOCK_SELECTOR))) {
- if (cs->bLength >= sizeof(*cs) && cs->bClockID == clock_id) {
- if (cs->bLength < 5 + cs->bNrInPins)
- return NULL;
- return cs;
- }
- }
-
- return NULL;
+ struct uac3_clock_source_descriptor *cs = p;
+ return cs->bLength == sizeof(*cs) && cs->bClockID == id;
}
-static struct uac3_clock_selector_descriptor *
- snd_usb_find_clock_selector_v3(struct usb_host_interface *ctrl_iface,
- int clock_id)
+static bool validate_clock_selector_v2(void *p, int id)
{
- struct uac3_clock_selector_descriptor *cs = NULL;
-
- while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
- ctrl_iface->extralen,
- cs, UAC3_CLOCK_SELECTOR))) {
- if (cs->bClockID == clock_id)
- return cs;
- }
-
- return NULL;
+ struct uac_clock_selector_descriptor *cs = p;
+ return cs->bLength >= sizeof(*cs) && cs->bClockID == id &&
+ cs->bLength == 7 + cs->bNrInPins;
}
-static struct uac_clock_multiplier_descriptor *
- snd_usb_find_clock_multiplier(struct usb_host_interface *ctrl_iface,
- int clock_id)
+static bool validate_clock_selector_v3(void *p, int id)
{
- struct uac_clock_multiplier_descriptor *cs = NULL;
-
- while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
- ctrl_iface->extralen,
- cs, UAC2_CLOCK_MULTIPLIER))) {
- if (cs->bLength >= sizeof(*cs) && cs->bClockID == clock_id)
- return cs;
- }
-
- return NULL;
+ struct uac3_clock_selector_descriptor *cs = p;
+ return cs->bLength >= sizeof(*cs) && cs->bClockID == id &&
+ cs->bLength == 11 + cs->bNrInPins;
}
-static struct uac3_clock_multiplier_descriptor *
- snd_usb_find_clock_multiplier_v3(struct usb_host_interface *ctrl_iface,
- int clock_id)
+static bool validate_clock_multiplier_v2(void *p, int id)
{
- struct uac3_clock_multiplier_descriptor *cs = NULL;
+ struct uac_clock_multiplier_descriptor *cs = p;
+ return cs->bLength == sizeof(*cs) && cs->bClockID == id;
+}
- while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
- ctrl_iface->extralen,
- cs, UAC3_CLOCK_MULTIPLIER))) {
- if (cs->bClockID == clock_id)
- return cs;
- }
+static bool validate_clock_multiplier_v3(void *p, int id)
+{
+ struct uac3_clock_multiplier_descriptor *cs = p;
+ return cs->bLength == sizeof(*cs) && cs->bClockID == id;
+}
- return NULL;
+#define DEFINE_FIND_HELPER(name, obj, validator, type) \
+static obj *name(struct usb_host_interface *iface, int id) \
+{ \
+ return find_uac_clock_desc(iface, id, validator, type); \
}
+DEFINE_FIND_HELPER(snd_usb_find_clock_source,
+ struct uac_clock_source_descriptor,
+ validate_clock_source_v2, UAC2_CLOCK_SOURCE);
+DEFINE_FIND_HELPER(snd_usb_find_clock_source_v3,
+ struct uac3_clock_source_descriptor,
+ validate_clock_source_v3, UAC3_CLOCK_SOURCE);
+
+DEFINE_FIND_HELPER(snd_usb_find_clock_selector,
+ struct uac_clock_selector_descriptor,
+ validate_clock_selector_v2, UAC2_CLOCK_SELECTOR);
+DEFINE_FIND_HELPER(snd_usb_find_clock_selector_v3,
+ struct uac3_clock_selector_descriptor,
+ validate_clock_selector_v3, UAC3_CLOCK_SELECTOR);
+
+DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier,
+ struct uac_clock_multiplier_descriptor,
+ validate_clock_multiplier_v2, UAC2_CLOCK_MULTIPLIER);
+DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier_v3,
+ struct uac3_clock_multiplier_descriptor,
+ validate_clock_multiplier_v3, UAC3_CLOCK_MULTIPLIER);
+
static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
{
unsigned char buf;