• Maciej W. Rozycki's avatar
    vt: Fix character height handling with VT_RESIZEX · 860dafa9
    Maciej W. Rozycki authored
    Restore the original intent of the VT_RESIZEX ioctl's `v_clin' parameter
    which is the number of pixel rows per character (cell) rather than the
    height of the font used.
    
    For framebuffer devices the two values are always the same, because the
    former is inferred from the latter one.  For VGA used as a true text
    mode device these two parameters are independent from each other: the
    number of pixel rows per character is set in the CRT controller, while
    font height is in fact hardwired to 32 pixel rows and fonts of heights
    below that value are handled by padding their data with blanks when
    loaded to hardware for use by the character generator.  One can change
    the setting in the CRT controller and it will update the screen contents
    accordingly regardless of the font loaded.
    
    The `v_clin' parameter is used by the `vgacon' driver to set the height
    of the character cell and then the cursor position within.  Make the
    parameter explicit then, by defining a new `vc_cell_height' struct
    member of `vc_data', set it instead of `vc_font.height' from `v_clin' in
    the VT_RESIZEX ioctl, and then use it throughout the `vgacon' driver
    except where actual font data is accessed which as noted above is
    independent from the CRTC setting.
    
    This way the framebuffer console driver is free to ignore the `v_clin'
    parameter as irrelevant, as it always should have, avoiding any issues
    attempts to give the parameter a meaning there could have caused, such
    as one that has led to commit 988d0763 ("vt_ioctl: make VT_RESIZEX
    behave like VT_RESIZE"):
    
     "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."
    
    The problem first appeared around Linux 2.5.66 which predates our repo
    history, but the origin could be identified with the old MIPS/Linux repo
    also at: <git://git.kernel.org/pub/scm/linux/kernel/git/ralf/linux.git>
    as commit 9736a3546de7 ("Merge with Linux 2.5.66."), where VT_RESIZEX
    code in `vt_ioctl' was updated as follows:
    
     		if (clin)
    -			video_font_height = clin;
    +			vc->vc_font.height = clin;
    
    making the parameter apply to framebuffer devices as well, perhaps due
    to the use of "font" in the name of the original `video_font_height'
    variable.  Use "cell" in the new struct member then to avoid ambiguity.
    
    References:
    
    [1] https://syzkaller.appspot.com/bug?id=32577e96d88447ded2d3b76d71254fb855245837
    [2] https://syzkaller.appspot.com/bug?id=6b8355d27b2b94fb5cedf4655e3a59162d9e48e3Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
    Fixes: 1da177e4 ("Linux-2.6.12-rc2")
    Cc: stable@vger.kernel.org # v2.6.12+
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    860dafa9
vgacon.c 36.2 KB