Re: blkdev loop UAF

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jan 11, 2018 at 06:00:08PM +0100, Jan Kara wrote:
> On Thu 11-01-18 19:22:39, Hou Tao wrote:
> > Hi,
> > 
> > On 2018/1/11 16:24, Dan Carpenter wrote:
> > > Thanks for your report and the patch.  I am sending it to the
> > > linux-block devs since it's already public.
> > > 
> > > regards,
> > > dan carpenter
> > 
> > The User-after-free problem is not specific for loop device, it can also
> > be reproduced on scsi device, and there are more race problems caused by
> > the race between bdev open and gendisk shutdown [1].
> > 
> > The cause of the UAF problem is that there are two instances of gendisk which share
> > the same bdev. After the process owning the new gendisk increases bdev->bd_openers,
> > the other process which owns the older gendisk will find bdev->bd_openers is not zero
> > and will put the last reference of the older gendisk and cause User-after-free.
> > 
> > I had proposed a patch for the problem, but it's still an incomplete fix for the race
> > between gendisk shutdown and bdev opening.
> > 
> > diff --git a/fs/block_dev.c b/fs/block_dev.c
> > index 4a181fc..5ecdb9f 100644
> > --- a/fs/block_dev.c
> > +++ b/fs/block_dev.c
> > @@ -1510,6 +1510,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
> >                 if (bdev->bd_bdi == &noop_backing_dev_info)
> >                         bdev->bd_bdi = bdi_get(disk->queue->backing_dev_info);
> >         } else {
> > +               if (bdev->bd_disk != disk) {
> > +                       ret = -ENXIO;
> > +                       goto out_unlock_bdev;
> > +               }
> > +
> >                 if (bdev->bd_contains == bdev) {
> >                         ret = 0;
> >                         if (bdev->bd_disk->fops->open)
> > 
> > 
> > As far as I know, Jan Kara is working on these problems. So, Jan, any suggestions ?
> 
> Yeah, thanks for the ping. I was working today to get this fixed. I have
> about 6 patches (attached) which should fix all the outstanding issues I'm
> aware of.  So far they are only boot tested. I will give them more
> stress-testing next week and then post them officially but if you have time,
> feel free to try them out as well. Thanks!
> 

Jan, are you still planning to fix this?  This was also reported by syzbot here:
https://groups.google.com/d/msg/syzkaller-bugs/9wXx4YULITQ/0SK8vqxhAgAJ.  Note
that the C reproducer attached to that report doesn't work for me anymore
following ae6650163c6 ("loop: fix concurrent lo_open/lo_release").  However,
syzbot has still hit this on more recent kernels.  Here's a C reproducer that
still works for me on Linus' tree as of today, though it can take 5-10 seconds:

#include <fcntl.h>
#include <linux/loop.h>
#include <sys/ioctl.h>
#include <unistd.h>

int main()
{
	int fd = open("/dev/loop-control", 0);

	if (!fork()) {
		for (;;)
			ioctl(fd, LOOP_CTL_ADD, 0);
	}

	if (!fork()) {
		for (;;)
			ioctl(fd, LOOP_CTL_REMOVE, 0);
	}

	fork();
	for (;;) {
		fd = open("/dev/loop0", O_EXCL);
		close(fd);
	}
}

This is the KASAN splat I get from the above:

BUG: KASAN: use-after-free in disk_unblock_events+0x3e/0x40 block/genhd.c:1672
Read of size 8 at addr ffff880030743670 by task systemd-udevd/165

CPU: 1 PID: 165 Comm: systemd-udevd Not tainted 4.15.0-08279-gfe53d1443a146 #38
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-20171110_100015-anatol 04/01/2014
Call Trace:
 __dump_stack lib/dump_stack.c:17 [inline]
 dump_stack+0xb3/0x145 lib/dump_stack.c:53
perf: interrupt took too long (7334 > 4816), lowering kernel.perf_event_max_sample_rate to 27000
 print_address_description+0x73/0x290 mm/kasan/report.c:252
 kasan_report_error mm/kasan/report.c:351 [inline]
 kasan_report+0x235/0x350 mm/kasan/report.c:409
 disk_unblock_events+0x3e/0x40 block/genhd.c:1672
 __blkdev_get+0x41b/0xd30 fs/block_dev.c:1535
 blkdev_get+0x283/0x980 fs/block_dev.c:1591
 do_dentry_open.isra.1+0x6c0/0xaf0 fs/open.c:752
 do_last fs/namei.c:3378 [inline]
 path_openat+0x587/0x28b0 fs/namei.c:3518
 do_filp_open+0x231/0x3a0 fs/namei.c:3553
 do_sys_open+0x399/0x610 fs/open.c:1059
 do_syscall_64+0x213/0x740 arch/x86/entry/common.c:285
 entry_SYSCALL64_slow_path+0x25/0x25
RIP: 0033:0x7f51d23262ce
RSP: 002b:00007ffdf1844310 EFLAGS: 00000246 ORIG_RAX: 0000000000000101
RAX: ffffffffffffffda RBX: 0000562878961d30 RCX: 00007f51d23262ce
RDX: 00000000000a0800 RSI: 0000562878974860 RDI: ffffffffffffff9c
RBP: 0000562878965150 R08: 00007f51d1c9d914 R09: ffffffffffffffb0
R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000000e
R13: 0000562878965150 R14: 0000000000000004 R15: 0000000000000003

Allocated by task 160:
 kmem_cache_alloc_node_trace include/linux/slab.h:413 [inline]
 kmalloc_node include/linux/slab.h:537 [inline]
 kzalloc_node include/linux/slab.h:699 [inline]
 __alloc_disk_node+0xb6/0x450 block/genhd.c:1415
 loop_add+0x3fd/0x9e0 drivers/block/loop.c:1814
 loop_probe+0x152/0x180 drivers/block/loop.c:1921
 kobj_lookup+0x176/0x310 drivers/base/map.c:124
 get_gendisk+0x28/0x290 block/genhd.c:804
 __blkdev_get+0x2ec/0xd30 fs/block_dev.c:1433
 blkdev_get+0x485/0x980 fs/block_dev.c:1591
 do_dentry_open.isra.1+0x6c0/0xaf0 fs/open.c:752
 do_last fs/namei.c:3378 [inline]
 path_openat+0x587/0x28b0 fs/namei.c:3518
 do_filp_open+0x231/0x3a0 fs/namei.c:3553
 do_sys_open+0x399/0x610 fs/open.c:1059
 entry_SYSCALL_64_fastpath+0x1e/0x8b

Freed by task 165:
 __cache_free mm/slab.c:3484 [inline]
 kfree+0x8a/0xd0 mm/slab.c:3799
 disk_release+0x2c3/0x380 block/genhd.c:1264
 device_release+0x6e/0x1d0 drivers/base/core.c:811
 kobject_cleanup lib/kobject.c:646 [inline]
 kobject_release lib/kobject.c:675 [inline]
 kref_put include/linux/kref.h:70 [inline]
 kobject_put+0x14c/0x400 lib/kobject.c:692
 __blkdev_get+0x39f/0xd30 fs/block_dev.c:1528
 blkdev_get+0x283/0x980 fs/block_dev.c:1591
 do_dentry_open.isra.1+0x6c0/0xaf0 fs/open.c:752
 do_last fs/namei.c:3378 [inline]
 path_openat+0x587/0x28b0 fs/namei.c:3518
 do_filp_open+0x231/0x3a0 fs/namei.c:3553
 do_sys_open+0x399/0x610 fs/open.c:1059
 do_syscall_64+0x213/0x740 arch/x86/entry/common.c:285
 return_from_SYSCALL_64+0x0/0x75

The buggy address belongs to the object at ffff880030743280
 which belongs to the cache kmalloc-2048 of size 2048
The buggy address is located 1008 bytes inside of
 2048-byte region [ffff880030743280, ffff880030743a80)
The buggy address belongs to the page:
page:ffffea0000a99670 count:1 mapcount:0 mapping:ffff880030742180 index:0x0 compound_mapcount: 0
flags: 0x100000000008100(slab|head)
raw: 0100000000008100 ffff880030742180 0000000000000000 0000000100000003
raw: ffffea0000b895a0 ffffea0000b91720 ffff880036000800
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff880030743500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff880030743580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff880030743600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                                                             ^
 ffff880030743680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff880030743700: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb



[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux