Skip to content

Commit a6687c8

Browse files
Matthew Wilcox (Oracle)tehcaster
authored andcommitted
slab: Mark large folios for debugging purposes
If a user calls p = kmalloc(1024); kfree(p); kfree(p); and 'p' was the only object in the slab, we may free the slab after the first call to kfree(). If we do, we clear PGTY_slab and the second call to kfree() will call free_large_kmalloc(). That will leave a trace in the logs ("object pointer: 0x%p"), but otherwise proceed to free the memory, which is likely to corrupt the page allocator's metadata. Allocate a new page type for large kmalloc and mark the memory with it while it's allocated. That lets us detect this double-free and return without harming any data structures. Reported-by: Hannes Reinecke <[email protected]> Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Reviewed-by: Harry Yoo <[email protected]> Signed-off-by: Vlastimil Babka <[email protected]>
1 parent 7e384db commit a6687c8

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

include/linux/page-flags.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -925,14 +925,15 @@ FOLIO_FLAG_FALSE(has_hwpoisoned)
925925
enum pagetype {
926926
/* 0x00-0x7f are positive numbers, ie mapcount */
927927
/* Reserve 0x80-0xef for mapcount overflow. */
928-
PGTY_buddy = 0xf0,
929-
PGTY_offline = 0xf1,
930-
PGTY_table = 0xf2,
931-
PGTY_guard = 0xf3,
932-
PGTY_hugetlb = 0xf4,
933-
PGTY_slab = 0xf5,
934-
PGTY_zsmalloc = 0xf6,
935-
PGTY_unaccepted = 0xf7,
928+
PGTY_buddy = 0xf0,
929+
PGTY_offline = 0xf1,
930+
PGTY_table = 0xf2,
931+
PGTY_guard = 0xf3,
932+
PGTY_hugetlb = 0xf4,
933+
PGTY_slab = 0xf5,
934+
PGTY_zsmalloc = 0xf6,
935+
PGTY_unaccepted = 0xf7,
936+
PGTY_large_kmalloc = 0xf8,
936937

937938
PGTY_mapcount_underflow = 0xff
938939
};
@@ -1075,6 +1076,7 @@ PAGE_TYPE_OPS(Zsmalloc, zsmalloc, zsmalloc)
10751076
* Serialized with zone lock.
10761077
*/
10771078
PAGE_TYPE_OPS(Unaccepted, unaccepted, unaccepted)
1079+
FOLIO_TYPE_OPS(large_kmalloc, large_kmalloc)
10781080

10791081
/**
10801082
* PageHuge - Determine if the page belongs to hugetlbfs

mm/slub.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4255,6 +4255,7 @@ static void *___kmalloc_large_node(size_t size, gfp_t flags, int node)
42554255
ptr = folio_address(folio);
42564256
lruvec_stat_mod_folio(folio, NR_SLAB_UNRECLAIMABLE_B,
42574257
PAGE_SIZE << order);
4258+
__folio_set_large_kmalloc(folio);
42584259
}
42594260

42604261
ptr = kasan_kmalloc_large(ptr, size, flags);
@@ -4730,6 +4731,11 @@ static void free_large_kmalloc(struct folio *folio, void *object)
47304731
{
47314732
unsigned int order = folio_order(folio);
47324733

4734+
if (WARN_ON_ONCE(!folio_test_large_kmalloc(folio))) {
4735+
dump_page(&folio->page, "Not a kmalloc allocation");
4736+
return;
4737+
}
4738+
47334739
if (WARN_ON_ONCE(order == 0))
47344740
pr_warn_once("object pointer: 0x%p\n", object);
47354741

@@ -4739,6 +4745,7 @@ static void free_large_kmalloc(struct folio *folio, void *object)
47394745

47404746
lruvec_stat_mod_folio(folio, NR_SLAB_UNRECLAIMABLE_B,
47414747
-(PAGE_SIZE << order));
4748+
__folio_clear_large_kmalloc(folio);
47424749
folio_put(folio);
47434750
}
47444751

0 commit comments

Comments
 (0)