summaryrefslogtreecommitdiffstats
path: root/drivers/block/zram
diff options
context:
space:
mode:
authorMinchan Kim <minchan@kernel.org>2019-03-28 23:44:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-29 13:01:37 -0400
commit0bc9f5d14a93971c6cd9c0d81b0fc154fc54c65d (patch)
tree08c1ddd4f286cf5631494364f1e87231e19eb5e6 /drivers/block/zram
parentf5777bc2d9cf0712554228b1a7927b6f13f5c1f0 (diff)
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: Minchan Kim <minchan@kernel.org> Reported-by: Makoto Wu <makotowu@google.com> Reviewed-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/block/zram')
-rw-r--r--drivers/block/zram/zram_drv.c32
1 files changed, 6 insertions, 26 deletions
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index e7a5f1d1c314..399cad7daae7 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -290,18 +290,8 @@ static ssize_t idle_store(struct device *dev,
290 struct zram *zram = dev_to_zram(dev); 290 struct zram *zram = dev_to_zram(dev);
291 unsigned long nr_pages = zram->disksize >> PAGE_SHIFT; 291 unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
292 int index; 292 int index;
293 char mode_buf[8];
294 ssize_t sz;
295 293
296 sz = strscpy(mode_buf, buf, sizeof(mode_buf)); 294 if (!sysfs_streq(buf, "all"))
297 if (sz <= 0)
298 return -EINVAL;
299
300 /* ignore trailing new line */
301 if (mode_buf[sz - 1] == '\n')
302 mode_buf[sz - 1] = 0x00;
303
304 if (strcmp(mode_buf, "all"))
305 return -EINVAL; 295 return -EINVAL;
306 296
307 down_read(&zram->init_lock); 297 down_read(&zram->init_lock);
@@ -635,25 +625,15 @@ static ssize_t writeback_store(struct device *dev,
635 struct bio bio; 625 struct bio bio;
636 struct bio_vec bio_vec; 626 struct bio_vec bio_vec;
637 struct page *page; 627 struct page *page;
638 ssize_t ret, sz; 628 ssize_t ret;
639 char mode_buf[8]; 629 int mode;
640 int mode = -1;
641 unsigned long blk_idx = 0; 630 unsigned long blk_idx = 0;
642 631
643 sz = strscpy(mode_buf, buf, sizeof(mode_buf)); 632 if (sysfs_streq(buf, "idle"))
644 if (sz <= 0)
645 return -EINVAL;
646
647 /* ignore trailing newline */
648 if (mode_buf[sz - 1] == '\n')
649 mode_buf[sz - 1] = 0x00;
650
651 if (!strcmp(mode_buf, "idle"))
652 mode = IDLE_WRITEBACK; 633 mode = IDLE_WRITEBACK;
653 else if (!strcmp(mode_buf, "huge")) 634 else if (sysfs_streq(buf, "huge"))
654 mode = HUGE_WRITEBACK; 635 mode = HUGE_WRITEBACK;
655 636 else
656 if (mode == -1)
657 return -EINVAL; 637 return -EINVAL;
658 638
659 down_read(&zram->init_lock); 639 down_read(&zram->init_lock);