linux-imx/block
Vegard Nossum 8b85bc8b9e block: fix use-after-free in seq file
commit 77da160530 upstream.

I got a KASAN report of use-after-free:

    ==================================================================
    BUG: KASAN: use-after-free in klist_iter_exit+0x61/0x70 at addr ffff8800b6581508
    Read of size 8 by task trinity-c1/315
    =============================================================================
    BUG kmalloc-32 (Not tainted): kasan: bad access detected
    -----------------------------------------------------------------------------

    Disabling lock debugging due to kernel taint
    INFO: Allocated in disk_seqf_start+0x66/0x110 age=144 cpu=1 pid=315
            ___slab_alloc+0x4f1/0x520
            __slab_alloc.isra.58+0x56/0x80
            kmem_cache_alloc_trace+0x260/0x2a0
            disk_seqf_start+0x66/0x110
            traverse+0x176/0x860
            seq_read+0x7e3/0x11a0
            proc_reg_read+0xbc/0x180
            do_loop_readv_writev+0x134/0x210
            do_readv_writev+0x565/0x660
            vfs_readv+0x67/0xa0
            do_preadv+0x126/0x170
            SyS_preadv+0xc/0x10
            do_syscall_64+0x1a1/0x460
            return_from_SYSCALL_64+0x0/0x6a
    INFO: Freed in disk_seqf_stop+0x42/0x50 age=160 cpu=1 pid=315
            __slab_free+0x17a/0x2c0
            kfree+0x20a/0x220
            disk_seqf_stop+0x42/0x50
            traverse+0x3b5/0x860
            seq_read+0x7e3/0x11a0
            proc_reg_read+0xbc/0x180
            do_loop_readv_writev+0x134/0x210
            do_readv_writev+0x565/0x660
            vfs_readv+0x67/0xa0
            do_preadv+0x126/0x170
            SyS_preadv+0xc/0x10
            do_syscall_64+0x1a1/0x460
            return_from_SYSCALL_64+0x0/0x6a

    CPU: 1 PID: 315 Comm: trinity-c1 Tainted: G    B           4.7.0+ #62
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
     ffffea0002d96000 ffff880119b9f918 ffffffff81d6ce81 ffff88011a804480
     ffff8800b6581500 ffff880119b9f948 ffffffff8146c7bd ffff88011a804480
     ffffea0002d96000 ffff8800b6581500 fffffffffffffff4 ffff880119b9f970
    Call Trace:
     [<ffffffff81d6ce81>] dump_stack+0x65/0x84
     [<ffffffff8146c7bd>] print_trailer+0x10d/0x1a0
     [<ffffffff814704ff>] object_err+0x2f/0x40
     [<ffffffff814754d1>] kasan_report_error+0x221/0x520
     [<ffffffff8147590e>] __asan_report_load8_noabort+0x3e/0x40
     [<ffffffff83888161>] klist_iter_exit+0x61/0x70
     [<ffffffff82404389>] class_dev_iter_exit+0x9/0x10
     [<ffffffff81d2e8ea>] disk_seqf_stop+0x3a/0x50
     [<ffffffff8151f812>] seq_read+0x4b2/0x11a0
     [<ffffffff815f8fdc>] proc_reg_read+0xbc/0x180
     [<ffffffff814b24e4>] do_loop_readv_writev+0x134/0x210
     [<ffffffff814b4c45>] do_readv_writev+0x565/0x660
     [<ffffffff814b8a17>] vfs_readv+0x67/0xa0
     [<ffffffff814b8de6>] do_preadv+0x126/0x170
     [<ffffffff814b92ec>] SyS_preadv+0xc/0x10

This problem can occur in the following situation:

open()
 - pread()
    - .seq_start()
       - iter = kmalloc() // succeeds
       - seqf->private = iter
    - .seq_stop()
       - kfree(seqf->private)
 - pread()
    - .seq_start()
       - iter = kmalloc() // fails
    - .seq_stop()
       - class_dev_iter_exit(seqf->private) // boom! old pointer

As the comment in disk_seqf_stop() says, stop is called even if start
failed, so we need to reinitialise the private pointer to NULL when seq
iteration stops.

