diff options
author | Minchan Kim <minchan@kernel.org> | 2019-03-28 23:44:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-29 13:01:37 -0400 |
commit | 0bc9f5d14a93971c6cd9c0d81b0fc154fc54c65d (patch) | |
tree | 08c1ddd4f286cf5631494364f1e87231e19eb5e6 /drivers/block/zram | |
parent | f5777bc2d9cf0712554228b1a7927b6f13f5c1f0 (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.c | 32 |
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); |