Skip to content

Commit 81c254a

Browse files
error27tiwai
authored andcommitted
ALSA: fireface: fix locking bug in ff400_copy_msg_to_user()
The ff400_copy_msg_to_user() function drops the spin lock to call copy_to_user(). However, if the copy_to_user() fails, then it must take the lock again before returning. Failure to take the lock leads to a double unlock in the caller, hwdep_read(). Fixes: acdebd8 ("ALSA: fireface: implement message parser for Fireface 400") Signed-off-by: Dan Carpenter <[email protected]> Acked-by: Takashi Sakamoto <[email protected]> Link: https://lore.kernel.org/r/Y8at+W/7OGvEBY8O@kili Signed-off-by: Takashi Iwai <[email protected]>
1 parent 3ee0fe7 commit 81c254a

File tree

1 file changed

+8
-6
lines changed

1 file changed

+8
-6
lines changed

sound/firewire/fireface/ff-protocol-former.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -680,28 +680,30 @@ static long ff400_copy_msg_to_user(struct snd_ff *ff, char __user *buf, long cou
680680
struct ff400_msg_parser *parser = ff->msg_parser;
681681
u32 type = SNDRV_FIREWIRE_EVENT_FF400_MESSAGE;
682682
long consumed = 0;
683+
int ret = 0;
683684

684685
if (count < 8)
685686
return 0;
686687

687688
spin_unlock_irq(&ff->lock);
688-
689689
if (copy_to_user(buf, &type, sizeof(type)))
690-
return -EFAULT;
691-
690+
ret = -EFAULT;
692691
spin_lock_irq(&ff->lock);
692+
if (ret)
693+
return ret;
693694

694695
count -= sizeof(type);
695696
consumed += sizeof(type);
696697

697698
while (count >= sizeof(*parser->msgs) && parser->pull_pos != parser->push_pos) {
698699
spin_unlock_irq(&ff->lock);
699-
700700
if (copy_to_user(buf + consumed, parser->msgs + parser->pull_pos,
701701
sizeof(*parser->msgs)))
702-
return -EFAULT;
703-
702+
ret = -EFAULT;
704703
spin_lock_irq(&ff->lock);
704+
if (ret)
705+
return ret;
706+
705707
++parser->pull_pos;
706708
if (parser->pull_pos >= FF400_QUEUE_SIZE)
707709
parser->pull_pos = 0;

0 commit comments

Comments
 (0)