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 Change-Id: I6849ac4d944498b9a431b47cad7adc7903c9bbaa Signed-off-by: Charan Teja Kalla <quic_charante@quicinc.com>
This commit is contained in:
committed by
Suren Baghdasaryan
parent
8a57e65659
commit
c41503e313
@@ -88,6 +88,16 @@ static void init_page_pinner(void)
|
|||||||
if (!page_pinner_enabled)
|
if (!page_pinner_enabled)
|
||||||
return;
|
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();
|
register_failure_stack();
|
||||||
static_branch_enable(&page_pinner_inited);
|
static_branch_enable(&page_pinner_inited);
|
||||||
}
|
}
|
||||||
@@ -396,16 +406,6 @@ static int __init page_pinner_init(void)
|
|||||||
if (!static_branch_unlikely(&page_pinner_inited))
|
if (!static_branch_unlikely(&page_pinner_inited))
|
||||||
return 0;
|
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");
|
pr_info("page_pinner enabled\n");
|
||||||
|
|
||||||
pp_debugfs_root = debugfs_create_dir("page_pinner", NULL);
|
pp_debugfs_root = debugfs_create_dir("page_pinner", NULL);
|
||||||
|
|||||||
Reference in New Issue
Block a user