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