]> git.itanic.dy.fi Git - linux-stable/commitdiff
vc_screen: rewrite vcs_size to accept vc, not inode
authorJiri Slaby <jslaby@suse.cz>
Tue, 18 Aug 2020 08:56:55 +0000 (10:56 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 30 May 2023 11:44:08 +0000 (12:44 +0100)
[ Upstream commit 71d4abfab322e827a75304431fe0fad3c805cb80 ]

It is weird to fetch the information from the inode over and over. Read
and write already have the needed information, so rewrite vcs_size to
accept a vc, attr and unicode and adapt vcs_lseek to that.

Also make sure all sites check the return value of vcs_size for errors.

And document it using kernel-doc.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20200818085706.12163-5-jslaby@suse.cz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: 8fb9ea65c9d1 ("vc_screen: reload load of struct vc_data pointer in vcs_write() to avoid UAF")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/tty/vt/vc_screen.c

index 90de3331e4a511cbcbd0c09fad53322b7e5eeba0..48d74269f1d597a4bd14df14ce528124431e3c28 100644 (file)
@@ -200,39 +200,47 @@ vcs_vc(struct inode *inode, int *viewed)
        return vc_cons[currcons].d;
 }
 
-/*
- * Returns size for VC carried by inode.
+/**
+ * vcs_size -- return size for a VC in @vc
+ * @vc: which VC
+ * @attr: does it use attributes?
+ * @unicode: is it unicode?
+ *
  * Must be called with console_lock.
  */
-static int
-vcs_size(struct inode *inode)
+static int vcs_size(const struct vc_data *vc, bool attr, bool unicode)
 {
        int size;
-       struct vc_data *vc;
 
        WARN_CONSOLE_UNLOCKED();
 
-       vc = vcs_vc(inode, NULL);
-       if (!vc)
-               return -ENXIO;
-
        size = vc->vc_rows * vc->vc_cols;
 
-       if (use_attributes(inode)) {
-               if (use_unicode(inode))
+       if (attr) {
+               if (unicode)
                        return -EOPNOTSUPP;
-               size = 2*size + HEADER_SIZE;
-       } else if (use_unicode(inode))
+
+               size = 2 * size + HEADER_SIZE;
+       } else if (unicode)
                size *= 4;
+
        return size;
 }
 
 static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
 {
+       struct inode *inode = file_inode(file);
+       struct vc_data *vc;
        int size;
 
        console_lock();
-       size = vcs_size(file_inode(file));
+       vc = vcs_vc(inode, NULL);
+       if (!vc) {
+               console_unlock();
+               return -ENXIO;
+       }
+
+       size = vcs_size(vc, use_attributes(inode), use_unicode(inode));
        console_unlock();
        if (size < 0)
                return size;
@@ -294,7 +302,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
                 * as copy_to_user at the end of this loop
                 * could sleep.
                 */
-               size = vcs_size(inode);
+               size = vcs_size(vc, attr, uni_mode);
                if (size < 0) {
                        ret = size;
                        break;
@@ -476,7 +484,11 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
        if (!vc)
                goto unlock_out;
 
-       size = vcs_size(inode);
+       size = vcs_size(vc, attr, false);
+       if (size < 0) {
+               ret = size;
+               goto unlock_out;
+       }
        ret = -EINVAL;
        if (pos < 0 || pos > size)
                goto unlock_out;
@@ -515,7 +527,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
                 * the user buffer, so recheck.
                 * Return data written up to now on failure.
                 */
-               size = vcs_size(inode);
+               size = vcs_size(vc, attr, false);
                if (size < 0) {
                        if (written)
                                break;