CVE-2014-4652
Protect user controls against concurrent access

CVE-2014-4653
Don't access controls outside of protected regions

Reference:
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-4652
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-4653

Signed-off-by: Sona Sarmadi <sona.sarm...@enea.com>
---
 .../linux/files/0001-ALSA-CVE-2014-4652.patch      | 140 +++++++++++++++++++++
 .../linux/files/0002-ALSA-CVE-2014-4653.patch      |  92 ++++++++++++++
 recipes-kernel/linux/linux-qoriq_3.12.bb           |   2 +
 3 files changed, 234 insertions(+)
 create mode 100644 recipes-kernel/linux/files/0001-ALSA-CVE-2014-4652.patch
 create mode 100644 recipes-kernel/linux/files/0002-ALSA-CVE-2014-4653.patch

diff --git a/recipes-kernel/linux/files/0001-ALSA-CVE-2014-4652.patch 
b/recipes-kernel/linux/files/0001-ALSA-CVE-2014-4652.patch
new file mode 100644
index 0000000..0130768
--- /dev/null
+++ b/recipes-kernel/linux/files/0001-ALSA-CVE-2014-4652.patch
@@ -0,0 +1,140 @@
+From ed81e6b21790b717cda5f5bab2bdb07d2ce17ab1 Mon Sep 17 00:00:00 2001
+From: Lars-Peter Clausen <l...@metafoo.de>
+Date: Wed, 18 Jun 2014 13:32:31 +0200
+Subject: [PATCH] ALSA: control: Protect user controls against concurrent
+ access
+
+commit 07f4d9d74a04aa7c72c5dae0ef97565f28f17b92 upstream.
+
+The user-control put and get handlers as well as the tlv do not protect against
+concurrent access from multiple threads. Since the state of the control is not
+updated atomically it is possible that either two write operations or a write
+and a read operation race against each other. Both can lead to arbitrary memory
+disclosure. This patch introduces a new lock that protects user-controls from
+concurrent access. Since applications typically access controls sequentially
+than in parallel a single lock per card should be fine.
+
+This fixes CVE-2014-4652
+Upstream-Status: Backport
+
+Signed-off-by: Lars-Peter Clausen <l...@metafoo.de>
+Acked-by: Jaroslav Kysela <pe...@perex.cz>
+Signed-off-by: Takashi Iwai <ti...@suse.de>
+Signed-off-by: Jiri Slaby <jsl...@suse.cz>
+Signed-off-by: Sona Sarmadi <sona.sarm...@enea.com>
+---
+ include/sound/core.h |  2 ++
+ sound/core/control.c | 31 +++++++++++++++++++++++++------
+ sound/core/init.c    |  1 +
+ 3 files changed, 28 insertions(+), 6 deletions(-)
+
+diff --git a/include/sound/core.h b/include/sound/core.h
+index 2a14f1f..d6bc961 100644
+--- a/include/sound/core.h
++++ b/include/sound/core.h
+@@ -121,6 +121,8 @@ struct snd_card {
+       int user_ctl_count;             /* count of all user controls */
+       struct list_head controls;      /* all controls for this card */
+       struct list_head ctl_files;     /* active control files */
++      struct mutex user_ctl_lock;     /* protects user controls against
++                                         concurrent access */
+ 
+       struct snd_info_entry *proc_root;       /* root for soundcard specific 
files */
+       struct snd_info_entry *proc_id; /* the card id */
+diff --git a/sound/core/control.c b/sound/core/control.c
+index d8aa206..183fab2 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -992,6 +992,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
+ 
+ struct user_element {
+       struct snd_ctl_elem_info info;
++      struct snd_card *card;
+       void *elem_data;                /* element data */
+       unsigned long elem_data_size;   /* size of element data in bytes */
+       void *tlv_data;                 /* TLV data */
+@@ -1035,7 +1036,9 @@ static int snd_ctl_elem_user_get(struct snd_kcontrol 
*kcontrol,
+ {
+       struct user_element *ue = kcontrol->private_data;
+ 
++      mutex_lock(&ue->card->user_ctl_lock);
+       memcpy(&ucontrol->value, ue->elem_data, ue->elem_data_size);
++      mutex_unlock(&ue->card->user_ctl_lock);
+       return 0;
+ }
+ 
+@@ -1044,10 +1047,12 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol 
*kcontrol,
+ {
+       int change;
+       struct user_element *ue = kcontrol->private_data;
+-      
++
++      mutex_lock(&ue->card->user_ctl_lock);
+       change = memcmp(&ucontrol->value, ue->elem_data, ue->elem_data_size) != 
0;
+       if (change)
+               memcpy(ue->elem_data, &ucontrol->value, ue->elem_data_size);
++      mutex_unlock(&ue->card->user_ctl_lock);
+       return change;
+ }
+ 
+@@ -1067,19 +1072,32 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol 
*kcontrol,
+               new_data = memdup_user(tlv, size);
+               if (IS_ERR(new_data))
+                       return PTR_ERR(new_data);
++              mutex_lock(&ue->card->user_ctl_lock);
+               change = ue->tlv_data_size != size;
+               if (!change)
+                       change = memcmp(ue->tlv_data, new_data, size);
+               kfree(ue->tlv_data);
+               ue->tlv_data = new_data;
+               ue->tlv_data_size = size;
++              mutex_unlock(&ue->card->user_ctl_lock);
+       } else {
+-              if (! ue->tlv_data_size || ! ue->tlv_data)
+-                      return -ENXIO;
+-              if (size < ue->tlv_data_size)
+-                      return -ENOSPC;
++              int ret = 0;
++
++              mutex_lock(&ue->card->user_ctl_lock);
++              if (!ue->tlv_data_size || !ue->tlv_data) {
++                      ret = -ENXIO;
++                      goto err_unlock;
++              }
++              if (size < ue->tlv_data_size) {
++                      ret = -ENOSPC;
++                      goto err_unlock;
++              }
+               if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size))
+-                      return -EFAULT;
++                      ret = -EFAULT;
++err_unlock:
++              mutex_unlock(&ue->card->user_ctl_lock);
++              if (ret)
++                      return ret;
+       }
+       return change;
+ }
+@@ -1211,6 +1229,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
+       ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL);
+       if (ue == NULL)
+               return -ENOMEM;
++      ue->card = card;
+       ue->info = *info;
+       ue->info.access = 0;
+       ue->elem_data = (char *)ue + sizeof(*ue);
+diff --git a/sound/core/init.c b/sound/core/init.c
+index d047851..b9268a5 100644
+--- a/sound/core/init.c
++++ b/sound/core/init.c
+@@ -215,6 +215,7 @@ int snd_card_create(int idx, const char *xid,
+       INIT_LIST_HEAD(&card->devices);
+       init_rwsem(&card->controls_rwsem);
+       rwlock_init(&card->ctl_files_rwlock);
++      mutex_init(&card->user_ctl_lock);
+       INIT_LIST_HEAD(&card->controls);
+       INIT_LIST_HEAD(&card->ctl_files);
+       spin_lock_init(&card->files_lock);
+-- 
+1.9.1
+
diff --git a/recipes-kernel/linux/files/0002-ALSA-CVE-2014-4653.patch 
b/recipes-kernel/linux/files/0002-ALSA-CVE-2014-4653.patch
new file mode 100644
index 0000000..8612d74
--- /dev/null
+++ b/recipes-kernel/linux/files/0002-ALSA-CVE-2014-4653.patch
@@ -0,0 +1,92 @@
+From 0bf595fd311aa4d6e82c43879f2c0d0650e83271 Mon Sep 17 00:00:00 2001
+From: Lars-Peter Clausen <l...@metafoo.de>
+Date: Wed, 18 Jun 2014 13:32:33 +0200
+Subject: [PATCH] ALSA: control: Don't access controls outside of protected
+ regions
+
+commit fd9f26e4eca5d08a27d12c0933fceef76ed9663d upstream.
+
+A control that is visible on the card->controls list can be freed at any time.
+This means we must not access any of its memory while not holding the
+controls_rw_lock. Otherwise we risk a use after free access.
+
+This fixes CVE-2014-4653
+Upstream-Status: Backport
+
+Signed-off-by: Lars-Peter Clausen <l...@metafoo.de>
+Acked-by: Jaroslav Kysela <pe...@perex.cz>
+Signed-off-by: Takashi Iwai <ti...@suse.de>
+Signed-off-by: Jiri Slaby <jsl...@suse.cz>
+Signed-off-by: Sona Sarmadi <sona.sarm...@enea.com>
+---
+ sound/core/control.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 15bc844..d4a597f 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -331,6 +331,7 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol 
*kcontrol)
+ {
+       struct snd_ctl_elem_id id;
+       unsigned int idx;
++      unsigned int count;
+       int err = -EINVAL;
+ 
+       if (! kcontrol)
+@@ -359,8 +360,9 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol 
*kcontrol)
+       card->controls_count += kcontrol->count;
+       kcontrol->id.numid = card->last_numid + 1;
+       card->last_numid += kcontrol->count;
++      count = kcontrol->count;
+       up_write(&card->controls_rwsem);
+-      for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
++      for (idx = 0; idx < count; idx++, id.index++, id.numid++)
+               snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
+       return 0;
+ 
+@@ -389,6 +391,7 @@ int snd_ctl_replace(struct snd_card *card, struct 
snd_kcontrol *kcontrol,
+                   bool add_on_replace)
+ {
+       struct snd_ctl_elem_id id;
++      unsigned int count;
+       unsigned int idx;
+       struct snd_kcontrol *old;
+       int ret;
+@@ -424,8 +427,9 @@ add:
+       card->controls_count += kcontrol->count;
+       kcontrol->id.numid = card->last_numid + 1;
+       card->last_numid += kcontrol->count;
++      count = kcontrol->count;
+       up_write(&card->controls_rwsem);
+-      for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
++      for (idx = 0; idx < count; idx++, id.index++, id.numid++)
+               snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
+       return 0;
+ 
+@@ -898,9 +902,9 @@ static int snd_ctl_elem_write(struct snd_card *card, 
struct snd_ctl_file *file,
+                       result = kctl->put(kctl, control);
+               }
+               if (result > 0) {
++                      struct snd_ctl_elem_id id = control->id;
+                       up_read(&card->controls_rwsem);
+-                      snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+-                                     &control->id);
++                      snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
+                       return 0;
+               }
+       }
+@@ -1334,8 +1338,9 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
+               }
+               err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
+               if (err > 0) {
++                      struct snd_ctl_elem_id id = kctl->id;
+                       up_read(&card->controls_rwsem);
+-                      snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, 
&kctl->id);
++                      snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &id);
+                       return 0;
+               }
+       } else {
+-- 
+1.9.1
+
diff --git a/recipes-kernel/linux/linux-qoriq_3.12.bb 
b/recipes-kernel/linux/linux-qoriq_3.12.bb
index bbbf4ba..90ccedd 100644
--- a/recipes-kernel/linux/linux-qoriq_3.12.bb
+++ b/recipes-kernel/linux/linux-qoriq_3.12.bb
@@ -23,6 +23,8 @@ SRC_URI = 
"git://git.freescale.com/ppc/sdk/linux.git;nobranch=1 \
     file://0002-net-sctp-CVE-2014-3687.patch \
     file://0003-net-sctp-CVE-2014-3688.patch \
     file://auditsc-CVE-2014-3917.patch \
+    file://0001-ALSA-CVE-2014-4652.patch \
+    file://0002-ALSA-CVE-2014-4653.patch \
 "
 SRCREV = "6619b8b55796cdf0cec04b66a71288edd3057229"
 
-- 
1.9.1

-- 
_______________________________________________
meta-freescale mailing list
meta-freescale@yoctoproject.org
https://lists.yoctoproject.org/listinfo/meta-freescale

Reply via email to