summaryrefslogtreecommitdiff
path: root/sound/core/seq/seq_clientmgr.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-04-12 12:44:39 +0200
committerTakashi Iwai <tiwai@suse.de>2019-04-12 13:07:25 +0200
commit6b580f523172f2c738b661069a57c23c74a75f88 (patch)
treed772938f0958be15c9f097fecfdccc39609c9b7b /sound/core/seq/seq_clientmgr.c
parent6740ea6776e97274627e3c261469d1c4ba0a0cb5 (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.c40
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;