Skip to content

Commit 297224f

Browse files
committed
ALSA: seq: oss: Fix racy open/close of MIDI devices
Although snd_seq_oss_midi_open() and snd_seq_oss_midi_close() can be called concurrently from different code paths, we have no proper data protection against races. Introduce open_mutex to each seq_oss_midi object for avoiding the races. Reported-by: "Gong, Sishuai" <[email protected]> Closes: https://lore.kernel.org/r/[email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent a2a8714 commit 297224f

File tree

1 file changed

+22
-13
lines changed

1 file changed

+22
-13
lines changed

sound/core/seq/oss/seq_oss_midi.c

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct seq_oss_midi {
3737
struct snd_midi_event *coder; /* MIDI event coder */
3838
struct seq_oss_devinfo *devinfo; /* assigned OSSseq device */
3939
snd_use_lock_t use_lock;
40+
struct mutex open_mutex;
4041
};
4142

4243

@@ -172,6 +173,7 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
172173
mdev->flags = pinfo->capability;
173174
mdev->opened = 0;
174175
snd_use_lock_init(&mdev->use_lock);
176+
mutex_init(&mdev->open_mutex);
175177

176178
/* copy and truncate the name of synth device */
177179
strscpy(mdev->name, pinfo->name, sizeof(mdev->name));
@@ -322,15 +324,17 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
322324
int perm;
323325
struct seq_oss_midi *mdev;
324326
struct snd_seq_port_subscribe subs;
327+
int err;
325328

326329
mdev = get_mididev(dp, dev);
327330
if (!mdev)
328331
return -ENODEV;
329332

333+
mutex_lock(&mdev->open_mutex);
330334
/* already used? */
331335
if (mdev->opened && mdev->devinfo != dp) {
332-
snd_use_lock_free(&mdev->use_lock);
333-
return -EBUSY;
336+
err = -EBUSY;
337+
goto unlock;
334338
}
335339

336340
perm = 0;
@@ -340,14 +344,14 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
340344
perm |= PERM_READ;
341345
perm &= mdev->flags;
342346
if (perm == 0) {
343-
snd_use_lock_free(&mdev->use_lock);
344-
return -ENXIO;
347+
err = -ENXIO;
348+
goto unlock;
345349
}
346350

347351
/* already opened? */
348352
if ((mdev->opened & perm) == perm) {
349-
snd_use_lock_free(&mdev->use_lock);
350-
return 0;
353+
err = 0;
354+
goto unlock;
351355
}
352356

353357
perm &= ~mdev->opened;
@@ -372,13 +376,17 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
372376
}
373377

374378
if (! mdev->opened) {
375-
snd_use_lock_free(&mdev->use_lock);
376-
return -ENXIO;
379+
err = -ENXIO;
380+
goto unlock;
377381
}
378382

379383
mdev->devinfo = dp;
384+
err = 0;
385+
386+
unlock:
387+
mutex_unlock(&mdev->open_mutex);
380388
snd_use_lock_free(&mdev->use_lock);
381-
return 0;
389+
return err;
382390
}
383391

384392
/*
@@ -393,10 +401,9 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
393401
mdev = get_mididev(dp, dev);
394402
if (!mdev)
395403
return -ENODEV;
396-
if (! mdev->opened || mdev->devinfo != dp) {
397-
snd_use_lock_free(&mdev->use_lock);
398-
return 0;
399-
}
404+
mutex_lock(&mdev->open_mutex);
405+
if (!mdev->opened || mdev->devinfo != dp)
406+
goto unlock;
400407

401408
memset(&subs, 0, sizeof(subs));
402409
if (mdev->opened & PERM_WRITE) {
@@ -415,6 +422,8 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
415422
mdev->opened = 0;
416423
mdev->devinfo = NULL;
417424

425+
unlock:
426+
mutex_unlock(&mdev->open_mutex);
418427
snd_use_lock_free(&mdev->use_lock);
419428
return 0;
420429
}

0 commit comments

Comments
 (0)