• M
    hugetlb: before freeing hugetlb page set dtor to appropriate value · e32d20c0
    Mike Kravetz 提交于
    When removing a hugetlb page from the pool the ref count is set to one (as
    the free page has no ref count) and compound page destructor is set to
    NULL_COMPOUND_DTOR.  Since a subsequent call to free the hugetlb page will
    call __free_pages for non-gigantic pages and free_gigantic_page for
    gigantic pages the destructor is not used.
    
    However, consider the following race with code taking a speculative
    reference on the page:
    
    Thread 0				Thread 1
    --------				--------
    remove_hugetlb_page
      set_page_refcounted(page);
      set_compound_page_dtor(page,
               NULL_COMPOUND_DTOR);
    					get_page_unless_zero(page)
    __update_and_free_page
      __free_pages(page,
               huge_page_order(h));
    
    		/* Note that __free_pages() will simply drop
    		   the reference to the page. */
    
    					put_page(page)
    					  __put_compound_page()
    					    destroy_compound_page
    					      NULL_COMPOUND_DTOR
    						BUG: kernel NULL pointer
    						dereference, address:
    						0000000000000000
    
    To address this race, set the dtor to the normal compound page dtor for
    non-gigantic pages.  The dtor for gigantic pages does not matter as
    gigantic pages are changed from a compound page to 'just a group of pages'
    before freeing.  Hence, the destructor is not used.
    
    Link: https://lkml.kernel.org/r/20210809184832.18342-4-mike.kravetz@oracle.comSigned-off-by: NMike Kravetz <mike.kravetz@oracle.com>
    Reviewed-by: NMuchun Song <songmuchun@bytedance.com>
    Cc: Michal Hocko <mhocko@suse.com>
    Cc: Oscar Salvador <osalvador@suse.de>
    Cc: David Hildenbrand <david@redhat.com>
    Cc: Matthew Wilcox <willy@infradead.org>
    Cc: Naoya Horiguchi <naoya.horiguchi@linux.dev>
    Cc: Mina Almasry <almasrymina@google.com>
    Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
    e32d20c0
hugetlb.c 176.3 KB