forked from Minki/linux
sound fixes for 4.17-rc1
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. -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAlrLiZ4OHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE8YshAAr0j8P7eUfHs6laTZhYaTzFmGBHpabL1rIw1U QvcqbGDXAACSELud+wQe91nML2vKsv8LE18aCRqjA5ZSY5beHa0wXurAyQdxx4tb LPZVUEUTeh1Vs1SCrVE4ZHtMZPcDiOVsm3Y4YfMcg3bqyNXTGDyVk7Co+p4dzGA0 XU4z/K93aXPWEG8zomYNdbyiubxz7Kwuo0gVGSuRNarNDLKZS0cdOoiYCvA7vits HVTG5O/GOxFmKTYnrxByKclFkVH5PhUylIdvDwecxyIOVM6tmKwjCRG0q8DGi1ic QKxjbnDvbMkJBj1N9aFJ4QbgVKFhZP4DJil9T874OjscWnzXc/9z1EKlNbHWdYH+ mQNtN94Z0YK0jFPdJZf/WePIcyb7XeTAmhKY8cNhkO12bcfzQbcef9I3dsISMCc3 o0z6RQdc9KWuawXvLNIYh+/O4seWXNG026qZhZcFRpoIQ4HhaJxxsSPz7aZE47ha AmLRUiwmv0aDHgvGgnBQuwqa2qi0tre/OyW8ciiN9uY+hAC+P7mnD/wdEBYoSPqP 0i1zFe/ikxbJXL4vg7+SXTN6pZ8l2ZRQrldXmxEB7mf7WWBM3JoDH4QBRILkobA0 qc+0NF3oxpQFOJjwefeRr3dwaRvIrqYt2agY5UwvxhNYQmiIbwgBz8VsUMK1CYNZ 95u57q8= =3GP4 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
7aa1cf254c
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
|
||||
ctrl_iface->extralen,
|
||||
cs, UAC3_CLOCK_MULTIPLIER))) {
|
||||
if (cs->bClockID == clock_id)
|
||||
return cs;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
struct uac_clock_multiplier_descriptor *cs = p;
|
||||
return cs->bLength == sizeof(*cs) && cs->bClockID == id;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#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;
|
||||
|
Loading…
Reference in New Issue
Block a user