diff options
author | yang-cy.chen <yang-cy.chen@mediatek.com> | 2015-10-30 15:42:59 +0800 |
---|---|---|
committer | Jin Qian <jinqian@google.com> | 2015-11-02 19:36:45 +0000 |
commit | f029d0d424d327535f5c4f8a2af1c8e26a48adb3 (patch) | |
tree | aa1c59d1c61265831742330f176efa03f6f8da3e | |
parent | 98a2f202c1ca10ce981a2e87be73b5bd7dd11540 (diff) | |
download | mediatek-f029d0d424d327535f5c4f8a2af1c8e26a48adb3.tar.gz |
mediatek:fix "Kernel vulnerability in /dev/misc-sd" issueandroid-6.0.1_r0.16
Problem:
Security vulnerability in /dev/misc-sd, and someone
can use invalid value through ioctl to get root.
Solution:
Add boundary protection
Bug num:25323711
Change-Id: I3cb499da51ddacf9f6c7073473ff1d80c0428ffc
Signed-off-by: yang-cy.chen <yang-cy.chen@mediatek.com>
(cherry picked from commit 3342bf8ec543ad2df2f32a8eadd03c39ba9c859d)
-rw-r--r-- | drivers/misc/mediatek/mmc-host/mt6582/mt_sd_misc.c | 115 |
1 files changed, 70 insertions, 45 deletions
diff --git a/drivers/misc/mediatek/mmc-host/mt6582/mt_sd_misc.c b/drivers/misc/mediatek/mmc-host/mt6582/mt_sd_misc.c index 4fba87af1999..454669551485 100644 --- a/drivers/misc/mediatek/mmc-host/mt6582/mt_sd_misc.c +++ b/drivers/misc/mediatek/mmc-host/mt6582/mt_sd_misc.c @@ -32,7 +32,7 @@ #include <linux/mmc/sd.h> #include <linux/mmc/sdio.h> #include <linux/dma-mapping.h> - +#include <linux/genhd.h> #include <mach/dma.h> #include <mach/board.h> /* FIXME */ #include <mach/mt_reg_base.h> @@ -143,6 +143,9 @@ static int simple_sd_ioctl_single_rw(struct msdc_ioctl* msdc_ctl) struct mmc_request msdc_mrq; struct msdc_host *host_ctl; + if(msdc_ctl->total_size <= 0) + return -EINVAL; + host_ctl = mtk_msdc_host[msdc_ctl->host_num]; BUG_ON(!host_ctl); BUG_ON(!host_ctl->mmc); @@ -260,6 +263,9 @@ static int simple_sd_ioctl_single_rw(struct msdc_ioctl* msdc_ctl) } } + /* clear the global buffer of R/W IOCTL */ + memset(sg_msdc_multi_buffer, 0 , 512); + if (msdc_ctl->partition){ mmc_send_ext_csd(host_ctl->mmc->card,l_buf); @@ -300,6 +306,9 @@ static int simple_sd_ioctl_multi_rw(struct msdc_ioctl* msdc_ctl) struct mmc_request msdc_mrq; struct msdc_host *host_ctl; + if(msdc_ctl->total_size <= 0) + return -EINVAL; + host_ctl = mtk_msdc_host[msdc_ctl->host_num]; BUG_ON(!host_ctl); BUG_ON(!host_ctl->mmc); @@ -430,6 +439,9 @@ static int simple_sd_ioctl_multi_rw(struct msdc_ioctl* msdc_ctl) } } + /* clear the global buffer of R/W IOCTL */ + memset(sg_msdc_multi_buffer, 0 , msdc_ctl->total_size); + if (msdc_ctl->partition){ mmc_send_ext_csd(host_ctl->mmc->card,l_buf); @@ -968,7 +980,7 @@ static int simple_mmc_get_disk_info(struct mbr_part_info* mpi, unsigned char* na #if DEBUG_MMC_IOCTL printk("part_name = %s name = %s\n", part->info->volname, name); #endif - if (!strncmp(part->info->volname, name, 25)){ + if (!strncmp(part->info->volname, name, PARTITION_META_INFO_VOLNAMELTH)){ mpi->start_sector = part->start_sect; mpi->nr_sects = part->nr_sects; mpi->part_no = part->partno; @@ -1062,7 +1074,10 @@ static int simple_mmc_erase_partition(unsigned char* name) static int simple_mmc_erase_partition_wrap(struct msdc_ioctl* msdc_ctl) { - unsigned char name[25]; + unsigned char name[PARTITION_META_INFO_VOLNAMELTH]; + + if(msdc_ctl->total_size > PARTITION_META_INFO_VOLNAMELTH) + return -EFAULT; if (copy_from_user(name, (unsigned char*)msdc_ctl->buffer, msdc_ctl->total_size)) return -EFAULT; @@ -1072,57 +1087,67 @@ static int simple_mmc_erase_partition_wrap(struct msdc_ioctl* msdc_ctl) static long simple_sd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct msdc_ioctl *msdc_ctl = (struct msdc_ioctl *)arg; + struct msdc_ioctl msdc_ctl; int ret; - if(msdc_ctl == NULL){ + + if((struct msdc_ioctl*)arg == NULL){ switch(cmd){ case MSDC_REINIT_SDCARD: - ret = sd_ioctl_reinit(msdc_ctl); + ret = sd_ioctl_reinit(NULL); break; default: - printk("mt_sd_ioctl:this opcode value is illegal!!\n"); - return -EINVAL; - } + printk("mt_sd_ioctl:this opcode value is illegal!!\n"); + return -EINVAL; + } return ret; } else{ - switch (msdc_ctl->opcode){ - case MSDC_SINGLE_READ_WRITE: - msdc_ctl->result = simple_sd_ioctl_single_rw(msdc_ctl); - break; - case MSDC_MULTIPLE_READ_WRITE: - msdc_ctl->result = simple_sd_ioctl_multi_rw(msdc_ctl); - break; - case MSDC_GET_CID: - msdc_ctl->result = simple_sd_ioctl_get_cid(msdc_ctl); - break; - case MSDC_GET_CSD: - msdc_ctl->result = simple_sd_ioctl_get_csd(msdc_ctl); - break; - case MSDC_GET_EXCSD: - msdc_ctl->result = simple_sd_ioctl_get_excsd(msdc_ctl); - break; - case MSDC_DRIVING_SETTING: - printk("in ioctl to change driving\n"); - if (1 == msdc_ctl->iswrite){ - msdc_ctl->result = simple_sd_ioctl_set_driving(msdc_ctl); - } else { - msdc_ctl->result = simple_sd_ioctl_get_driving(msdc_ctl); - } - break; - case MSDC_ERASE_PARTITION: - msdc_ctl->result = simple_mmc_erase_partition_wrap(msdc_ctl); - break; - case MSDC_SD30_MODE_SWITCH: - msdc_ctl->result = simple_sd_ioctl_sd30_mode_switch(msdc_ctl); - break; - default: - printk("simple_sd_ioctl:this opcode value is illegal!!\n"); - return -EINVAL; - } + if (copy_from_user(&msdc_ctl, (struct msdc_ioctl*)arg, sizeof(struct msdc_ioctl))){ + return -EFAULT; + } - return msdc_ctl->result; -} + if (msdc_ctl.host_num >= HOST_MAX_NUM || msdc_ctl.host_num < 0) + return -EFAULT; + + switch (msdc_ctl.opcode){ + case MSDC_SINGLE_READ_WRITE: + msdc_ctl.result = simple_sd_ioctl_single_rw(&msdc_ctl); + break; + case MSDC_MULTIPLE_READ_WRITE: + msdc_ctl.result = simple_sd_ioctl_multi_rw(&msdc_ctl); + break; + case MSDC_GET_CID: + msdc_ctl.result = simple_sd_ioctl_get_cid(&msdc_ctl); + break; + case MSDC_GET_CSD: + msdc_ctl.result = simple_sd_ioctl_get_csd(&msdc_ctl); + break; + case MSDC_GET_EXCSD: + msdc_ctl.result = simple_sd_ioctl_get_excsd(&msdc_ctl); + break; + case MSDC_DRIVING_SETTING: + printk("in ioctl to change driving\n"); + if (1 == msdc_ctl.iswrite){ + msdc_ctl.result = simple_sd_ioctl_set_driving(&msdc_ctl); + } else { + msdc_ctl.result = simple_sd_ioctl_get_driving(&msdc_ctl); + } + break; + case MSDC_ERASE_PARTITION: + msdc_ctl.result = simple_mmc_erase_partition_wrap(&msdc_ctl); + break; + case MSDC_SD30_MODE_SWITCH: + msdc_ctl.result = simple_sd_ioctl_sd30_mode_switch(&msdc_ctl); + break; + default: + printk("simple_sd_ioctl:this opcode value is illegal!!\n"); + return -EINVAL; + } + if (copy_to_user((struct msdc_ioctl*)arg, &msdc_ctl, sizeof(struct msdc_ioctl))) { + return -EFAULT; + } + return msdc_ctl.result; + } } static struct file_operations simple_msdc_em_fops = { |