aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/compat_ioctl.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 65643def3182..6b44cdc96fac 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -1194,6 +1194,7 @@ static int vt_check(struct file *file)
1194{ 1194{
1195 struct tty_struct *tty; 1195 struct tty_struct *tty;
1196 struct inode *inode = file->f_path.dentry->d_inode; 1196 struct inode *inode = file->f_path.dentry->d_inode;
1197 struct vc_data *vc;
1197 1198
1198 if (file->f_op->ioctl != tty_ioctl) 1199 if (file->f_op->ioctl != tty_ioctl)
1199 return -EINVAL; 1200 return -EINVAL;
@@ -1204,12 +1205,16 @@ static int vt_check(struct file *file)
1204 1205
1205 if (tty->driver->ioctl != vt_ioctl) 1206 if (tty->driver->ioctl != vt_ioctl)
1206 return -EINVAL; 1207 return -EINVAL;
1207 1208
1209 vc = (struct vc_data *)tty->driver_data;
1210 if (!vc_cons_allocated(vc->vc_num)) /* impossible? */
1211 return -ENOIOCTLCMD;
1212
1208 /* 1213 /*
1209 * To have permissions to do most of the vt ioctls, we either have 1214 * To have permissions to do most of the vt ioctls, we either have
1210 * to be the owner of the tty, or super-user. 1215 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
1211 */ 1216 */
1212 if (current->signal->tty == tty || capable(CAP_SYS_ADMIN)) 1217 if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
1213 return 1; 1218 return 1;
1214 return 0; 1219 return 0;
1215} 1220}
@@ -1310,16 +1315,28 @@ static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
1310 struct unimapdesc32 tmp; 1315 struct unimapdesc32 tmp;
1311 struct unimapdesc32 __user *user_ud = compat_ptr(arg); 1316 struct unimapdesc32 __user *user_ud = compat_ptr(arg);
1312 int perm = vt_check(file); 1317 int perm = vt_check(file);
1313 1318 struct vc_data *vc;
1314 if (perm < 0) return perm; 1319
1320 if (perm < 0)
1321 return perm;
1315 if (copy_from_user(&tmp, user_ud, sizeof tmp)) 1322 if (copy_from_user(&tmp, user_ud, sizeof tmp))
1316 return -EFAULT; 1323 return -EFAULT;
1324 if (tmp.entries)
1325 if (!access_ok(VERIFY_WRITE, compat_ptr(tmp.entries),
1326 tmp.entry_ct*sizeof(struct unipair)))
1327 return -EFAULT;
1328 vc = ((struct tty_struct *)file->private_data)->driver_data;
1317 switch (cmd) { 1329 switch (cmd) {
1318 case PIO_UNIMAP: 1330 case PIO_UNIMAP:
1319 if (!perm) return -EPERM; 1331 if (!perm)
1320 return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries)); 1332 return -EPERM;
1333 return con_set_unimap(vc, tmp.entry_ct,
1334 compat_ptr(tmp.entries));
1321 case GIO_UNIMAP: 1335 case GIO_UNIMAP:
1322 return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries)); 1336 if (!perm && fg_console != vc->vc_num)
1337 return -EPERM;
1338 return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
1339 compat_ptr(tmp.entries));
1323 } 1340 }
1324 return 0; 1341 return 0;
1325} 1342}