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

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
...@@ -290,18 +290,8 @@ static ssize_t idle_store(struct device *dev, ...@@ -290,18 +290,8 @@ static ssize_t idle_store(struct device *dev,
struct zram *zram = dev_to_zram(dev); struct zram *zram = dev_to_zram(dev);
unsigned long nr_pages = zram->disksize >> PAGE_SHIFT; unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
int index; int index;
char mode_buf[8];
ssize_t sz;
sz = strscpy(mode_buf, buf, sizeof(mode_buf)); if (!sysfs_streq(buf, "all"))
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"))
return -EINVAL; return -EINVAL;
down_read(&zram->init_lock); down_read(&zram->init_lock);
...@@ -635,25 +625,15 @@ static ssize_t writeback_store(struct device *dev, ...@@ -635,25 +625,15 @@ static ssize_t writeback_store(struct device *dev,
struct bio bio; struct bio bio;
struct bio_vec bio_vec; struct bio_vec bio_vec;
struct page *page; struct page *page;
ssize_t ret, sz; ssize_t ret;
char mode_buf[8]; int mode;
int mode = -1;
unsigned long blk_idx = 0; unsigned long blk_idx = 0;
sz = strscpy(mode_buf, buf, sizeof(mode_buf)); if (sysfs_streq(buf, "idle"))
if (sz <= 0)
return -EINVAL;
/* ignore trailing newline */
if (mode_buf[sz - 1] == '\n')
mode_buf[sz - 1] = 0x00;
if (!strcmp(mode_buf, "idle"))
mode = IDLE_WRITEBACK; mode = IDLE_WRITEBACK;
else if (!strcmp(mode_buf, "huge")) else if (sysfs_streq(buf, "huge"))
mode = HUGE_WRITEBACK; mode = HUGE_WRITEBACK;
else
if (mode == -1)
return -EINVAL; return -EINVAL;
down_read(&zram->init_lock); down_read(&zram->init_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment