summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryang-cy.chen <yang-cy.chen@mediatek.com>2015-10-30 15:42:59 +0800
committerJin Qian <jinqian@google.com>2015-11-02 19:36:45 +0000
commitf029d0d424d327535f5c4f8a2af1c8e26a48adb3 (patch)
treeaa1c59d1c61265831742330f176efa03f6f8da3e
parent98a2f202c1ca10ce981a2e87be73b5bd7dd11540 (diff)
downloadmediatek-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.c115
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 = {