FPII-2320: Elevation of privilege vulnerability in kernel USB driver CVE-2014-4655 A-29916012

The snd_ctl_elem_add function in sound/core/control.c file, in the ALSA control implementation in the Linux kernel before 3.15.2, does not properly maintain the user_ctl_count value, which allows local users to execute code in the kernel by leveraging /dev/snd/controlCX access for a large number of SNDRV_CTL_IOCTL_ELEM_REPLACE ioctl calls.
The fix is designed to use the snd_ctl_remove_user_ctl function, which does

proper permission checks and decrements user_ctl_count after the control

Change-Id: Id8ba70327eb6723d6528d2a1793d6f4e9b475d51
diff --git a/sound/core/control.c b/sound/core/control.c
index 2487a6b..f719cf4 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1130,8 +1130,6 @@
 	struct user_element *ue;
 	int idx, err;
 
-	if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS)
-		return -ENOMEM;
 	if (info->count < 1)
 		return -EINVAL;
 	access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
@@ -1140,21 +1138,15 @@
 				 SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE));
 	info->id.numid = 0;
 	memset(&kctl, 0, sizeof(kctl));
-	down_write(&card->controls_rwsem);
-	_kctl = snd_ctl_find_id(card, &info->id);
-	err = 0;
-	if (_kctl) {
-		if (replace)
-			err = snd_ctl_remove(card, _kctl);
-		else
-			err = -EBUSY;
-	} else {
-		if (replace)
-			err = -ENOENT;
+	if (replace) {
+    err = snd_ctl_remove_user_ctl(file, &info->id);
+        if (err)
+            return err;
 	}
-	up_write(&card->controls_rwsem);
-	if (err < 0)
-		return err;
+
+    if (card->user_ctl_count >= MAX_USER_CONTROLS)
+        return -ENOMEM;
+
 	memcpy(&kctl.id, &info->id, sizeof(info->id));
 	kctl.count = info->owner ? info->owner : 1;
 	access |= SNDRV_CTL_ELEM_ACCESS_USER;