Re: [PATCH] mm/sparse: Fix kernel crash with pfn_section_valid check
From: Michal Hocko <mhocko@kernel.org>
Date: 2020-03-26 10:16:36
Also in:
linux-mm, lkml
On Thu 26-03-20 15:26:22, Aneesh Kumar K.V wrote:
On 3/26/20 3:10 PM, Michal Hocko wrote:quoted
On Wed 25-03-20 08:49:14, Aneesh Kumar K.V wrote:quoted
Fixes the below crash BUG: Kernel NULL pointer dereference on read at 0x00000000 Faulting instruction address: 0xc000000000c3447c Oops: Kernel access of bad area, sig: 11 [#1] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries CPU: 11 PID: 7519 Comm: lt-ndctl Not tainted 5.6.0-rc7-autotest #1 ... NIP [c000000000c3447c] vmemmap_populated+0x98/0xc0 LR [c000000000088354] vmemmap_free+0x144/0x320 Call Trace: section_deactivate+0x220/0x240It would be great to match this to the specific source code.The crash is due to NULL dereference at test_bit(idx, ms->usage->subsection_map); due to ms->usage = NULL;
It would be nice to call that out here as well [...]
quoted
Why do we have to free usage before deactivaing section memmap? Now that we have a late section_mem_map reset shouldn't we tear down the usage in the same branch?We still need to make the section invalid before we call into depopulate_section_memmap(). Because architecture like powerpc can share vmemmap area across sections (16MB mapping of vmemmap area) and we use vmemmap_popluated() to make that decision.
This should be noted in a comment as well.
quoted
quoted
Fixes: d41e2f3bd546 ("mm/hotplug: fix hot remove failure in SPARSEMEM|!VMEMMAP case") Cc: Baoquan He <redacted> Reported-by: Sachin Sant <redacted> Signed-off-by: Aneesh Kumar K.V <redacted> --- mm/sparse.c | 2 ++ 1 file changed, 2 insertions(+)diff --git a/mm/sparse.c b/mm/sparse.c index aadb7298dcef..3012d1f3771a 100644 --- a/mm/sparse.c +++ b/mm/sparse.c@@ -781,6 +781,8 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, ms->usage = NULL; } memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr); + /* Mark the section invalid */ + ms->section_mem_map &= ~SECTION_HAS_MEM_MAP;Btw. this comment is not really helping at all.That is marking the section invalid so that static inline int valid_section(struct mem_section *section) { return (section && (section->section_mem_map & SECTION_HAS_MEM_MAP)); } returns false.
Yes that is obvious once you are clear where to look. I was really hoping for a comment that would simply point you to the right direcection without chasing SECTION_HAS_MEM_MAP usage. This code is subtle and useful comments, even when they state something that is obvious to you _right_now_, can be really helpful. Thanks! -- Michal Hocko SUSE Labs