Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f4d43bd579f13219ffd3cae48432eab5bbac2d6f
Commit:     f4d43bd579f13219ffd3cae48432eab5bbac2d6f
Parent:     1ea0975875294964853209927feccdf6bc8cf5f9
Author:     Hugh Dickins <[EMAIL PROTECTED]>
AuthorDate: Sat May 26 00:39:17 2007 +0100
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Fri May 25 17:37:46 2007 -0700

    fix compat console unimap regression
    
    Why is it that since the 2f1a2ccb9c0de632ab07193becf5f7121794f6ae 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: Hugh Dickins <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/compat_ioctl.c |   33 +++++++++++++++++++++++++--------
 1 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 65643de..6b44cdc 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -1194,6 +1194,7 @@ static int vt_check(struct file *file)
 {
        struct tty_struct *tty;
        struct inode *inode = file->f_path.dentry->d_inode;
+       struct vc_data *vc;
        
        if (file->f_op->ioctl != tty_ioctl)
                return -EINVAL;
@@ -1204,12 +1205,16 @@ static int vt_check(struct file *file)
                                                        
        if (tty->driver->ioctl != vt_ioctl)
                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 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 0;                                                    
 }
@@ -1310,16 +1315,28 @@ static int do_unimap_ioctl(unsigned int fd, unsigned 
int cmd, unsigned long arg,
        struct unimapdesc32 tmp;
        struct unimapdesc32 __user *user_ud = compat_ptr(arg);
        int perm = vt_check(file);
-       
-       if (perm < 0) return perm;
+       struct vc_data *vc;
+
+       if (perm < 0)
+               return perm;
        if (copy_from_user(&tmp, user_ud, sizeof tmp))
                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) {
        case PIO_UNIMAP:
-               if (!perm) return -EPERM;
-               return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, 
compat_ptr(tmp.entries));
+               if (!perm)
+                       return -EPERM;
+               return con_set_unimap(vc, tmp.entry_ct,
+                                               compat_ptr(tmp.entries));
        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;
 }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to