From 4543fde75f1e4cb7c287780b64fcf1967fb1fa47 Mon Sep 17 00:00:00 2001 From: Charan Teja Kalla Date: Fri, 16 Dec 2022 12:52:28 +0530 Subject: [PATCH] ANDROID: page_pinner: prevent pp_buffer uninitialized access There is a race window between page_pinner_inited set and the pp_buffer initialization which cause accessing the pp_buffer->lock. Avoid this by moving the pp_buffer initialization to page_ext_ops->init() which sets the page_pinner_inited only after the pp_buffer is initialized. Race scenario: 1) init_page_pinner is called --> page_pinner_inited is set. 2) __alloc_contig_migrate_range --> __page_pinner_failure_detect() accesses the pp_buffer->lock(yet to be initialized). 3) Then the pp_buffer is allocated and initialized. Below is the issue call stack: spin_bug+0x0 _raw_spin_lock_irqsave+0x3c __page_pinner_failure_detect+0x110 __alloc_contig_migrate_range+0x1c4 alloc_contig_range+0x130 cma_alloc+0x170 dma_alloc_contiguous+0xa0 __dma_direct_alloc_pages+0x16c dma_direct_alloc+0x88 Bug: 259024332 Bug: 240196534 Change-Id: I6849ac4d944498b9a431b47cad7adc7903c9bbaa Signed-off-by: Charan Teja Kalla (cherry picked from commit d47c9481dafae5152bb1b036dad831317004060d) Signed-off-by: Georgi Djakov --- mm/page_pinner.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mm/page_pinner.c b/mm/page_pinner.c index 46a8571649d8..7ef84314c295 100644 --- a/mm/page_pinner.c +++ b/mm/page_pinner.c @@ -89,6 +89,16 @@ static void init_page_pinner(void) if (!page_pinner_enabled) return; + pp_buffer.buffer = kvmalloc_array(pp_buf_size, sizeof(*pp_buffer.buffer), + GFP_KERNEL); + if (!pp_buffer.buffer) { + pr_info("page_pinner disabled due to failure of buffer allocation\n"); + return; + } + + spin_lock_init(&pp_buffer.lock); + pp_buffer.index = 0; + register_failure_stack(); static_branch_enable(&page_pinner_inited); } @@ -399,16 +409,6 @@ static int __init page_pinner_init(void) if (!static_branch_unlikely(&page_pinner_inited)) return 0; - pp_buffer.buffer = kvmalloc_array(pp_buf_size, sizeof(*pp_buffer.buffer), - GFP_KERNEL); - if (!pp_buffer.buffer) { - pr_info("page_pinner disabled due to failure of buffer allocation\n"); - return 1; - } - - spin_lock_init(&pp_buffer.lock); - pp_buffer.index = 0; - pr_info("page_pinner enabled\n"); pp_debugfs_root = debugfs_create_dir("page_pinner", NULL);