提交 60141517 编写于 作者: Y Ye Bin 提交者: Zheng Zengkai

nbd: Fix use-after-free in blk_mq_free_rqs

hulk inclusion
category: bugfix
bugzilla: 185875 https://gitee.com/openeuler/kernel/issues/I4DDEL

-----------------------------------------------

We got issue as follows:
[  833.786542] nbd: failed to add new device
[  833.791613] ==================================================================
[  833.794918] BUG: KASAN: use-after-free in blk_mq_free_rqs+0x558/0x6c0
[  833.798108] Read of size 8 at addr ffff800109b7c288 by task kworker/0:3/113
[  833.804216] CPU: 0 PID: 113 Comm: kworker/0:3 Kdump: loaded Not tainted 4.19.90 #1
[  833.807635] Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
[  833.811798] Workqueue: events __blk_release_queue
[  833.815035] Call trace:
[  833.817964]  dump_backtrace+0x0/0x3c0
[  833.821070]  show_stack+0x28/0x38
[  833.824091]  dump_stack+0xfc/0x154
[  833.827042]  print_address_description+0x68/0x278
[  833.830147]  kasan_report+0x204/0x330
[  833.833121]  __asan_report_load8_noabort+0x30/0x40
[  833.836180]  blk_mq_free_rqs+0x558/0x6c0
[  833.839089]  blk_mq_sched_tags_teardown+0xf4/0x1c0
[  833.842035]  blk_mq_exit_sched+0x1b8/0x260
[  833.844878]  elevator_exit+0x114/0x148
[  833.847634]  blk_exit_queue+0x68/0xe8
[  833.850352]  __blk_release_queue+0xd0/0x408
[  833.853113]  process_one_work+0x55c/0x10d0
[  833.855864]  worker_thread+0x3d4/0xe30
[  833.858558]  kthread+0x2c8/0x348
[  833.861139]  ret_from_fork+0x10/0x18
[  833.863714]
[  833.866000] Allocated by task 186531:
[  833.868467]  kasan_kmalloc+0xe0/0x190
[  833.870936]  kmem_cache_alloc_trace+0x104/0x218
[  833.873483]  nbd_dev_add+0x54/0x760 [nbd]
[  833.875988]  nbd_genl_connect+0x3c4/0x1348 [nbd]
[  833.878591]  genl_family_rcv_msg+0x798/0xa10
[  833.881113]  genl_rcv_msg+0xc0/0x170
[  833.883489]  netlink_rcv_skb+0x1b4/0x370
[  833.885897]  genl_rcv+0x40/0x58
[  833.888225]  netlink_unicast+0x4bc/0x660
[  833.890661]  netlink_sendmsg+0x880/0xa60
[  833.893112]  sock_sendmsg+0xb8/0x110
[  833.895513]  ____sys_sendmsg+0x570/0x698
[  833.897927]  ___sys_sendmsg+0x108/0x188
[  833.900350]  __sys_sendmsg+0xe8/0x198
[  833.900360]  __arm64_sys_sendmsg+0x78/0xa8
[  833.906911]  el0_svc_common+0x10c/0x330
[  833.909289]  el0_svc_handler+0x60/0xd0
[  833.911660]  el0_svc+0x8/0x1b0
[  833.913963]
[  833.916117] Freed by task 186531:
[  833.918445]  __kasan_slab_free+0x120/0x228
[  833.920860]  kasan_slab_free+0x10/0x18
[  833.923193]  kfree+0x80/0x1f0
[  833.925392]  nbd_dev_add+0xf0/0x760 [nbd]
[  833.927686]  nbd_genl_connect+0x3c4/0x1348 [nbd]
[  833.929989]  genl_family_rcv_msg+0x798/0xa10
[  833.932231]  genl_rcv_msg+0xc0/0x170
[  833.934335]  netlink_rcv_skb+0x1b4/0x370
[  833.936444]  genl_rcv+0x40/0x58
[  833.938460]  netlink_unicast+0x4bc/0x660
[  833.940570]  netlink_sendmsg+0x880/0xa60
[  833.942682]  sock_sendmsg+0xb8/0x110
[  833.944745]  ____sys_sendmsg+0x570/0x698
[  833.946849]  ___sys_sendmsg+0x108/0x188
[  833.948924]  __sys_sendmsg+0xe8/0x198
[  833.950980]  __arm64_sys_sendmsg+0x78/0xa8
[  833.953059]  el0_svc_common+0x10c/0x330
[  833.955121]  el0_svc_handler+0x60/0xd0
[  833.957143]  el0_svc+0x8/0x1b0
[  833.959088]
[  833.960846] The buggy address belongs to the object at ffff800109b7c280
[  833.960846]  which belongs to the cache kmalloc-512 of size 512
[  833.965502] The buggy address is located 8 bytes inside of
[  833.965502]  512-byte region [ffff800109b7c280, ffff800109b7c480)
[  833.970108] The buggy address belongs to the page:
[  833.972390] page:ffff7e000426df00 count:1 mapcount:0 mapping:ffff8000c0003800 index:0x0 compound_mapcount: 0
[  833.975269] flags: 0x7ffff0000008100(slab|head)
[  833.977640] raw: 07ffff0000008100 ffff7e00035d1600 0000000200000002 ffff8000c0003800
[  833.980426] raw: 0000000000000000 00000000000c000c 00000001ffffffff 0000000000000000
[  833.983212] page dumped because: kasan: bad access detected
[  833.985778]
[  833.987935] Memory state around the buggy address:
[  833.990448]  ffff800109b7c180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  833.993265]  ffff800109b7c200: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  833.996097] >ffff800109b7c280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  833.998930]                       ^
[  834.001384]  ffff800109b7c300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  834.004329]  ffff800109b7c380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  834.007264] ==================================================================

As 98fd847a commit add check "disk->first_minor", if failed will
free tags and finally call put_disk will free request_queue.
blk_mq_free_tag_set
  blk_mq_free_map_and_requests
    blk_mq_free_rqs

put_disk:
__blk_release_queue
  blk_exit_queue
    elevator_exit
      blk_mq_exit_sched
        blk_mq_sched_tags_teardown
	  blk_mq_free_rqs -->will trigger UAF
To address this issue, just move 'disk->first_minor' check at the first
in nbd_dev_add.

Fixes:98fd847a("nbd: add sanity check for first_minor")
Signed-off-by: NYe Bin <yebin10@huawei.com>
Reviewed-by: NYu Kuai <yukuai3@huawei.com>
Reviewed-by: NJason Yan <yanaijie@huawei.com>
Signed-off-by: NChen Jun <chenjun102@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 0a6d21a3
...@@ -1758,6 +1758,15 @@ static int nbd_dev_add(int index) ...@@ -1758,6 +1758,15 @@ static int nbd_dev_add(int index)
struct gendisk *disk; struct gendisk *disk;
struct request_queue *q; struct request_queue *q;
int err = -ENOMEM; int err = -ENOMEM;
int first_minor = index << part_shift;
/*
* Too big index can cause duplicate creation of sysfs files/links,
* because MKDEV() expect that the max first minor is MINORMASK, or
* index << part_shift can overflow.
*/
if (first_minor < index || first_minor > MINORMASK)
return -EINVAL;
nbd = kzalloc(sizeof(struct nbd_device), GFP_KERNEL); nbd = kzalloc(sizeof(struct nbd_device), GFP_KERNEL);
if (!nbd) if (!nbd)
...@@ -1821,18 +1830,7 @@ static int nbd_dev_add(int index) ...@@ -1821,18 +1830,7 @@ static int nbd_dev_add(int index)
refcount_set(&nbd->refs, 1); refcount_set(&nbd->refs, 1);
INIT_LIST_HEAD(&nbd->list); INIT_LIST_HEAD(&nbd->list);
disk->major = NBD_MAJOR; disk->major = NBD_MAJOR;
disk->first_minor = first_minor;
/*
* Too big index can cause duplicate creation of sysfs files/links,
* because MKDEV() expect that the max first minor is MINORMASK, or
* index << part_shift can overflow.
*/
disk->first_minor = index << part_shift;
if (disk->first_minor < index || disk->first_minor > MINORMASK) {
err = -EINVAL;
goto out_free_tags;
}
disk->fops = &nbd_fops; disk->fops = &nbd_fops;
disk->private_data = nbd; disk->private_data = nbd;
sprintf(disk->disk_name, "nbd%d", index); sprintf(disk->disk_name, "nbd%d", index);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册