• M
    mm: bootmem: fix free_all_bootmem_core() with odd bitmap alignment · 10d73e65
    Max Filippov 提交于
    Currently free_all_bootmem_core ignores that node_min_pfn may be not
    multiple of BITS_PER_LONG.  Eg commit 6dccdcbe ("mm: bootmem: fix
    checking the bitmap when finally freeing bootmem") shifts vec by lower
    bits of start instead of lower bits of idx.  Also
    
      if (IS_ALIGNED(start, BITS_PER_LONG) && vec == ~0UL)
    
    assumes that vec bit 0 corresponds to start pfn, which is only true when
    node_min_pfn is a multiple of BITS_PER_LONG.  Also loop in the else
    clause can double-free pages (e.g.  with node_min_pfn == start == 1,
    map[0] == ~0 on 32-bit machine page 32 will be double-freed).
    
    This bug causes the following message during xtensa kernel boot:
    
      bootmem::free_all_bootmem_core nid=0 start=1 end=8000
      BUG: Bad page state in process swapper  pfn:00001
      page:d04bd020 count:0 mapcount:-127 mapping:  (null) index:0x2
      page flags: 0x0()
      Call Trace:
        bad_page+0x8c/0x9c
        free_pages_prepare+0x5e/0x88
        free_hot_cold_page+0xc/0xa0
        __free_pages+0x24/0x38
        __free_pages_bootmem+0x54/0x56
        free_all_bootmem_core$part$11+0xeb/0x138
        free_all_bootmem+0x46/0x58
        mem_init+0x25/0xa4
        start_kernel+0x11e/0x25c
        should_never_return+0x0/0x3be7
    
    The fix is the following:
     - always align vec so that its bit 0 corresponds to start
     - provide BITS_PER_LONG bits in vec, if those bits are available in the
       map
     - don't free pages past next start position in the else clause.
    Signed-off-by: NMax Filippov <jcmvbkbc@gmail.com>
    Cc: Gavin Shan <shangw@linux.vnet.ibm.com>
    Cc: Johannes Weiner <hannes@cmpxchg.org>
    Cc: Tejun Heo <tj@kernel.org>
    Cc: Yinghai Lu <yinghai@kernel.org>
    Cc: Joonsoo Kim <js1304@gmail.com>
    Cc: Prasad Koya <prasad.koya@gmail.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
    10d73e65
bootmem.c 21.1 KB