Commit f4d43bd5 authored by Hugh Dickins's avatar Hugh Dickins Committed by Linus Torvalds

fix compat console unimap regression

Why is it that since the 2f1a2ccb console
UTF-8 fixes went into 2.6.22-rc1, the PowerMac G5 shows only inverse video
question marks for the text on tty2-6? whereas tty1 is fine, and so is x86.

No fault of that patch: by removing the old fallback behaviour, it reveals
that 32-bit setfont running on 64-bit kernels has only really worked on
the current console, the rest getting faked by that inadequate fallback.

Bring the compat do_unimap_ioctl into line with the main one: PIO_UNIMAP
and GIO_UNIMAP apply to the specified tty, not redirected to fg_console.
Use the same checks, and most particularly, remember to check access_ok:
con_set_unimap and con_get_unimap are using __get_user and __put_user.

And the compat vt_check should ask for the same capability as the main
one, CAP_SYS_TTY_CONFIG rather than CAP_SYS_ADMIN.  Added in vt_ioctl's
vc_cons_allocated check for safety, though failure may well be impossible.
Signed-off-by: default avatarHugh Dickins <hugh@veritas.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1ea09758
...@@ -1194,6 +1194,7 @@ static int vt_check(struct file *file) ...@@ -1194,6 +1194,7 @@ static int vt_check(struct file *file)
{ {
struct tty_struct *tty; struct tty_struct *tty;
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
struct vc_data *vc;
if (file->f_op->ioctl != tty_ioctl) if (file->f_op->ioctl != tty_ioctl)
return -EINVAL; return -EINVAL;
...@@ -1205,11 +1206,15 @@ static int vt_check(struct file *file) ...@@ -1205,11 +1206,15 @@ static int vt_check(struct file *file)
if (tty->driver->ioctl != vt_ioctl) if (tty->driver->ioctl != vt_ioctl)
return -EINVAL; return -EINVAL;
vc = (struct vc_data *)tty->driver_data;
if (!vc_cons_allocated(vc->vc_num)) /* impossible? */
return -ENOIOCTLCMD;
/* /*
* To have permissions to do most of the vt ioctls, we either have * To have permissions to do most of the vt ioctls, we either have
* to be the owner of the tty, or super-user. * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
*/ */
if (current->signal->tty == tty || capable(CAP_SYS_ADMIN)) if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
return 1; return 1;
return 0; return 0;
} }
...@@ -1310,16 +1315,28 @@ static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, ...@@ -1310,16 +1315,28 @@ static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
struct unimapdesc32 tmp; struct unimapdesc32 tmp;
struct unimapdesc32 __user *user_ud = compat_ptr(arg); struct unimapdesc32 __user *user_ud = compat_ptr(arg);
int perm = vt_check(file); int perm = vt_check(file);
struct vc_data *vc;
if (perm < 0) return perm; if (perm < 0)
return perm;
if (copy_from_user(&tmp, user_ud, sizeof tmp)) if (copy_from_user(&tmp, user_ud, sizeof tmp))
return -EFAULT; return -EFAULT;
if (tmp.entries)
if (!access_ok(VERIFY_WRITE, compat_ptr(tmp.entries),
tmp.entry_ct*sizeof(struct unipair)))
return -EFAULT;
vc = ((struct tty_struct *)file->private_data)->driver_data;
switch (cmd) { switch (cmd) {
case PIO_UNIMAP: case PIO_UNIMAP:
if (!perm) return -EPERM; if (!perm)
return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries)); return -EPERM;
return con_set_unimap(vc, tmp.entry_ct,
compat_ptr(tmp.entries));
case GIO_UNIMAP: case GIO_UNIMAP:
return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries)); if (!perm && fg_console != vc->vc_num)
return -EPERM;
return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
compat_ptr(tmp.entries));
} }
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment