lkml.org 
[lkml]   [2018]   [Nov]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.18 06/39] block: brd: associate with queue until adding disk
    Date
    From: Ming Lei <ming.lei@redhat.com>

    [ Upstream commit 153fcd5f6d93b8e1e4040b1337f564a10f8d93af ]

    brd_free() may be called in failure path on one brd instance which
    disk isn't added yet, so release handler of gendisk may free the
    associated request_queue early and causes the following use-after-free[1].

    This patch fixes this issue by associating gendisk with request_queue
    just before adding disk.

    [1] KASAN: use-after-free Read in del_timer_syncNon-volatile memory driver v1.3
    Linux agpgart interface v0.103
    [drm] Initialized vgem 1.0.0 20120112 for virtual device on minor 0
    usbcore: registered new interface driver udl
    ==================================================================
    BUG: KASAN: use-after-free in __lock_acquire+0x36d9/0x4c20
    kernel/locking/lockdep.c:3218
    Read of size 8 at addr ffff8801d1b6b540 by task swapper/0/1

    CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.19.0+ #88
    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
    Google 01/01/2011
    Call Trace:
    __dump_stack lib/dump_stack.c:77 [inline]
    dump_stack+0x244/0x39d lib/dump_stack.c:113
    print_address_description.cold.7+0x9/0x1ff mm/kasan/report.c:256
    kasan_report_error mm/kasan/report.c:354 [inline]
    kasan_report.cold.8+0x242/0x309 mm/kasan/report.c:412
    __asan_report_load8_noabort+0x14/0x20 mm/kasan/report.c:433
    __lock_acquire+0x36d9/0x4c20 kernel/locking/lockdep.c:3218
    lock_acquire+0x1ed/0x520 kernel/locking/lockdep.c:3844
    del_timer_sync+0xb7/0x270 kernel/time/timer.c:1283
    blk_cleanup_queue+0x413/0x710 block/blk-core.c:809
    brd_free+0x5d/0x71 drivers/block/brd.c:422
    brd_init+0x2eb/0x393 drivers/block/brd.c:518
    do_one_initcall+0x145/0x957 init/main.c:890
    do_initcall_level init/main.c:958 [inline]
    do_initcalls init/main.c:966 [inline]
    do_basic_setup init/main.c:984 [inline]
    kernel_init_freeable+0x5c6/0x6b9 init/main.c:1148
    kernel_init+0x11/0x1ae init/main.c:1068
    ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:350

    Reported-by: syzbot+3701447012fe951dabb2@syzkaller.appspotmail.com
    Signed-off-by: Ming Lei <ming.lei@redhat.com>
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/block/brd.c | 16 +++++++++++-----
    1 file changed, 11 insertions(+), 5 deletions(-)

    diff --git a/drivers/block/brd.c b/drivers/block/brd.c
    index bb976598ee43..739f8dfd6fd7 100644
    --- a/drivers/block/brd.c
    +++ b/drivers/block/brd.c
    @@ -396,15 +396,14 @@ static struct brd_device *brd_alloc(int i)
    disk->first_minor = i * max_part;
    disk->fops = &brd_fops;
    disk->private_data = brd;
    - disk->queue = brd->brd_queue;
    disk->flags = GENHD_FL_EXT_DEVT;
    sprintf(disk->disk_name, "ram%d", i);
    set_capacity(disk, rd_size * 2);
    - disk->queue->backing_dev_info->capabilities |= BDI_CAP_SYNCHRONOUS_IO;
    + brd->brd_queue->backing_dev_info->capabilities |= BDI_CAP_SYNCHRONOUS_IO;

    /* Tell the block layer that this is not a rotational device */
    - blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
    - blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue);
    + blk_queue_flag_set(QUEUE_FLAG_NONROT, brd->brd_queue);
    + blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, brd->brd_queue);

    return brd;

    @@ -436,6 +435,7 @@ static struct brd_device *brd_init_one(int i, bool *new)

    brd = brd_alloc(i);
    if (brd) {
    + brd->brd_disk->queue = brd->brd_queue;
    add_disk(brd->brd_disk);
    list_add_tail(&brd->brd_list, &brd_devices);
    }
    @@ -503,8 +503,14 @@ static int __init brd_init(void)

    /* point of no return */

    - list_for_each_entry(brd, &brd_devices, brd_list)
    + list_for_each_entry(brd, &brd_devices, brd_list) {
    + /*
    + * associate with queue just before adding disk for
    + * avoiding to mess up failure path
    + */
    + brd->brd_disk->queue = brd->brd_queue;
    add_disk(brd->brd_disk);
    + }

    blk_register_region(MKDEV(RAMDISK_MAJOR, 0), 1UL << MINORBITS,
    THIS_MODULE, brd_probe, NULL, NULL);
    --
    2.17.1
    \
     
     \ /
      Last update: 2018-11-13 06:51    [W:4.381 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site