Summary
CVE | CVE-2014-1739 |
---|---|
Author | Salva Peiró |
Date | April 2014 - Discovery of the vulnerability. |
Impact | The vulnerability discloses 200 bytes of kernel process stack. |
Affected Versions | From linux-2.6.38 to linux-3.15-rc3 |
Bug Timespan | 3 years: 2011-03-23 to 2014-04-29 commit 1651333b |
Description
During a code review of the kernel sources we found an infoleak vulnerability in the
ioctl media_enum_entities()
that allows to disclose 200 bytes the kernel process' stack.
The vulnerability is exploitable on versions up to linux-3.15-rc3
by local
users with read access to /dev/media0
.
Linux distributions ship with chmod 600 /dev/media0
preventing unprivileged
local users from exploiting the vulnerability. However, some Android devices
are known to be shipped with both read and/or
write permissions for all: chmod 666 /dev/media0.
Impact
The vulnerability was introduced in linux-2.6.38
and has been fixed in
linux-3.15-rc3
, therefore, all kernel versions in between are affected.
The kernel subsystem affected is the media device
that provides the enumeration of media devices such as: V4L
, ALSA
, DBV
, and FB
.
Vulnerability
The vulnerability leaks the contents of the kernel process stack through the
reserved
and raw
fields of the struct media_entity_desc uent;
.
The cause of the infoleak is the missing initialisation of the struct media_device_entity; uent
before being copied to userland.
This causes 200 bytes of kernel process' stack to be disclosed to userland.
Proof of Concept code
The PoC code media-enum-poc.c
triggers the vulnerability by issuing the ioctl(fd, MEDIA_IOC_ENUM_ENTITIES)
request and checking the data returned.
box $ ./media-enum-poc /dev/media0 [*] CVE-2014-1739: Infoleak PoC in media_device_enum_entities() leaking 200 kstack bytes: 00000000: 0x00001000 0xc104d114 0x00010000 0xf6744514 00000004: 0x00000051 0x00000000 0x00000000 0xc1420b91 00000008: 0xf2e31dc8 0xc12fe9be 0xf86ddab0 0xf6744514 00000012: 0xf29cc140 0xf2e31dc8 0x00000000 0xc115086d 00000016: 0x00000000 0xf29cc140 0xf6744514 0xf29cc148 00000020: 0x00000000 0xc114a77a 0xc11f2581 0x00000002 00000024: 0xf6744514 0xf3ea7690 0xf29cc440 0x000000cf 00000028: 0xf3ea7760 0xc10fcb11 0xc116680d 0x00000000 00000032: 0xf5929d50 0xf3ea7690 0xf29cc440 0xf3ea775c 00000036: 0xf6f92960 0xc10fe4bb 0x00000081 0x00ffffff 00000040: 0x00000000 0x000000a8 0x000000cf 0xe8defeb8 00000044: 0xf5929d40 0xc104d2d4 0x0000003c 0xfffff000 00000048: 0x00000001 0xc104d114
The Vulnerability Fix
After verification the patch that memsets(0)
the whole struct media_device_entity uent;
has been submitted to the kernel:
[PATCH] drivers/media: Fix infoleak in ioctl media_enum_entities()
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index d5a7a13..703560f 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -93,6 +93,7 @@ static long media_device_enum_entities(struct media_device *mdev, struct media_entity *ent; struct media_entity_desc u_ent; + memset(&u_ent, 0, sizeof(u_ent)); if (copy_from_user(&u_ent.id, &uent->id, sizeof(u_ent.id))) return -EFAULT;
File: 0001-drivers-media-Fix-infoleak-in-ioctl-media_enum_entit.patch
Update
After looking at the code fixing the infoleak one notices that
that when a ent->name
is provided u_ent.name
is memset(0) twice;
first at the global memset() of the u_ent
and afterwards at u_ent.name
.
The next patch addresses this issue by removing the memset(u_ent.name, 0, ...)
.
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 703560f..3729d63 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -105,9 +105,6 @@ static long media_device_enum_entities(struct media_device *mdev, u_ent.id = ent->id; if (ent->name) { strncpy(u_ent.name, ent->name, sizeof(u_ent.name)); u_ent.name[sizeof(u_ent.name) - 1] = '\0'; - } else { - memset(u_ent.name, 0, sizeof(u_ent.name)); } u_ent.type = ent->type; u_ent.revision = ent->revision;
File: 0001-media-device-Remove-duplicated-memset-in-media_enum_.patch