All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peilin Ye <yepeilin.cs@gmail.com>
To: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Cc: syzbot <syzbot+b308f5fd049fbbc6e74f@syzkaller.appspotmail.com>,
	linux-fbdev@vger.kernel.org, b.zolnierkie@samsung.com,
	daniel.vetter@ffwll.ch, deller@gmx.de,
	syzkaller-bugs@googlegroups.com, linux-kernel@vger.kernel.org,
	dri-devel@lists.freedesktop.org, gregkh@linuxfoundation.org,
	jirislaby@kernel.org, yepeilin.cs@gmail.com
Subject: Re: KASAN: use-after-free Read in bit_putcs
Date: Sat, 26 Sep 2020 19:39:57 +0000	[thread overview]
Message-ID: <20200926193957.GA1033221@PWN> (raw)
In-Reply-To: <bbcef674-4ac6-c933-b55d-8961ada97f4c@i-love.sakura.ne.jp>

On Sun, Sep 27, 2020 at 01:25:17AM +0900, Tetsuo Handa wrote:
> A simplified reproducer and debug printk() patch shown below reported that
> vc_font.height is increased to 9 via ioctl(VT_RESIZEX) after it was once
> decreased from 16 to 2 via ioctl(PIO_FONT).
> 
> 
> 
> Since vc_resize() with v.v_rows = 0 preserves current vc->vc_rows value,
> this reproducer is bypassing
> 
> 	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;
> 		}
> 	}
> 
> check by setting v.v_vlin = 1 and v.v_clin = 9.
> 
> If v.v_vcol > 0 and v.v_vcol != vc->vc_cols (though this reproducer is passing
> v.v_vcol = 0), tty_do_resize() from vc_do_resize() from vc_resize() can make
> "struct tty_struct"->winsize.ws_ypixel = 1 despite
> "struct tty_struct"->winsize.vc->vc_rows = vc->vc_rows (which is usually larger
> than 1). Does such winsize (a row has 1 / vc->vc_rows pixel) make sense?
> 
> 
> 
> Since I don't know the meaning of "struct vt_consize"->v_clin (which is commented
> with "/* number of pixel rows per character */" but does it mean font size ?),
> I don't know why we can assign that value to vcp->vc_font.height via
> 
> 	if (v.v_clin)
> 		vcp->vc_font.height = v.v_clin;
> 
> in vt_resizex(). While ioctl(PIO_FONT) needs to pass vc->vc_sw->con_font_set()
> check in con_font_set(), ioctl(VT_RESIZEX) does not pass it in vt_resizex()...
> 
> Since this problem does not happen if I remove
> 
> 	if (v.v_clin)
> 		vcp->vc_font.height = v.v_clin;

Hi Tetsuo!

>  from vt_resizex(), I guess that some variables are getting confused by change
> of vc->vc_font.height ...

Yes, see bit_putcs():

