--- /dev/null
+From b3defb791b26ea0683a93a4f49c77ec45ec96f10 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 9 Jan 2018 23:11:03 +0100
+Subject: ALSA: seq: Make ioctls race-free
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit b3defb791b26ea0683a93a4f49c77ec45ec96f10 upstream.
+
+The ALSA sequencer ioctls have no protection against racy calls while
+the concurrent operations may lead to interfere with each other. As
+reported recently, for example, the concurrent calls of setting client
+pool with a combination of write calls may lead to either the
+unkillable dead-lock or UAF.
+
+As a slightly big hammer solution, this patch introduces the mutex to
+make each ioctl exclusive. Although this may reduce performance via
+parallel ioctl calls, usually it's not demanded for sequencer usages,
+hence it should be negligible.
+
+Reported-by: Luo Quan <a4651386@163.com>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+[bwh: Backported to 4.4: ioctl dispatch is done from snd_seq_do_ioctl();
+ take the mutex and add ret variable there.]
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/seq/seq_clientmgr.c | 10 ++++++++--
+ sound/core/seq/seq_clientmgr.h | 1 +
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+--- a/sound/core/seq/seq_clientmgr.c
++++ b/sound/core/seq/seq_clientmgr.c
+@@ -236,6 +236,7 @@ static struct snd_seq_client *seq_create
+ rwlock_init(&client->ports_lock);
+ mutex_init(&client->ports_mutex);
+ INIT_LIST_HEAD(&client->ports_list_head);
++ mutex_init(&client->ioctl_mutex);
+
+ /* find free slot in the client table */
+ spin_lock_irqsave(&clients_lock, flags);
+@@ -2200,6 +2201,7 @@ static int snd_seq_do_ioctl(struct snd_s
+ void __user *arg)
+ {
+ struct seq_ioctl_table *p;
++ int ret;
+
+ switch (cmd) {
+ case SNDRV_SEQ_IOCTL_PVERSION:
+@@ -2213,8 +2215,12 @@ static int snd_seq_do_ioctl(struct snd_s
+ if (! arg)
+ return -EFAULT;
+ for (p = ioctl_tables; p->cmd; p++) {
+- if (p->cmd == cmd)
+- return p->func(client, arg);
++ if (p->cmd == cmd) {
++ mutex_lock(&client->ioctl_mutex);
++ ret = p->func(client, arg);
++ mutex_unlock(&client->ioctl_mutex);
++ return ret;
++ }
+ }
+ pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
+--- a/sound/core/seq/seq_clientmgr.h
++++ b/sound/core/seq/seq_clientmgr.h
+@@ -59,6 +59,7 @@ struct snd_seq_client {
+ struct list_head ports_list_head;
+ rwlock_t ports_lock;
+ struct mutex ports_mutex;
++ struct mutex ioctl_mutex;
+ int convert32; /* convert 32->64bit */
+
+ /* output pool */