Skip to content

Commit 583d424

Browse files
committed
mtd: properly check all write ioctls for permissions
commit f7e6b19 upstream. 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]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 8c19b60 commit 583d424

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
@@ -372,9 +372,6 @@ static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,
372372
uint32_t retlen;
373373
int ret = 0;
374374

375-
if (!(file->f_mode & FMODE_WRITE))
376-
return -EPERM;
377-
378375
if (length > 4096)
379376
return -EINVAL;
380377

@@ -681,6 +678,48 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
681678
return -EFAULT;
682679
}
683680

681+
/*
682+
* Check the file mode to require "dangerous" commands to have write
683+
* permissions.
684+
*/
685+
switch (cmd) {
686+
/* "safe" commands */
687+
case MEMGETREGIONCOUNT:
688+
case MEMGETREGIONINFO:
689+
case MEMGETINFO:
690+
case MEMREADOOB:
691+
case MEMREADOOB64:
692+
case MEMLOCK:
693+
case MEMUNLOCK:
694+
case MEMISLOCKED:
695+
case MEMGETOOBSEL:
696+
case MEMGETBADBLOCK:
697+
case MEMSETBADBLOCK:
698+
case OTPSELECT:
699+
case OTPGETREGIONCOUNT:
700+
case OTPGETREGIONINFO:
701+
case OTPLOCK:
702+
case ECCGETLAYOUT:
703+
case ECCGETSTATS:
704+
case MTDFILEMODE:
705+
case BLKPG:
706+
case BLKRRPART:
707+
break;
708+
709+
/* "dangerous" commands */
710+
case MEMERASE:
711+
case MEMERASE64:
712+
case MEMWRITEOOB:
713+
case MEMWRITEOOB64:
714+
case MEMWRITE:
715+
if (!(file->f_mode & FMODE_WRITE))
716+
return -EPERM;
717+
break;
718+
719+
default:
720+
return -ENOTTY;
721+
}
722+
684723
switch (cmd) {
685724
case MEMGETREGIONCOUNT:
686725
if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
@@ -728,9 +767,6 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
728767
{
729768
struct erase_info *erase;
730769

731-
if(!(file->f_mode & FMODE_WRITE))
732-
return -EPERM;
733-
734770
erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
735771
if (!erase)
736772
ret = -ENOMEM;
@@ -1051,9 +1087,6 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
10511087
ret = 0;
10521088
break;
10531089
}
1054-
1055-
default:
1056-
ret = -ENOTTY;
10571090
}
10581091

10591092
return ret;
@@ -1097,6 +1130,11 @@ static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd,
10971130
struct mtd_oob_buf32 buf;
10981131
struct mtd_oob_buf32 __user *buf_user = argp;
10991132

1133+
if (!(file->f_mode & FMODE_WRITE)) {
1134+
ret = -EPERM;
1135+
break;
1136+
}
1137+
11001138
if (copy_from_user(&buf, argp, sizeof(buf)))
11011139
ret = -EFAULT;
11021140
else

0 commit comments

Comments
 (0)