Skip to content

Commit 04b2d9c

Browse files
takaswietiwai
authored andcommitted
ALSA: firewire-tascam: accessing to user space outside spinlock
In hwdep interface of firewire-tascam driver, accessing to user space is in a critical section with disabled local interrupt. Depending on architecture, accessing to user space can cause page fault exception. Then local processor stores machine status and handle the synchronous event. A handler corresponding to the event can call task scheduler to wait for preparing pages. In a case of usage of single core processor, the state to disable local interrupt is worse because it doesn't handle usual interrupts from hardware. This commit fixes this bug, by performing the accessing outside spinlock. Reported-by: Vaishali Thakkar <[email protected]> Cc: [email protected] Fixes: e5e0c3d('ALSA: firewire-tascam: add hwdep interface') Signed-off-by: Takashi Sakamoto <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent fd06c77 commit 04b2d9c

File tree

1 file changed

+11
-22
lines changed

1 file changed

+11
-22
lines changed

sound/firewire/tascam/tascam-hwdep.c

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,14 @@
1616

1717
#include "tascam.h"
1818

19-
static long hwdep_read_locked(struct snd_tscm *tscm, char __user *buf,
20-
long count)
21-
{
22-
union snd_firewire_event event;
23-
24-
memset(&event, 0, sizeof(event));
25-
26-
event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
27-
event.lock_status.status = (tscm->dev_lock_count > 0);
28-
tscm->dev_lock_changed = false;
29-
30-
count = min_t(long, count, sizeof(event.lock_status));
31-
32-
if (copy_to_user(buf, &event, count))
33-
return -EFAULT;
34-
35-
return count;
36-
}
37-
3819
static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
3920
loff_t *offset)
4021
{
4122
struct snd_tscm *tscm = hwdep->private_data;
4223
DEFINE_WAIT(wait);
43-
union snd_firewire_event event;
24+
union snd_firewire_event event = {
25+
.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS,
26+
};
4427

4528
spin_lock_irq(&tscm->lock);
4629

@@ -54,10 +37,16 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
5437
spin_lock_irq(&tscm->lock);
5538
}
5639

57-
memset(&event, 0, sizeof(event));
58-
count = hwdep_read_locked(tscm, buf, count);
40+
event.lock_status.status = (tscm->dev_lock_count > 0);
41+
tscm->dev_lock_changed = false;
42+
5943
spin_unlock_irq(&tscm->lock);
6044

45+
count = min_t(long, count, sizeof(event.lock_status));
46+
47+
if (copy_to_user(buf, &event, count))
48+
return -EFAULT;
49+
6150
return count;
6251
}
6352

0 commit comments

Comments
 (0)