From: Yang Yingliang yangyingliang@huawei.com
hulk inclusion category: bugfix bugzilla: 47452 CVE: NA
-------------------------------------------------
In fast path of slab_alloc_node(), interrupt is not disabled, after get object and page, they may be changed beacuse memory will be allocated in interrupt context, it cause check_valid_pointer() report corrupted freelist wrongly. So compare next object with magic number directly to avoid the crash caused by using connnector.
[22635000.696206] Unable to handle kernel paging request at virtual address 000000030000004c [22635000.704370] Mem abort info: [22635000.707417] ESR = 0x96000004 [22635000.710723] Exception class = DABT (current EL), IL = 32 bits [22635000.716878] SET = 0, FnV = 0 [22635000.720183] EA = 0, S1PTW = 0 [22635000.723575] Data abort info: [22635000.726709] ISV = 0, ISS = 0x00000004 [22635000.730792] CM = 0, WnR = 0 [22635000.734011] user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000cfe46aff [22635000.740859] [000000030000004c] pgd=0000000000000000 [22635000.745980] Internal error: Oops: 96000004 [#1] SMP [22635000.751094] Process thread-pool-6 (pid: 44316, stack limit = 0x00000000378f8b35) [22635000.758717] CPU: 49 PID: 44316 Comm: thread-pool-6 Kdump: loaded Tainted: G OE K 4.19.36 #1 [22635000.771695] Hardware name: Huawei TaiShan 2280 V2/BC82AMDD, BIOS 1.05 09/18/2019 [22635000.779314] pstate: 60400009 (nZCv daif +PAN -UAO) [22635000.784348] pc : __kmalloc_node_track_caller+0x214/0x348 [22635000.789894] lr : __kmalloc_node_track_caller+0x6c/0x348
Besides, add page check, before using it to print message and add WARN to track stack.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Cheng Jian cj.chengjian@huawei.com --- mm/slub.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/mm/slub.c b/mm/slub.c index 45b5353e0938..4b681e71ba8c 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1359,15 +1359,19 @@ static bool isolate_corrupted_freelist(struct kmem_cache *s, struct page *page, void **freelist, void *next) { if (sysctl_isolate_corrupted_freelist && - (!check_valid_pointer(s, page, next))) { + (unsigned long)next == 0x30000004cul) { /* Need caller make sure freelist is not NULL */ *freelist = NULL; isolate_cnt++;
slab_fix(s, "Freelist corrupt,isolate corrupted freechain."); - pr_info("freelist=%lx object=%lx, page->base=%lx, page->objects=%u, objsize=%u, s->offset=%d page:%llx\n", - (long)freelist, (long)next, (long)page_address(page), page->objects, s->size, s->offset, (u64)page); - + if (page) + pr_info("freelist=%lx object=%lx, page->base=%lx, page->objects=%u, objsize=%u, s->offset=%d page:%llx\n", + (long)freelist, (long)next, (long)page_address(page), page->objects, s->size, s->offset, (u64)page); + else + pr_info("freelist=%lx object=%lx, objsize=%u, s->offset=%d\n", + (long)freelist, (long)next, s->size, s->offset); + WARN_ON(1); return true; }