(drivers/video/fbdev/core/bitblit.c)
static void bit_putcs(struct vc_data *vc, struct fb_info *info,
		      const unsigned short *s, int count, int yy, int xx,
		      int fg, int bg)
{
	struct fb_image image;
	u32 width = DIV_ROUND_UP(vc->vc_font.width, 8);
	u32 cellsize = width * vc->vc_font.height;
	    ^^^^^^^^		   ^^^^^^^^^^^^^^

`cellsize` is now too large. Later, in bit_putcs_aligned():

	while (cnt--) {
		src = vc->vc_font.data + (scr_readw(s++)&
					  charmask)*cellsize;
						    ^^^^^^^^

`src` goes out of bounds of the data buffer. At first glance I guess
this is an out-of-bound read reported as a use-after-free read? The
crashlog says:

[  149.732103][ T6693] Allocated by task 6667:
[ 149.732115][ T6693] kasan_save_stack (mm/kasan/common.c:48)
[ 149.732121][ T6693] __kasan_kmalloc.constprop.0 (mm/kasan/common.c:56 mm/kasan/common.c:461)
[ 149.732126][ T6693] __kmalloc (mm/slab.c:3656 mm/slab.c:3664)
[ 149.732133][ T6693] alloc_pipe_info (fs/pipe.c:810)
[ 149.732139][ T6693] create_pipe_files (fs/pipe.c:883 fs/pipe.c:914)
[ 149.732145][ T6693] do_pipe2 (fs/pipe.c:965 fs/pipe.c:1012)

I'm not sure, but I don't think a buffer allocated in fs/pipe.c is
related here. Maybe they just live near each other on the heap?

To resolve this out-of-bound issue for now, I think the easiest way
is to add a range check in bit_putcs(), or bit_putcs_aligned().

...but yeah, that `VT_RESIZEX` ioctl looks really buggy, and is already
causing more issues:

KASAN: global-out-of-bounds Read in fbcon_get_font
Link: https://syzkaller.appspot.com/bug?id\bb8be45afea11888776f897895aef9ad1c3ecfd

This was also caused by `VT_RESIZEX`...

Thank you,
Peilin Ye

WARNING: multiple messages have this Message-ID (diff)
From: Peilin Ye <yepeilin.cs@gmail.com>
To: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Cc: syzbot <syzbot+b308f5fd049fbbc6e74f@syzkaller.appspotmail.com>,
	linux-fbdev@vger.kernel.org, b.zolnierkie@samsung.com,
	daniel.vetter@ffwll.ch, deller@gmx.de,
	syzkaller-bugs@googlegroups.com, linux-kernel@vger.kernel.org,
	dri-devel@lists.freedesktop.org, gregkh@linuxfoundation.org,
	jirislaby@kernel.org, yepeilin.cs@gmail.com
Subject: Re: KASAN: use-after-free Read in bit_putcs
Date: Sat, 26 Sep 2020 15:39:57 -0400	[thread overview]
Message-ID: <20200926193957.GA1033221@PWN> (raw)
In-Reply-To: <bbcef674-4ac6-c933-b55d-8961ada97f4c@i-love.sakura.ne.jp>

On Sun, Sep 27, 2020 at 01:25:17AM +0900, Tetsuo Handa wrote:
> A simplified reproducer and debug printk() patch shown below reported that
> vc_font.height is increased to 9 via ioctl(VT_RESIZEX) after it was once
> decreased from 16 to 2 via ioctl(PIO_FONT).
> 
> 
> 
> Since vc_resize() with v.v_rows == 0 preserves current vc->vc_rows value,
> this reproducer is bypassing
> 
> 	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;
> 		}
> 	}
> 
> check by setting v.v_vlin == 1 and v.v_clin == 9.
> 
> If v.v_vcol > 0 and v.v_vcol != vc->vc_cols (though this reproducer is passing
> v.v_vcol == 0), tty_do_resize() from vc_do_resize() from vc_resize() can make
> "struct tty_struct"->winsize.ws_ypixel = 1 despite
> "struct tty_struct"->winsize.vc->vc_rows = vc->vc_rows (which is usually larger
> than 1). Does such winsize (a row has 1 / vc->vc_rows pixel) make sense?
> 
> 
> 
> Since I don't know the meaning of "struct vt_consize"->v_clin (which is commented
> with "/* number of pixel rows per character */" but does it mean font size ?),
> I don't know why we can assign that value to vcp->vc_font.height via
> 
> 	if (v.v_clin)
> 		vcp->vc_font.height = v.v_clin;
> 
> in vt_resizex(). While ioctl(PIO_FONT) needs to pass vc->vc_sw->con_font_set()
> check in con_font_set(), ioctl(VT_RESIZEX) does not pass it in vt_resizex()...
> 
> Since this problem does not happen if I remove
> 
> 	if (v.v_clin)
> 		vcp->vc_font.height = v.v_clin;

Hi Tetsuo!

>  from vt_resizex(), I guess that some variables are getting confused by change
> of vc->vc_font.height ...

Yes, see bit_putcs():

