Re: io_submit with slab free object overwritten

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

 



Qian Cai <cai@xxxxxx> writes:

> This is only reproducible on linux-next (20190221), as v5.0-rc7 is fine. Running
> two LTP tests and then reboot will trigger this on ppc64le (CONFIG_IO_URING=n
> and CONFIG_SHUFFLE_PAGE_ALLOCATOR=y).
>
> # fgetxattr02
> # io_submit01
> # systemctl reboot
>
> There is a 32-bit (with all ones) overwritten of free slab objects (poisoned).
>
> [23424.121182] BUG aio_kiocb (Tainted: G    B   W    L   ): Poison overwritten
> [23424.121189]
> -----------------------------------------------------------------------------
> [23424.121189]
> [23424.121197] INFO: 0x000000009f1f5145-0x00000000841e301b. First byte 0xff
> instead of 0x6b
> [23424.121205] INFO: Allocated in io_submit_one+0x9c/0xb20 age=0 cpu=7 pid=12174
> [23424.121212]  __slab_alloc+0x34/0x60
> [23424.121217]  kmem_cache_alloc+0x504/0x5c0
> [23424.121221]  io_submit_one+0x9c/0xb20
> [23424.121224]  sys_io_submit+0xe0/0x350
> [23424.121227]  system_call+0x5c/0x70
> [23424.121231] INFO: Freed in aio_complete+0x31c/0x410 age=0 cpu=7 pid=12174
> [23424.121234]  kmem_cache_free+0x4bc/0x540
> [23424.121237]  aio_complete+0x31c/0x410
> [23424.121240]  blkdev_bio_end_io+0x238/0x3e0
> [23424.121243]  bio_endio.part.3+0x214/0x330
> [23424.121247]  brd_make_request+0x2d8/0x314 [brd]

Yeah, the ramdisk is synchronous, so I/O completes in the issuing
context.  I guess we could also see a problem with an error in the issue
path, and regular storage.

That -1 probably comes from this:

@@ -412,6 +420,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
                                bio->bi_opf |= REQ_HIPRI;
 
                        qc = submit_bio(bio);
+                       WRITE_ONCE(iocb->ki_cookie, qc);

#define BLK_QC_T_NONE           -1U

Use after free.  Further down the function, we also reference the iocb,
though:

        if (!is_sync)
                return -EIOCBQUEUED;

        for (;;) {
                set_current_state(TASK_UNINTERRUPTIBLE);
                if (!READ_ONCE(dio->waiter))
                        break;

                if (!(iocb->ki_flags & IOCB_HIPRI) ||
                    !blk_poll(bdev_get_queue(bdev), qc, true))
                        io_schedule();
        }

So I guess a bit more auditing is required.

-Jeff




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux