Skip to content

Commit b088b53

Browse files
committed
ALSA: aloop: Fix inconsistent format due to incomplete rule
The extra hw constraint rule for the formats the aloop driver introduced has a slight flaw, where it doesn't return a positive value when the mask got changed. It came from the fact that it's basically a copy&paste from snd_hw_constraint_mask64(). The original code is supposed to be a single-shot and it modifies the mask bits only once and never after, while what we need for aloop is the dynamic hw rule that limits the mask bits. This difference results in the inconsistent state, as the hw_refine doesn't apply the dependencies fully. The worse and surprisingly result is that it causes a crash in OSS emulation when multiple full-duplex reads/writes are performed concurrently (I leave why it triggers Oops to readers as a homework). For fixing this, replace a few open-codes with the standard snd_mask_*() macros. Reported-by: [email protected] Fixes: b1c73fc ("ALSA: snd-aloop: Fix hw_params restrictions and checking") Cc: <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent 9685347 commit b088b53

File tree

1 file changed

+6
-7
lines changed

1 file changed

+6
-7
lines changed

sound/drivers/aloop.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <sound/core.h>
4040
#include <sound/control.h>
4141
#include <sound/pcm.h>
42+
#include <sound/pcm_params.h>
4243
#include <sound/info.h>
4344
#include <sound/initval.h>
4445

@@ -622,14 +623,12 @@ static int rule_format(struct snd_pcm_hw_params *params,
622623
{
623624

624625
struct snd_pcm_hardware *hw = rule->private;
625-
struct snd_mask *maskp = hw_param_mask(params, rule->var);
626+
struct snd_mask m;
626627

627-
maskp->bits[0] &= (u_int32_t)hw->formats;
628-
maskp->bits[1] &= (u_int32_t)(hw->formats >> 32);
629-
memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */
630-
if (! maskp->bits[0] && ! maskp->bits[1])
631-
return -EINVAL;
632-
return 0;
628+
snd_mask_none(&m);
629+
m.bits[0] = (u_int32_t)hw->formats;
630+
m.bits[1] = (u_int32_t)(hw->formats >> 32);
631+
return snd_mask_refine(hw_param_mask(params, rule->var), &m);
633632
}
634633

635634
static int rule_rate(struct snd_pcm_hw_params *params,

0 commit comments

Comments
 (0)