syzbot is reporting OOB write at vga16fb_imageblit() [1], for resize_screen() from ioctl(VT_RESIZE) returns 0 without checking whether requested rows/columns fit the amount of memory reserved for the graphical screen if current mode is KD_GRAPHICS. ---------- #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/kd.h> #include <linux/vt.h> int main(int argc, char *argv[]) { const int fd = open("/dev/char/4:1", O_RDWR); struct vt_sizes vt = { 0x4100, 2 }; ioctl(fd, KDSETMODE, KD_GRAPHICS); ioctl(fd, VT_RESIZE, &vt); ioctl(fd, KDSETMODE, KD_TEXT); return 0; } ---------- Allow framebuffer drivers to return -EINVAL, by moving vc->vc_mode != KD_GRAPHICS check from resize_screen() to fbcon_resize().
Unified · Split
| @@ -1171,7 +1171,7 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, · 1170 unmodified lines | ||
| 1171 | 1171 | /* Resizes the resolution of the display adapater */ |
| 1172 | 1172 | int err = 0; |
| 1173 | 1173 | |
| 1174 | − if (vc->vc_mode != KD_GRAPHICS && vc->vc_sw->con_resize) | |
| 1174 | + if (vc->vc_sw->con_resize) | |
| 1175 | 1175 | err = vc->vc_sw->con_resize(vc, width, height, user); |
| 1176 | 1176 | |
| 1177 | 1177 | return err; |
| @@ -2019,7 +2019,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, · 2018 unmodified lines | ||
| 2019 | 2019 | return -EINVAL; |
| 2020 | 2020 | |
| 2021 | 2021 | pr_debug("resize now %ix%i\n", var.xres, var.yres); |
| 2022 | − if (con_is_visible(vc)) { | |
| 2022 | + if (con_is_visible(vc) && vc->vc_mode == KD_TEXT) { | |
| 2023 | 2023 | var.activate = FB_ACTIVATE_NOW | |
| 2024 | 2024 | FB_ACTIVATE_FORCE; |
| 2025 | 2025 | fb_set_var(info, &var); |