diff options
author | Takashi Iwai <tiwai@suse.de> | 2019-04-12 12:44:39 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2019-04-12 13:07:25 +0200 |
commit | 6b580f523172f2c738b661069a57c23c74a75f88 (patch) | |
tree | d772938f0958be15c9f097fecfdccc39609c9b7b /sound/core/seq/seq_clientmgr.c | |
parent | 6740ea6776e97274627e3c261469d1c4ba0a0cb5 (diff) |
ALSA: seq: Protect racy pool manipulation from OSS sequencer
OSS sequencer emulation still allows to queue and issue the events
that manipulate the client pool concurrently in a racy way. This
patch serializes the access like the normal sequencer write / ioctl
via taking the client ioctl_mutex. Since the access to the sequencer
client is done indirectly via a client id number, a new helper to
take/release the mutex is introduced.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/seq/seq_clientmgr.c')
-rw-r--r-- | sound/core/seq/seq_clientmgr.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 0af5b1440b33..a5c9d59eb5b8 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -179,6 +179,36 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid) return client; } +/* Take refcount and perform ioctl_mutex lock on the given client; + * used only for OSS sequencer + * Unlock via snd_seq_client_ioctl_unlock() below + */ +bool snd_seq_client_ioctl_lock(int clientid) +{ + struct snd_seq_client *client; + + client = snd_seq_client_use_ptr(clientid); + if (!client) + return false; + mutex_lock(&client->ioctl_mutex); + return true; +} +EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_lock); + +/* Unlock and unref the given client; for OSS sequencer use only */ +void snd_seq_client_ioctl_unlock(int clientid) +{ + struct snd_seq_client *client; + + client = snd_seq_client_use_ptr(clientid); + if (WARN_ON(!client)) + return; + mutex_unlock(&client->ioctl_mutex); + snd_use_lock_free(&client->use_lock); + snd_seq_client_unlock(client); +} +EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_unlock); + static void usage_alloc(struct snd_seq_usage *res, int num) { res->cur += num; @@ -2247,11 +2277,15 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev, if (cptr == NULL) return -EINVAL; - if (! cptr->accept_output) + if (!cptr->accept_output) { result = -EPERM; - else /* send it */ + } else { /* send it */ + mutex_lock(&cptr->ioctl_mutex); result = snd_seq_client_enqueue_event(cptr, ev, file, blocking, - false, 0, NULL); + false, 0, + &cptr->ioctl_mutex); + mutex_unlock(&cptr->ioctl_mutex); + } snd_seq_client_unlock(cptr); return result; |