Skip to content

Commit f7e6b19

Browse files
gregkhrichardweinberger
authored andcommitted
mtd: properly check all write ioctls for permissions
When doing a "write" ioctl call, properly check that we have permissions to do so before copying anything from userspace or anything else so we can "fail fast". This includes also covering the MEMWRITE ioctl which previously missed checking for this. Cc: Miquel Raynal <[email protected]> Cc: Richard Weinberger <[email protected]> Cc: Vignesh Raghavendra <[email protected]> Cc: stable <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> [rw: Fixed locking issue] Signed-off-by: Richard Weinberger <[email protected]>
1 parent d15be54 commit f7e6b19

File tree

1 file changed

+47
-9
lines changed

1 file changed

+47
-9
lines changed

drivers/mtd/mtdchar.c

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,6 @@ static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,
355355
uint32_t retlen;
356356
int ret = 0;
357357

358-
if (!(file->f_mode & FMODE_WRITE))
359-
return -EPERM;
360-
361358
if (length > 4096)
362359
return -EINVAL;
363360

@@ -643,6 +640,48 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
643640

644641
pr_debug("MTD_ioctl\n");
645642

643+
/*
644+
* Check the file mode to require "dangerous" commands to have write
645+
* permissions.
646+
*/
647+
switch (cmd) {
648+
/* "safe" commands */
649+
case MEMGETREGIONCOUNT:
650+
case MEMGETREGIONINFO:
651+
case MEMGETINFO:
652+
case MEMREADOOB:
653+
case MEMREADOOB64:
654+
case MEMLOCK:
655+
case MEMUNLOCK:
656+
case MEMISLOCKED:
657+
case MEMGETOOBSEL:
658+
case MEMGETBADBLOCK:
659+
case MEMSETBADBLOCK:
660+
case OTPSELECT:
661+
case OTPGETREGIONCOUNT:
662+
case OTPGETREGIONINFO:
663+
case OTPLOCK:
664+
case ECCGETLAYOUT:
665+
case ECCGETSTATS:
666+
case MTDFILEMODE:
667+
case BLKPG:
668+
case BLKRRPART:
669+
break;
670+
671+
/* "dangerous" commands */
672+
case MEMERASE:
673+
case MEMERASE64:
674+
case MEMWRITEOOB:
675+
case MEMWRITEOOB64:
676+
case MEMWRITE:
677+
if (!(file->f_mode & FMODE_WRITE))
678+
return -EPERM;
679+
break;
680+
681+
default:
682+
return -ENOTTY;
683+
}
684+
646685
switch (cmd) {
647686
case MEMGETREGIONCOUNT:
648687
if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
@@ -690,9 +729,6 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
690729
{
691730
struct erase_info *erase;
692731

693-
if(!(file->f_mode & FMODE_WRITE))
694-
return -EPERM;
695-
696732
erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
697733
if (!erase)
698734
ret = -ENOMEM;
@@ -985,9 +1021,6 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
9851021
ret = 0;
9861022
break;
9871023
}
988-
989-
default:
990-
ret = -ENOTTY;
9911024
}
9921025

9931026
return ret;
@@ -1031,6 +1064,11 @@ static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd,
10311064
struct mtd_oob_buf32 buf;
10321065
struct mtd_oob_buf32 __user *buf_user = argp;
10331066

1067+
if (!(file->f_mode & FMODE_WRITE)) {
1068+
ret = -EPERM;
1069+
break;
1070+
}
1071+
10341072
if (copy_from_user(&buf, argp, sizeof(buf)))
10351073
ret = -EFAULT;
10361074
else

0 commit comments

Comments
 (0)