syzbot is reporting UAF/OOB read at bit_putcs()/soft_cursor() [1][2], for
vt_resizex() from ioctl(VT_RESIZEX) allows setting font height larger than
actual font height calculated by con_font_set() from ioctl(PIO_FONT).
Since fbcon_set_font() from con_font_set() allocates minimal amount of
memory based on actual font height calculated by con_font_set(),
use of vt_resizex() can cause UAF/OOB read for font data.

VT_RESIZEX was introduced in Linux 1.3.3, but it is unclear that what
comes to the "+ more" part, and I couldn't find a user of VT_RESIZEX.

  #define VT_RESIZE   0x5609 /* set kernel's idea of screensize */
  #define VT_RESIZEX  0x560A /* set kernel's idea of screensize + more */

So far we are not aware of syzbot reports caused by setting non-zero value
to v_vlin parameter. But given that it is possible that nobody is using
VT_RESIZEX, we can try removing support for v_clin and v_vlin parameters.

Therefore, this patch effectively makes VT_RESIZEX behave like VT_RESIZE,
with emitting a message if somebody is still using v_clin and/or v_vlin
parameters.

[1] 
https://syzkaller.appspot.com/bug?id=32577e96d88447ded2d3b76d71254fb855245837
[2] 
https://syzkaller.appspot.com/bug?id=6b8355d27b2b94fb5cedf4655e3a59162d9e48e3

Reported-by: syzbot <syzbot+b308f5fd049fbbc6e...@syzkaller.appspotmail.com>
Reported-by: syzbot <syzbot+16469b5e8e5a72e91...@syzkaller.appspotmail.com>
Signed-off-by: Tetsuo Handa <penguin-ker...@i-love.sakura.ne.jp>
---
 drivers/tty/vt/vt_ioctl.c | 57 +++++++--------------------------------
 1 file changed, 10 insertions(+), 47 deletions(-)

diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index a4e520bdd521..bc33938e2f20 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -773,58 +773,21 @@ static int vt_resizex(struct vc_data *vc, struct 
vt_consize __user *cs)
        if (copy_from_user(&v, cs, sizeof(struct vt_consize)))
                return -EFAULT;
 
-       /* FIXME: Should check the copies properly */
-       if (!v.v_vlin)
-               v.v_vlin = vc->vc_scan_lines;
-
-       if (v.v_clin) {
-               int rows = v.v_vlin / v.v_clin;
-               if (v.v_rows != rows) {
-                       if (v.v_rows) /* Parameters don't add up */
-                               return -EINVAL;
-                       v.v_rows = rows;
-               }
-       }
-
-       if (v.v_vcol && v.v_ccol) {
-               int cols = v.v_vcol / v.v_ccol;
-               if (v.v_cols != cols) {
-                       if (v.v_cols)
-                               return -EINVAL;
-                       v.v_cols = cols;
-               }
-       }
-
-       if (v.v_clin > 32)
-               return -EINVAL;
+       if (v.v_vlin)
+               pr_info_once("\"struct vt_consize\"->v_vlin is ignored. Please 
report if you need this.\n");
+       if (v.v_clin)
+               pr_info_once("\"struct vt_consize\"->v_clin is ignored. Please 
report if you need this.\n");
 
+       console_lock();
        for (i = 0; i < MAX_NR_CONSOLES; i++) {
-               struct vc_data *vcp;
+               vc = vc_cons[i].d;
 
-               if (!vc_cons[i].d)
-                       continue;
-               console_lock();
-               vcp = vc_cons[i].d;
-               if (vcp) {
-                       int ret;
-                       int save_scan_lines = vcp->vc_scan_lines;
-                       int save_font_height = vcp->vc_font.height;
-
-                       if (v.v_vlin)
-                               vcp->vc_scan_lines = v.v_vlin;
-                       if (v.v_clin)
-                               vcp->vc_font.height = v.v_clin;
-                       vcp->vc_resize_user = 1;
-                       ret = vc_resize(vcp, v.v_cols, v.v_rows);
-                       if (ret) {
-                               vcp->vc_scan_lines = save_scan_lines;
-                               vcp->vc_font.height = save_font_height;
-                               console_unlock();
-                               return ret;
-                       }
+               if (vc) {
+                       vc->vc_resize_user = 1;
+                       vc_resize(vc, v.v_cols, v.v_rows);
                }
-               console_unlock();
        }
+       console_unlock();
 
        return 0;
 }
-- 
2.25.1

Reply via email to