Commit 96df59b1 authored by Li Huafei's avatar Li Huafei Committed by Palmer Dabbelt

RISC-V: kexec: Fix memory leak of fdt buffer

This is reported by kmemleak detector:

unreferenced object 0xff60000082864000 (size 9588):
  comm "kexec", pid 146, jiffies 4294900634 (age 64.788s)
  hex dump (first 32 bytes):
    d0 0d fe ed 00 00 12 ed 00 00 00 48 00 00 11 40  ...........H...@
    00 00 00 28 00 00 00 11 00 00 00 02 00 00 00 00  ...(............
  backtrace:
    [<00000000f95b17c4>] kmemleak_alloc+0x34/0x3e
    [<00000000b9ec8e3e>] kmalloc_order+0x9c/0xc4
    [<00000000a95cf02e>] kmalloc_order_trace+0x34/0xb6
    [<00000000f01e68b4>] __kmalloc+0x5c2/0x62a
    [<000000002bd497b2>] kvmalloc_node+0x66/0xd6
    [<00000000906542fa>] of_kexec_alloc_and_setup_fdt+0xa6/0x6ea
    [<00000000e1166bde>] elf_kexec_load+0x206/0x4ec
    [<0000000036548e09>] kexec_image_load_default+0x40/0x4c
    [<0000000079fbe1b4>] sys_kexec_file_load+0x1c4/0x322
    [<0000000040c62c03>] ret_from_syscall+0x0/0x2

In elf_kexec_load(), a buffer is allocated via kvmalloc() to store fdt.
While it's not freed back to system when kexec kernel is reloaded or
unloaded.  Then memory leak is caused.  Fix it by introducing riscv
specific function arch_kimage_file_post_load_cleanup(), and freeing the
buffer there.

Fixes: 6261586e ("RISC-V: Add kexec_file support")
Signed-off-by: default avatarLi Huafei <lihuafei1@huawei.com>
Reviewed-by: default avatarConor Dooley <conor.dooley@microchip.com>
Reviewed-by: default avatarLiao Chang <liaochang1@huawei.com>
Link: https://lore.kernel.org/r/20221104095658.141222-1-lihuafei1@huawei.com
Cc: stable@vger.kernel.org
Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent 9704beac
...@@ -39,6 +39,7 @@ crash_setup_regs(struct pt_regs *newregs, ...@@ -39,6 +39,7 @@ crash_setup_regs(struct pt_regs *newregs,
#define ARCH_HAS_KIMAGE_ARCH #define ARCH_HAS_KIMAGE_ARCH
struct kimage_arch { struct kimage_arch {
void *fdt; /* For CONFIG_KEXEC_FILE */
unsigned long fdt_addr; unsigned long fdt_addr;
}; };
...@@ -62,6 +63,10 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, ...@@ -62,6 +63,10 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
const Elf_Shdr *relsec, const Elf_Shdr *relsec,
const Elf_Shdr *symtab); const Elf_Shdr *symtab);
#define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add #define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add
struct kimage;
int arch_kimage_file_post_load_cleanup(struct kimage *image);
#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
#endif #endif
#endif #endif
...@@ -21,6 +21,14 @@ ...@@ -21,6 +21,14 @@
#include <linux/memblock.h> #include <linux/memblock.h>
#include <asm/setup.h> #include <asm/setup.h>
int arch_kimage_file_post_load_cleanup(struct kimage *image)
{
kvfree(image->arch.fdt);
image->arch.fdt = NULL;
return kexec_image_post_load_cleanup_default(image);
}
static int riscv_kexec_elf_load(struct kimage *image, struct elfhdr *ehdr, static int riscv_kexec_elf_load(struct kimage *image, struct elfhdr *ehdr,
struct kexec_elf_info *elf_info, unsigned long old_pbase, struct kexec_elf_info *elf_info, unsigned long old_pbase,
unsigned long new_pbase) unsigned long new_pbase)
...@@ -298,6 +306,8 @@ static void *elf_kexec_load(struct kimage *image, char *kernel_buf, ...@@ -298,6 +306,8 @@ static void *elf_kexec_load(struct kimage *image, char *kernel_buf,
pr_err("Error add DTB kbuf ret=%d\n", ret); pr_err("Error add DTB kbuf ret=%d\n", ret);
goto out_free_fdt; goto out_free_fdt;
} }
/* Cache the fdt buffer address for memory cleanup */
image->arch.fdt = fdt;
pr_notice("Loaded device tree at 0x%lx\n", kbuf.mem); pr_notice("Loaded device tree at 0x%lx\n", kbuf.mem);
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment