Nexus 5X
Nexus 6P
Nexus 9
Android One
Pixel
Pixel XL
Verified on Nexus 9 6.0.1/MOB30W, 7.0/NRD90M, 7.0/NRD90R
Apply the December 2016 Android Security Patches.
Due to lenient SELinux and DAC policy, vulnerable Synaptics DSX (touchscreen driver) sysfs file entires are exposed to an attacker that executes code within the mediaserver context on Android M 6.0.1 and system_server, bluetooth, nfc contexts on Android N 7.0 (or any other SELinux domain that has target type sysfs with the open and write permissions on file class).
The vulnerability has been found in the synaptics_dsx_fw_update.c.
On module initialization, a fixed-size heap buffer is created:
static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
{
[...]
fwu->image_name = kzalloc(MAX_IMAGE_NAME_LEN, GFP_KERNEL);
if (!fwu->image_name) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to alloc mem for image name\n",
__func__);
retval = -ENOMEM;
goto exit_free_fwu;
}
[...]
}
where MAX_IMAGE_NAME_LEN equals 256. fwu->imagename can be controlled from userspace by the write syscall – see CVE-2016-8394. But, in fwu_go_nogo() (a function that is called within the flashing firmware flow), on certain conditions (header->contains_firmware_id=0), the attacker copy most of the contents of fwu->image_name to a heap allocated buffer of size 10 (MAX_FIRMWARE_ID_LEN=10), causing a heap overrun:
static enum flash_area fwu_go_nogo(struct image_header_data *header)
{
[...]
char *strptr;
char *firmware_id;
[...]
/* Get image firmware ID */
if (header->contains_firmware_id) {
image_fw_id = header->firmware_id;
} else {
strptr = strstr(fwu->image_name, "PR");
if (!strptr) {
[...]
goto exit;
}
strptr += 2;
firmware_id = kzalloc(MAX_FIRMWARE_ID_LEN, GFP_KERNEL);
while (strptr[index] >= '0' && strptr[index] <= '9') {
firmware_id[index] = strptr[index];
index++;
}
[...]
}