Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0bc9f5d1 authored by Minchan Kim's avatar Minchan Kim Committed by Linus Torvalds
Browse files

drivers/block/zram/zram_drv.c: fix idle/writeback string compare

Makoto report a below KASAN error: zram does out-of-bounds read.  Because
strscpy copies from source up to count bytes unconditionally.  It could
cause out-of-bounds read on next object in slab.

To prevent it, use strlcpy which checks source's length automatically.

   BUG: KASAN: slab-out-of-bounds in strscpy+0x68/0x154
   Read of size 8 at addr ffffffc0c3495a00 by task system_server/1314
   ..
   Call trace:
     strscpy+0x68/0x154
     idle_store+0xc4/0x34c
     dev_attr_store+0x50/0x6c
     sysfs_kf_write+0x98/0xb4
     kernfs_fop_write+0x198/0x260
     __vfs_write+0x10c/0x338
     vfs_write+0x114/0x238
     SyS_write+0xc8/0x168
     __sys_trace_return+0x0/0x4

   Allocated by task 1314:
    __kmalloc+0x280/0x318
    kernfs_fop_write+0xac/0x260
    __vfs_write+0x10c/0x338
    vfs_write+0x114/0x238
    SyS_write+0xc8/0x168
    __sys_trace_return+0x0/0x4

   Freed by task 2855:
    kfree+0x138/0x630
    kernfs_put_open_node+0x10c/0x124
    kernfs_fop_release+0xd8/0x114
    __fput+0x130/0x2a4
    ____fput+0x1c/0x28
    task_work_run+0x16c/0x1c8
    do_notify_resume+0x2bc/0x107c
    work_pending+0x8/0x10

   The buggy address belongs to the object at ffffffc0c3495a00
    which belongs to the cache kmalloc-128 of size 128
   The buggy address is located 0 bytes inside of
    128-byte region [ffffffc0c3495a00, ffffffc0c3495a80)
   The buggy address belongs to the page:
   page:ffffffbf030d2500 count:1 mapcount:0 mapping:          (null) index:0x0 compound_mapcount: 0
   flags: 0x4000000000010200(slab|head)
   page dumped because: kasan: bad access detected

   Memory state around the buggy address:
    ffffffc0c3495900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    ffffffc0c3495980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
   >ffffffc0c3495a00: 04 fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
                      ^
    ffffffc0c3495a80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
    ffffffc0c3495b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Link: http://lkml.kernel.org/r/20190319231911.145968-1-minchan@kernel.org


Cc: <stable@vger.kernel.org>	[5.0]
Signed-off-by: default avatarMinchan Kim <minchan@kernel.org>
Reported-by: default avatarMakoto Wu <makotowu@google.com>
Reviewed-by: default avatarSergey Senozhatsky <sergey.senozhatsky@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f5777bc2
Loading
Loading
Loading
Loading
+6 −26
Original line number Diff line number Diff line
@@ -290,18 +290,8 @@ static ssize_t idle_store(struct device *dev,
	struct zram *zram = dev_to_zram(dev);
	unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
	int index;
	char mode_buf[8];
	ssize_t sz;

	sz = strscpy(mode_buf, buf, sizeof(mode_buf));
	if (sz <= 0)
		return -EINVAL;

	/* ignore trailing new line */
	if (mode_buf[sz - 1] == '\n')
		mode_buf[sz - 1] = 0x00;

	if (strcmp(mode_buf, "all"))
	if (!sysfs_streq(buf, "all"))
		return -EINVAL;

	down_read(&zram->init_lock);
@@ -635,25 +625,15 @@ static ssize_t writeback_store(struct device *dev,
	struct bio bio;
	struct bio_vec bio_vec;
	struct page *page;
	ssize_t ret, sz;
	char mode_buf[8];
	int mode = -1;
	ssize_t ret;
	int mode;
	unsigned long blk_idx = 0;

	sz = strscpy(mode_buf, buf, sizeof(mode_buf));
	if (sz <= 0)
		return -EINVAL;

	/* ignore trailing newline */
	if (mode_buf[sz - 1] == '\n')
		mode_buf[sz - 1] = 0x00;

	if (!strcmp(mode_buf, "idle"))
	if (sysfs_streq(buf, "idle"))
		mode = IDLE_WRITEBACK;
	else if (!strcmp(mode_buf, "huge"))
	else if (sysfs_streq(buf, "huge"))
		mode = HUGE_WRITEBACK;

	if (mode == -1)
	else
		return -EINVAL;

	down_read(&zram->init_lock);