Date: Tue, 24 Jun 2014 14:03:47 +0200 From: Marcus Meissner <meissner@...e.de> To: OSS Security List <oss-security@...ts.openwall.com> Cc: lars@...afoo.de Subject: Re: CVE Request: Linux kernel ALSA core control API vulnerabilities Hi, The mail that was send by Lars-Peter to the ALSA developers. Takashi Tiwai gave approval to forward it here. Ciao, Marcus ------------------------------------------------------------------- Subject: [PATCH 0/5] Use-after-free and out-of-bounds acccess vulnerabilities in the ALSA control code From: Lars-Peter Clausen <lars@...afoo.de> Hi, A couple of use-after-free and out-of-bounds memory accesses which can be triggered by race conditions have been discovered in the ALSA control handling code. These vulnerabilities allow users that have access to a ALSA control character device (/dev/snd/controlCX) to disclose memory and potentially allow for arbitrary code execution. On a typical Linux system these are the users that are in the audio group. This patch series fixes the issues and the patches are ordered by severity of the issue. The first issue is a race conditions in the user-control put/get and tlv handlers, which can cause the write callback to race against the read callback. For put/get this is pretty harmless as the only effect is that the reader will see a inconsistent state. The tlv callback is pretty bad though as it allows disclosure of kernel memory that is adjacent to the memory region where the tlv data is stored. The issue is essentially a race between ue->tlv_data = new_data; ue->tlv_data_size = size; and copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size) If tlv_data has already been updated to the new data, but size has not and the new data is smaller than the older data, copy_to_user() will read beyond the boundaries of the buffer. This allows to dump almost 128k bytes per race. The race seems to be fairly easy to trigger, the more cores the system has the easier. The data that has been dumped this way can contain all kind of sensitive data. Inital tests show that it is possible to disclose multiple hundreds of MB of memory within a few minutes. There are a couple of places where a kcontrol is de-referenced after controls_rwsem has been released. This can cause a use-after-free access as a control can be freed at any time. To avoid this the patch makes a on-stack copy of the relevant data before releasing the lock and then works with the copy. This race condition is very hard to hit though, since the data is only accessed for a very short amount of time after the lock has been released and to exploit the issue the control needs to be freed in that time and the memory needs to be re-allocated and assigned some other unrelated data. But it is possible to make it much easier to exploit by subscribing to the control events, but never read a event. This will create a rather long list which takes snd_ctl_notify() a while to process before it access the already freed data. This vulnerability allows to disclose a few bytes of kernel memory per triggered race condition The next issue is that SNDRV_CTL_IOCTL_ELEM_REPLACE does no permission checking on the control that is to be replaced. This allows a application to remove controls that were created by the kernel driver and also controls that are locked by other applications. The first can cause use-after-free access if the kernel driver keeps a pointer to the control and does not expect it to be freed (e.g. the ctrljack code). The later is just a bit of an inconvenience. SNDRV_CTL_IOCTL_ELEM_REPLACE also gets the user_ctl_count handling wrong. The MAX_USER_CONTROLS limit is not enforced when replacing a control, but user_ctl_count is still increment even though the number of controls stays the same. This means calling SNDRV_CTL_IOCTL_ELEM_REPLACE often enough will eventually overflow user_ctl_count, effectively bypassing the MAX_USER_CONTROLS limit. The last two issues are overflows of id.index and id.numid. The control code assumes that kctl->id.index + kctl->count and kctl->id.numid + kctl->count never overflow. If it happens this creates a controls that becomes inaccessible since snd_ctl_find_id() will not be able to find them. It will still show up in SNDRV_CTL_IOCTL_ELEM_LIST though. The index overflow is easy to create since the index can be freely chosen by the creator of the control. The numid overflow is a bit harder to trigger since the numid is automatically assigned. But by creating and removing enough controls it is also possible to overflow numid. I've created small prove of concept applications that show the issues.  * alsa-memory-dump.c will exploit the memory disclosure issue and write all data it is able to access to stdout. It is best to redirect stdout to a file to test this. For successful triggering of the race you may have to adjust the number of reader threads that are created to the number of CPUs you have in your system. * alsa-owner-bypass.c will create a control for one fd and try to delete it from another fd. It does not show how to delete kernel driver controls as that might crash the system, but the method for doing so is the same * alsa-index-overflow.c tries to create controls that overflow the index field * alsa-numid-overflow.c will create controls until numid overflows. If you want to test this and not want to wait forever it is best to patch the kernel to the initial value for last_numid to something like UINT_MAX - 10000. There is no example for the second issue as it is, as I said, very hard to trigger and only discloses a few bytes of memory per triggered race condition. The TLV issue was added in commit 8aa9b586e420("[ALSA] Control API - more robust TLV implementation") for which the first affected release is v2.6.18. Everything else seems to predate the git history, so v2.6.12 or earlier. - Lars  http://metafoo.de/alsa-vuln-poc.tar.bz2 Lars-Peter Clausen (5): ALSA: control: Protect user controls against concurrent access ALSA: control: Fix replacing user controls ALSA: control: Don't access controls outside of protected regions ALSA: control: Handle numid overflow ALSA: control: Make sure that id->index does not overflow include/sound/core.h | 2 ++ sound/core/control.c | 78 ++++++++++++++++++++++++++++++++++------------------ sound/core/init.c | 1 + 3 files changed, 54 insertions(+), 27 deletions(-) Ciao, Marcus
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.