summaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
authorYaliang Wang <Yaliang.Wang@windriver.com>2022-03-10 14:31:16 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-04-08 15:23:39 +0300
commitd29cda15cab086d82d692de016f7249545d4b6b4 (patch)
treefaa3a9ba2a84c580b0c5786940b4b240cf312de4 /arch/mips
parentd5e41310bd72e70c90ab9cb2d5b57da88c75a0e3 (diff)
downloadlinux-d29cda15cab086d82d692de016f7249545d4b6b4.tar.xz
MIPS: pgalloc: fix memory leak caused by pgd_free()
[ Upstream commit 2bc5bab9a763d520937e4f3fe8df51c6a1eceb97 ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/include/asm/pgalloc.h6
1 files changed, 6 insertions, 0 deletions
diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h
index c7925d0e9874..867e9c3db76e 100644
--- a/arch/mips/include/asm/pgalloc.h
+++ b/arch/mips/include/asm/pgalloc.h
@@ -15,6 +15,7 @@
#define __HAVE_ARCH_PMD_ALLOC_ONE
#define __HAVE_ARCH_PUD_ALLOC_ONE
+#define __HAVE_ARCH_PGD_FREE
#include <asm-generic/pgalloc.h>
static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
@@ -48,6 +49,11 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
extern void pgd_init(unsigned long page);
extern pgd_t *pgd_alloc(struct mm_struct *mm);
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+ free_pages((unsigned long)pgd, PGD_ORDER);
+}
+
#define __pte_free_tlb(tlb,pte,address) \
do { \
pgtable_pte_page_dtor(pte); \