(drivers/video/fbdev/core/bitblit.c)
static void bit_putcs(struct vc_data *vc, struct fb_info *info,
		      const unsigned short *s, int count, int yy, int xx,
		      int fg, int bg)
{
	struct fb_image image;
	u32 width = DIV_ROUND_UP(vc->vc_font.width, 8);
	u32 cellsize = width * vc->vc_font.height;
	    ^^^^^^^^		   ^^^^^^^^^^^^^^

`cellsize` is now too large. Later, in bit_putcs_aligned():

	while (cnt--) {
		src = vc->vc_font.data + (scr_readw(s++)&
					  charmask)*cellsize;
						    ^^^^^^^^

`src` goes out of bounds of the data buffer. At first glance I guess
this is an out-of-bound read reported as a use-after-free read? The
crashlog says:

[  149.732103][ T6693] Allocated by task 6667:
[ 149.732115][ T6693] kasan_save_stack (mm/kasan/common.c:48)
[ 149.732121][ T6693] __kasan_kmalloc.constprop.0 (mm/kasan/common.c:56 mm/kasan/common.c:461)
[ 149.732126][ T6693] __kmalloc (mm/slab.c:3656 mm/slab.c:3664)
[ 149.732133][ T6693] alloc_pipe_info (fs/pipe.c:810)
[ 149.732139][ T6693] create_pipe_files (fs/pipe.c:883 fs/pipe.c:914)
[ 149.732145][ T6693] do_pipe2 (fs/pipe.c:965 fs/pipe.c:1012)

I'm not sure, but I don't think a buffer allocated in fs/pipe.c is
related here. Maybe they just live near each other on the heap?

To resolve this out-of-bound issue for now, I think the easiest way
is to add a range check in bit_putcs(), or bit_putcs_aligned().

...but yeah, that `VT_RESIZEX` ioctl looks really buggy, and is already
causing more issues:

KASAN: global-out-of-bounds Read in fbcon_get_font
Link: https://syzkaller.appspot.com/bug?id=08b8be45afea11888776f897895aef9ad1c3ecfd

This was also caused by `VT_RESIZEX`...

Thank you,
Peilin Ye

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

WARNING: multiple messages have this Message-ID (diff)
From: Peilin Ye <yepeilin.cs@gmail.com>
To: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Cc: syzbot <syzbot+b308f5fd049fbbc6e74f@syzkaller.appspotmail.com>,
	b.zolnierkie@samsung.com, daniel.vetter@ffwll.ch, deller@gmx.de,
	gregkh@linuxfoundation.org, jirislaby@kernel.org,
	syzkaller-bugs@googlegroups.com, dri-devel@lists.freedesktop.org,
	linux-fbdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	yepeilin.cs@gmail.com
Subject: Re: KASAN: use-after-free Read in bit_putcs
Date: Sat, 26 Sep 2020 15:39:57 -0400	[thread overview]
Message-ID: <20200926193957.GA1033221@PWN> (raw)
In-Reply-To: <bbcef674-4ac6-c933-b55d-8961ada97f4c@i-love.sakura.ne.jp>

On Sun, Sep 27, 2020 at 01:25:17AM +0900, Tetsuo Handa wrote:
> A simplified reproducer and debug printk() patch shown below reported that
> vc_font.height is increased to 9 via ioctl(VT_RESIZEX) after it was once
> decreased from 16 to 2 via ioctl(PIO_FONT).
> 
> 
> 
> Since vc_resize() with v.v_rows == 0 preserves current vc->vc_rows value,
> this reproducer is bypassing
> 
> 	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;
> 		}
> 	}
> 
> check by setting v.v_vlin == 1 and v.v_clin == 9.
> 
> If v.v_vcol > 0 and v.v_vcol != vc->vc_cols (though this reproducer is passing
> v.v_vcol == 0), tty_do_resize() from vc_do_resize() from vc_resize() can make
> "struct tty_struct"->winsize.ws_ypixel = 1 despite
> "struct tty_struct"->winsize.vc->vc_rows = vc->vc_rows (which is usually larger
> than 1). Does such winsize (a row has 1 / vc->vc_rows pixel) make sense?
> 
> 
> 
> Since I don't know the meaning of "struct vt_consize"->v_clin (which is commented
> with "/* number of pixel rows per character */" but does it mean font size ?),
> I don't know why we can assign that value to vcp->vc_font.height via
> 
> 	if (v.v_clin)
> 		vcp->vc_font.height = v.v_clin;
> 
> in vt_resizex(). While ioctl(PIO_FONT) needs to pass vc->vc_sw->con_font_set()
> check in con_font_set(), ioctl(VT_RESIZEX) does not pass it in vt_resizex()...
> 
> Since this problem does not happen if I remove
> 
> 	if (v.v_clin)
> 		vcp->vc_font.height = v.v_clin;

Hi Tetsuo!

>  from vt_resizex(), I guess that some variables are getting confused by change
> of vc->vc_font.height ...

Yes, see bit_putcs():

