Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: pgalloc: fix memory leak caused by pgd_free()

pgd page is freed by generic implementation pgd_free() since commit
f9cb654cb550 ("asm-generic: pgalloc: provide generic pgd_free()"),
however, there are scenarios that the system uses more than one page as
the pgd table, in such cases the generic implementation pgd_free() won't
be applicable anymore. For example, when PAGE_SIZE_4KB is enabled and
MIPS_VA_BITS_48 is not enabled in a 64bit system, the macro "PGD_ORDER"
will be set as "1", which will cause allocating two pages as the pgd
table. Well, at the same time, the generic implementation pgd_free()
just free one pgd page, which will result in the memory leak.

The memory leak can be easily detected by executing shell command:
"while true; do ls > /dev/null; grep MemFree /proc/meminfo; done"

Fixes: f9cb654cb550 ("asm-generic: pgalloc: provide generic pgd_free()")
Signed-off-by: Yaliang Wang <Yaliang.Wang@windriver.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>

authored by

Yaliang Wang and committed by
Thomas Bogendoerfer
2bc5bab9 8755d57b

+6
+6
arch/mips/include/asm/pgalloc.h
··· 15 15 16 16 #define __HAVE_ARCH_PMD_ALLOC_ONE 17 17 #define __HAVE_ARCH_PUD_ALLOC_ONE 18 + #define __HAVE_ARCH_PGD_FREE 18 19 #include <asm-generic/pgalloc.h> 19 20 20 21 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, ··· 48 47 */ 49 48 extern void pgd_init(unsigned long page); 50 49 extern pgd_t *pgd_alloc(struct mm_struct *mm); 50 + 51 + static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) 52 + { 53 + free_pages((unsigned long)pgd, PGD_ORDER); 54 + } 51 55 52 56 #define __pte_free_tlb(tlb,pte,address) \ 53 57 do { \