Skip to content
  • Michal Hocko's avatar
    mm: fix NULL ptr dereference in __count_immobile_pages · bcbef18d
    Michal Hocko authored
    commit 687875fb
    
     upstream.
    
    Fix the following NULL ptr dereference caused by
    
      cat /sys/devices/system/memory/memory0/removable
    
    Pid: 13979, comm: sed Not tainted 3.0.13-0.5-default #1 IBM BladeCenter LS21 -[7971PAM]-/Server Blade
    RIP: __count_immobile_pages+0x4/0x100
    Process sed (pid: 13979, threadinfo ffff880221c36000, task ffff88022e788480)
    Call Trace:
      is_pageblock_removable_nolock+0x34/0x40
      is_mem_section_removable+0x74/0xf0
      show_mem_removable+0x41/0x70
      sysfs_read_file+0xfe/0x1c0
      vfs_read+0xc7/0x130
      sys_read+0x53/0xa0
      system_call_fastpath+0x16/0x1b
    
    We are crashing because we are trying to dereference NULL zone which
    came from pfn=0 (struct page ffffea0000000000). According to the boot
    log this page is marked reserved:
    e820 update range: 0000000000000000 - 0000000000010000 (usable) ==> (reserved)
    
    and early_node_map confirms that:
    early_node_map[3] active PFN ranges
        1: 0x00000010 -> 0x0000009c
        1: 0x00000100 -> 0x000bffa3
        1: 0x00100000 -> 0x00240000
    
    The problem is that memory_present works in PAGE_SECTION_MASK aligned
    blocks so the reserved range sneaks into the the section as well.  This
    also means that free_area_init_node will not take care of those reserved
    pages and they stay uninitialized.
    
    When we try to read the removable status we walk through all available
    sections and hope that the zone is valid for all pages in the section.
    But this is not true in this case as the zone and nid are not initialized.
    
    We have only one node in this particular case and it is marked as node=1
    (rather than 0) and that made the problem visible because page_to_nid will
    return 0 and there are no zones on the node.
    
    Let's check that the zone is valid and that the given pfn falls into its
    boundaries and mark the section not removable.  This might cause some
    false positives, probably, but we do not have any sane way to find out
    whether the page is reserved by the platform or it is just not used for
    whatever other reasons.
    
    Signed-off-by: default avatarMichal Hocko <mhocko@suse.cz>
    Acked-by: default avatarMel Gorman <mgorman@suse.de>
    Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
    Cc: Andrea Arcangeli <aarcange@redhat.com>
    Cc: David Rientjes <rientjes@google.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
    bcbef18d