OSDN Git Service

drivers: dma-removed: fix signedness issue
authorSrinivasarao P <spathi@codeaurora.org>
Mon, 13 Aug 2018 12:21:11 +0000 (17:51 +0530)
committerGerrit - the friendly Code Review server <code-review@localhost>
Fri, 14 Sep 2018 05:08:39 +0000 (22:08 -0700)
Large values returned by bitmap_find_next_zero_area() can overflow
and become negative when stored in signed variable 'pageno' that
can lead to failure of condition 'pageno < dma_mem->nr_pages'.

Due to this, Use-after-free issue is observed in bitmap_set(),
When user requests to allocate large size buffer using ion calls.

BUG: KASAN: use-after-free in bitmap_set+0x9c/0xd4 at addr ffffffe774946cc0
Read of size 8 by task syz-executor0/19717
page:ffffffbe5dd25180 count:0 mapcount:-127 mapping:(null)
index:0xffffffe774947000 flags: 0x0()
page dumped because: kasan: bad access detected
page_owner info is not active (free page?)
CPU: 3 PID: 19717 Comm: syz-executor0 Tainted: G        W       4.4.78+ #1
Call trace:
[<ffffffa10c68b6fc>] dump_backtrace+0x0/0x2fc
[<ffffffa10c68ba1c>] show_stack+0x24/0x30
[<ffffffa10cc29a34>] dump_stack+0xdc/0x134
[<ffffffa10c8b2c10>] kasan_report+0x380/0x508
[<ffffffa10c8b1f38>] __asan_load8+0x24/0x80
[<ffffffa10cc42218>] bitmap_set+0x9c/0xd4
[<ffffffa10d15941c>] removed_alloc+0x188/0x5e4
[<ffffffa10dba4f40>] ion_cma_allocate+0x164/0x3e0
[<ffffffa10db9cef4>] __ion_alloc+0x368/0x1044
[<ffffffa10db9e0c8>] ion_ioctl+0x25c/0x6ac
[<ffffffa10c8e2f40>] do_vfs_ioctl+0x844/0x9a8
[<ffffffa10c8e311c>] SyS_ioctl+0x78/0xbc
[<ffffffa10c683730>] el0_svc_naked+0x24/0x28

Change-Id: Ibbaa451250bdfa9ce2a6e2cb9d2ee357ee0c8385
Signed-off-by: Srinivasarao P <spathi@codeaurora.org>
drivers/base/dma-removed.c

index 5fa3c6b..fd03c02 100644 (file)
@@ -222,11 +222,11 @@ void *removed_alloc(struct device *dev, size_t size, dma_addr_t *handle,
        bool no_kernel_mapping = dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING,
                                        attrs);
        bool skip_zeroing = dma_get_attr(DMA_ATTR_SKIP_ZEROING, attrs);
-       int pageno;
+       unsigned int pageno;
        unsigned long order;
        void *addr = NULL;
        struct removed_region *dma_mem = dev->removed_mem;
-       int nbits;
+       unsigned int nbits;
        unsigned int align;
 
        if (!gfpflags_allow_blocking(gfp))