mm/filemap.c: fix NULL pointer in page_cache_tree_insert()
Subsystems (3)
[email protected]
maintainerPATCH 15/15 mm/filemap.c: fix NULL pointer in page_cache_tree_insert()
From: Matthew Wilcox <[email protected]>
Subject: mm/filemap.c: fix NULL pointer in page_cache_tree_insert()
f2fs specifies the __GFP_ZERO flag for allocating some of its pages. Unfortunately, the page cache also uses the mapping's GFP flags for allocating radix tree nodes. It always masked off the __GFP_HIGHMEM flag, and masks off __GFP_ZERO in some paths, but not all. That causes radix tree nodes to be allocated with a NULL list_head, which causes backtraces like:
[<ffffff80086f4de0>] __list_del_entry+0x30/0xd0 [<ffffff8008362018>] list_lru_del+0xac/0x1ac [<ffffff800830f04c>] page_cache_tree_insert+0xd8/0x110
The __GFP_DMA and __GFP_DMA32 flags would also be able to sneak through if they are ever used. Fix them all by using GFP_RECLAIM_MASK at the innermost location, and remove it from earlier in the callchain.
---
mm/filemap.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
mm/filemap.c renamed from mm/filemap.c~fix-null-pointer-in-page_cache_tree_insert +4 -5
@@ -786,7 +786,7 @@ int replace_page_cache_page(struct pageVM_BUG_ON_PAGE (!PageLocked (new), new);VM_BUG_ON_PAGE (new->mapping, new); - error =radix_tree_preload (gfp_mask & ~__GFP_HIGHMEM); + error =radix_tree_preload (gfp_mask &GFP_RECLAIM_MASK );if (!error) {struct address_space *mapping = old->mapping;void (*freepage)(struct page *);
@@ -842,7 +842,7 @@ static int __add_to_page_cache_locked(streturn error; } - error =radix_tree_maybe_preload (gfp_mask & ~__GFP_HIGHMEM); + error =radix_tree_maybe_preload (gfp_mask &GFP_RECLAIM_MASK );if (error) {if (!huge)mem_cgroup_cancel_charge (page, memcg, false);
@@ -1585,8 +1585,7 @@ no_page:if (fgp_flags &FGP_ACCESSED )__SetPageReferenced (page); - err =add_to_page_cache_lru (page, mapping, offset, - gfp_mask &GFP_RECLAIM_MASK ); + err =add_to_page_cache_lru (page, mapping, offset, gfp_mask);if (unlikely (err)) {put_page (page); page =NULL ;
@@ -2387,7 +2386,7 @@ static int page_cache_read(struct file *if (!page)return -ENOMEM ; - ret =add_to_page_cache_lru (page, mapping, offset, gfp_mask &GFP_KERNEL ); + ret =add_to_page_cache_lru (page, mapping, offset, gfp_mask);if (ret ==0 ) ret = mapping->a_ops->readpage (file, page);else if (ret == -EEXIST )
_