From nobody Fri Jul 24 23:32:06 2026 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9CAB35C183; Wed, 22 Jul 2026 06:30:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784701859; cv=none; b=iwTbrTmQ7tJMMqAOJaNqE2RzC4WsyeAb2XAGEQx5ujt359CHUr5nnjNoH6qGd3uA4ExG/O11p3FvGNrp/ZrmLSCVdZP200MALzyrxd8W5kvA0GD7oCHeyLz2bCdRtvU/D4G3aTTU8J8bUc0OMJiRVr81iAGjb/x6azohosstEq8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784701859; c=relaxed/simple; bh=VRVJgeWJkN6pOa6QfDnWbD3axb8vtIkbwfDQLtR6L4w=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=KQSE6bSoFihDRc+iZFWp3ldcFyJsM4T5eu1clrTFJuzhTtacH55XnvqJr447zFXOIQdSejlluBTUbyDjw8jxLszV3Ht+PNdMA3m4NZ9HaYuL6qZZqiCBCF5/6MZ1gGHHg1kANagGo+2phwiq2MhQpczR77WD9V+KPjMMCsqEXwI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=none smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.170]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4h4krd5xr1zKHMRH; Wed, 22 Jul 2026 14:30:09 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.112]) by mail.maildlp.com (Postfix) with ESMTP id 1AAAC40561; Wed, 22 Jul 2026 14:30:53 +0800 (CST) Received: from huaweicloud.com (unknown [10.50.85.155]) by APP1 (Coremail) with UTF8SMTPSA id cCh0CgCX8W2bY2BqWgB7CA--.42682S4; Wed, 22 Jul 2026 14:30:52 +0800 (CST) From: Zizhi Wo To: simona@ffwll.ch, deller@gmx.de, tzimmermann@suse.de, sam@ravnborg.org, ville.syrjala@linux.intel.com Cc: linux-kernel@vger.kernel.org, linux-fbdev@vger.kernel.org, dri-devel@lists.freedesktop.org, yangerkun@huawei.com, chengzhihao1@huawei.com, wozizhi@huawei.com Subject: [PATCH V2] fbdev: Fix out-of-bounds access when rotating console after font resize Date: Wed, 22 Jul 2026 14:22:16 +0800 Message-ID: <20260722062216.2574546-1-wozizhi@huaweicloud.com> X-Mailer: git-send-email 2.52.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: cCh0CgCX8W2bY2BqWgB7CA--.42682S4 X-Coremail-Antispam: 1UD129KBjvJXoWxKFy5AryUGry8JryfGF43Awb_yoW7trWUpF 12kr17Krs0q3Z3Zr4qgr45uF1aqw4DJry5WrZ3t3WYya45ZFWvv3ZrJFyDurW8urn3Cryr Z3WrKrW2kayq9aDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUv2b4IE77IF4wAFF20E14v26r4j6ryUM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28lY4IEw2IIxxk0rwA2F7IY1VAKz4 vEj48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7Cj xVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x 0267AKxVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG 6I80ewAv7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFV Cjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0E n4kS14v26r1q6r43MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I 0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWU tVW8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcV CY1x0267AKxVW8JVWxJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAF wI0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa 7IU17KsUUUUUU== X-CM-SenderInfo: pzr2x6tkl6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" From: Zizhi Wo [BUG] Recently, we encountered a KASAN warning as follows: BUG: KASAN: slab-out-of-bounds in ccw_putcs+0x8bd/0xa80 Read of size 1 at addr ff11000110067100 by task bash/1209 CPU: 10 UID: 0 PID: 1209 Comm: bash Not tainted 7.2.0-rc3 #69 PREEMPT(full) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-4.fc41 0= 4/01/2014 Call Trace: ... kasan_report+0xf0/0x120 ? ccw_putcs+0x8bd/0xa80 ccw_putcs+0x8bd/0xa80 ? __pfx_ccw_putcs+0x10/0x10 fbcon_putcs+0x338/0x410 ? __pfx_ccw_putcs+0x10/0x10 do_update_region+0x21d/0x450 invert_screen+0x29d/0x5e0 ? __kmalloc_noprof+0x493/0x640 ? vc_do_resize+0x17c/0xe50 clear_selection+0x4c/0x60 vc_do_resize+0xaee/0xe50 fbcon_modechanged+0x2bd/0x640 rotate_all_store+0x298/0x380 ... reproduce: 1) issue two ioctls: first a KDFONTOP ioctl with op.op =3D KD_FONT_OP_SET, op.width =3D 1 and op.height =3D 1, then a TIOCL_SETSEL ioctl 2) echo 2 > /sys/devices/virtual/graphics/fbcon/rotate_all 3) issue two ioctls: first a KDFONTOP ioctl with op.op =3D KD_FONT_OP_SET, op.width =3D 8 and op.height =3D 1, then a TIOCL_SETSEL ioctl 4) echo 3 > /sys/devices/virtual/graphics/fbcon/rotate_all [CAUSE] The root cause is that fbcon_modechanged() first sets the current rotate's corresponding ops. Subsequently, during vc_resize(), it may trigger clear_selection(), and in fbcon_putcs->ccw_putcs[rotate=3D3], this can resu= lt in an out-of-bounds access to "src". This happens because par->rotated.buf is reallocated in fbcon_rotate_font(): 1) When rotate=3D2, its size is (width + 7) / 8 * height 2) When rotate=3D3, its size is (height + 7) / 8 * width And the call to fbcon_rotate_font() occurs after clear_selection(). In other words, the fontbuffer is allocated using the size calculated from the previous rotation 2, but before reallocating it with the new size, con_putcs is already using the new rotation 3: rotate_all_store fbcon_rotate_all fbcon_set_all_vcs fbcon_modechanged set_blitting_type ... par->bitops =3D &ccw_fbcon_bitops vc_resize ... clear_selection highlight ... do_update_region fbcon_putcs ... image.dy =3D vyres - ((xx + count) * vc->vc_font.width) [1] // overflow! ccw_putcs_aligned // old buf size is still being used during the read! src =3D par->rotated.buf + (scr_readw(s--) & charmask) * cellsize fb_pad_aligned_buffer----[src KASAN!!!] [2] info->fbops->fb_imageblit(info, image) sys_imageblit fb_imageblit fb_address_forward // offset: image->dy * bits_per_line + image->dx * bpp unsigned int bits =3D (unsigned int)adr->bits + offset adr->address +=3D (bits & ~(BITS_PER_LONG - 1u)) / BITS_PER_BYTE [3] fb_bitmap_imageblit ... fb_read_offset // page fault! [4] update_screen redraw_screen ... ccw_cursor soft_cursor memcpy(src, image->data, dsize)----[src KASAN again!!!] [5] fbcon_switch fbcon_rotate_font font_data_rotate dst =3D kmalloc_array(charcount, d_cellsize, GFP_KERNEL) // the new size is allocated only here! par->rotated.buf =3D buf [6] [FIX] A fairly obvious approach is to follow fbcon_switch(): in fbcon_modechanged(), call rotate_font() before vc_resize() so that a correctly sized buffer is allocated in time, as done in [6]. This fix is necessary, but it is not sufficient on its own. In [1] it causes an image.dy overflow (ccw_putcs: vyres =3D 768, image.dy =3D 4294967040), because vc_cols has not been updated in time at this point (it is likewise only updated after clear_selection()). This allows (xx + count) * width to exceed vyres, causing image.dy to overflow. Subsequently, address in [3] is incremented by an even larger amount, which triggers a page fault at [4]. Therefore, a second fix is required in combination with the first: move clear_selection() earlier, before set_blitting_type() in fbcon_set_all_vcs(), to prevent the out-of-bounds access. fbcon_rotate() has a similar problem, so add the same clear there. Since vc_is_sel() is not exported, the fbdev side is currently forced to call clear_selection() unconditionally, causing the global selection to be cleared prematurely. And this will not cause any other significant impact. Signed-off-by: Zizhi Wo --- v2: Fixed the issue by calling clear_selection() earlier, and updated the related description in the commit message. v1: https://lore.kernel.org/all/20250905024340.337521-1-wozizhi@huaweicloud= .com/ --- drivers/video/fbdev/core/fbcon.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fb= con.c index 9f5c4c101581..3361479d139d 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -2639,13 +2639,20 @@ static void fbcon_modechanged(struct fb_info *info) vc =3D vc_cons[par->currcon].d; if (vc->vc_mode !=3D KD_TEXT || fbcon_info_from_console(par->currcon) !=3D info) return; =20 + clear_selection(); + p =3D &fb_display[vc->vc_num]; set_blitting_type(vc, info); =20 + if (par->bitops->rotate_font && par->bitops->rotate_font(info, vc)) { + par->rotate =3D FB_ROTATE_UR; + set_blitting_type(vc, info); + } + if (con_is_visible(vc)) { var_to_display(p, &info->var, info); cols =3D FBCON_SWAP(par->rotate, info->var.xres, info->var.yres); rows =3D FBCON_SWAP(par->rotate, info->var.yres, info->var.xres); cols /=3D vc->vc_font.width; @@ -2673,10 +2680,12 @@ static void fbcon_set_all_vcs(struct fb_info *info) int i, rows, cols, fg =3D -1; =20 if (!par || par->currcon < 0) return; =20 + clear_selection(); + for (i =3D first_fb_vc; i <=3D last_fb_vc; i++) { vc =3D vc_cons[i].d; if (!vc || vc->vc_mode !=3D KD_TEXT || fbcon_info_from_console(i) !=3D info) continue; --=20 2.52.0