(drivers/video/fbdev/core/bitblit.c)
static void bit_putcs(struct vc_data *vc, struct fb_info *info,
		      const unsigned short *s, int count, int yy, int xx,
		      int fg, int bg)
{
	struct fb_image image;
	u32 width = DIV_ROUND_UP(vc->vc_font.width, 8);
	u32 cellsize = width * vc->vc_font.height;
	    ^^^^^^^^		   ^^^^^^^^^^^^^^

`cellsize` is now too large. Later, in bit_putcs_aligned():

	while (cnt--) {
		src = vc->vc_font.data + (scr_readw(s++)&
					  charmask)*cellsize;
						    ^^^^^^^^

`src` goes out of bounds of the data buffer. At first glance I guess
this is an out-of-bound read reported as a use-after-free read? The
crashlog says:

[  149.732103][ T6693] Allocated by task 6667:
[ 149.732115][ T6693] kasan_save_stack (mm/kasan/common.c:48)
[ 149.732121][ T6693] __kasan_kmalloc.constprop.0 (mm/kasan/common.c:56 mm/kasan/common.c:461)
[ 149.732126][ T6693] __kmalloc (mm/slab.c:3656 mm/slab.c:3664)
[ 149.732133][ T6693] alloc_pipe_info (fs/pipe.c:810)
[ 149.732139][ T6693] create_pipe_files (fs/pipe.c:883 fs/pipe.c:914)
[ 149.732145][ T6693] do_pipe2 (fs/pipe.c:965 fs/pipe.c:1012)

I'm not sure, but I don't think a buffer allocated in fs/pipe.c is
related here. Maybe they just live near each other on the heap?

To resolve this out-of-bound issue for now, I think the easiest way
is to add a range check in bit_putcs(), or bit_putcs_aligned().

...but yeah, that `VT_RESIZEX` ioctl looks really buggy, and is already
causing more issues:

KASAN: global-out-of-bounds Read in fbcon_get_font
Link: https://syzkaller.appspot.com/bug?id=08b8be45afea11888776f897895aef9ad1c3ecfd

This was also caused by `VT_RESIZEX`...

Thank you,
Peilin Ye


  reply	other threads:[~2020-09-26 19:39 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-23 17:30 KASAN: use-after-free Read in bit_putcs syzbot
2020-02-23 17:30 ` syzbot
2020-02-23 17:30 ` syzbot
2020-09-26  2:03 ` syzbot
2020-09-26  2:03   ` syzbot
2020-09-26  2:03   ` syzbot
2020-09-26 16:25   ` Tetsuo Handa
2020-09-26 16:25     ` Tetsuo Handa
2020-09-26 16:25     ` Tetsuo Handa
2020-09-26 19:39     ` Peilin Ye [this message]
2020-09-26 19:39       ` Peilin Ye
2020-09-26 19:39       ` Peilin Ye
2020-09-27  0:25     ` Tetsuo Handa
2020-09-27  0:25       ` Tetsuo Handa
2020-09-27  0:25       ` Tetsuo Handa
2020-09-27  8:28       ` Tetsuo Handa
2020-09-27  8:28         ` Tetsuo Handa
2020-09-27  8:28         ` Tetsuo Handa
2020-09-27  9:27         ` Peilin Ye
2020-09-27  9:27           ` Peilin Ye
2020-09-27  9:27           ` Peilin Ye
2020-09-27 11:46           ` [PATCH] vt_ioctl: make VT_RESIZEX behave like VT_RESIZE Tetsuo Handa
2020-09-27 11:46             ` Tetsuo Handa
2020-09-27 11:46             ` Tetsuo Handa
2020-09-27 12:06             ` Greg KH
2020-09-27 12:06               ` Greg KH
2020-09-27 12:06               ` Greg KH
2020-09-28 17:59             ` Martin Hostettler
2020-09-28 17:59               ` Martin Hostettler
2020-09-28 17:59               ` Martin Hostettler
2020-09-29  1:12               ` Tetsuo Handa
2020-09-29  1:12                 ` Tetsuo Handa
2020-09-29  1:12                 ` Tetsuo Handa
2020-09-29 10:52                 ` Martin Hostettler
2020-09-29 10:52                   ` Martin Hostettler
2020-09-29 10:52                   ` Martin Hostettler
2020-09-29 16:56                   ` Daniel Vetter
2020-09-29 16:56                     ` Daniel Vetter
2020-09-29 16:56                     ` Daniel Vetter
2020-09-29 17:10                     ` Greg KH
2020-09-29 17:10                       ` Greg KH
2020-09-29 17:10                       ` Greg KH
2021-04-11 21:43                       ` Maciej W. Rozycki
2021-04-11 21:43                         ` Maciej W. Rozycki
2021-04-11 22:15                         ` Linus Torvalds
2021-04-11 22:15                           ` Linus Torvalds
2021-04-12  7:01                           ` Daniel Vetter
2021-04-12  7:01                             ` Daniel Vetter
2021-04-12 13:30                             ` Maciej W. Rozycki
2021-04-12 13:30                               ` Maciej W. Rozycki
2020-10-19 17:02             ` [tip: perf/urgent] " tip-bot2 for Tetsuo Handa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200926193957.GA1033221@PWN \
    --to=yepeilin.cs@gmail.com \
    --cc=b.zolnierkie@samsung.com \
    --cc=daniel.vetter@ffwll.ch \
    --cc=deller@gmx.de \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jirislaby@kernel.org \
    --cc=linux-fbdev@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=penguin-kernel@i-love.sakura.ne.jp \
    --cc=syzbot+b308f5fd049fbbc6e74f@syzkaller.appspotmail.com \
    --cc=syzkaller-bugs@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.