An alternative would be to set the private pointer to NULL when the
kmalloc() in disk_seqf_start() fails.

Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@fb.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
2016-08-19 09:51:06 +02:00
..
partitions mac: validate mac_partition is within sector 2016-03-03 12:45:57 +01:00
blk-cgroup.c blkcg: fix gendisk reference leak in blkg_conf_prep() 2015-08-19 08:36:39 +02:00
blk-cgroup.h blkcg: fix use-after-free in __blkg_release_rcu() by making blkcg_gq refcnt an atomic_t 2014-07-18 15:51:04 +02:00
blk-core.c SCSI: Fix NULL pointer dereference in runtime PM 2016-02-24 10:23:26 +01:00
blk-exec.c If the queue is dying then we only call the rq->end_io callout. 2013-09-18 08:33:55 -06:00
blk-flush.c Block: blk-flush: Fixed indent code style 2013-03-22 12:22:51 -06:00
blk-integrity.c scatterlist: introduce sg_unmark_end 2013-03-20 15:43:04 +10:30
blk-ioc.c lib/radix-tree.c: make radix_tree_node_alloc() work correctly within interrupt 2013-09-11 15:59:36 -07:00
blk-iopoll.c block: delete __cpuinit usage from all block files 2013-07-14 19:36:59 -04:00
blk-lib.c block: add cond_resched() to potentially long running ioctl discard loop 2014-02-22 13:32:28 -08:00
blk-map.c block: re-use existing 'reading' variable instead of checking direction again 2011-12-21 15:27:24 +01:00
blk-merge.c scatterlist: introduce sg_unmark_end 2013-03-20 15:43:04 +10:30
blk-settings.c block: fix alignment_offset math that assumes io_min is a power-of-2 2014-11-13 19:02:21 +01:00
blk-softirq.c block: delete __cpuinit usage from all block files 2013-07-14 19:36:59 -04:00
blk-sysfs.c block/blk-sysfs.c: replace strict_strtoul() with kstrtoul() 2013-09-11 15:56:56 -07:00
blk-tag.c block: don't assume last put of shared tags is for the host 2014-07-30 11:15:55 +02:00
blk-throttle.c blk-throttle: check stats_cpu before reading it from sysfs 2015-03-05 15:37:11 +01:00
blk-timeout.c block: fix race between request completion and timeout handling 2013-11-29 11:28:06 -08:00
blk.h block: __elv_next_request() shouldn't call into the elevator if bypassing 2014-02-22 13:32:28 -08:00
bsg-lib.c bsg: Remove unused function bsg_goose_queue() 2012-12-06 14:33:02 +01:00
bsg.c hlist: drop the node parameter from iterators 2013-02-27 19:10:24 -08:00
cfq-iosched.c cfq-iosched: fix incorrect filing of rt async cfqq 2015-03-01 23:34:19 +01:00
cmdline-parser.c block: support embedded device command line partition 2013-09-11 15:56:57 -07:00
compat_ioctl.c block: provide compat ioctl for BLKZEROOUT 2014-07-30 11:15:55 +02:00
deadline-iosched.c block: Convert kmalloc_node(...GFP_ZERO...) to kzalloc_node(...) 2013-09-11 13:22:03 -06:00
elevator.c elevator: acquire q->sysfs_lock in elevator_change() 2013-12-08 07:29:16 -08:00
genhd.c block: fix use-after-free in seq file 2016-08-19 09:51:06 +02:00
ioctl.c Merge branch 'for-3.7/core' of git://git.kernel.dk/linux-block 2012-10-11 09:04:23 +09:00
Kconfig block: change config option name for cmdline partition parsing 2013-09-30 14:31:02 -07:00
Kconfig.iosched blkcg: make CONFIG_BLK_CGROUP bool 2012-03-06 21:27:21 +01:00
Makefile block: change config option name for cmdline partition parsing 2013-09-30 14:31:02 -07:00
noop-iosched.c elevator: Fix a race in elevator switching 2013-07-03 13:25:24 +02:00
partition-generic.c block: Fix dev_t minor allocation lifetime 2014-10-13 15:41:19 +02:00
scsi_ioctl.c scsi: Fix error handling in SCSI_IOCTL_SEND_COMMAND 2014-11-13 19:02:57 +01:00