diff options
author | John Crispin <blogic@openwrt.org> | 2015-07-07 13:48:27 +0000 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2015-07-07 13:48:27 +0000 |
commit | df3135f44507b83f525c28105a8ee723ea6b807d (patch) | |
tree | 4f41b34c92bd1cfe7d3bf5d6a6dca4199ba148fb /target/linux/generic/patches-4.0/305-mips_module_reloc.patch | |
parent | 54fcf4f415e253cab77974d3819299fef1c44120 (diff) | |
download | master-187ad058-df3135f44507b83f525c28105a8ee723ea6b807d.tar.gz master-187ad058-df3135f44507b83f525c28105a8ee723ea6b807d.tar.bz2 master-187ad058-df3135f44507b83f525c28105a8ee723ea6b807d.zip |
mips: Free memory when load_module fails (#14453)
The mips reloc patch introduced new allocations which were done before
add_unformed_module but never freed them in case of an error. A new hook in
Linux 3.19 called module_arch_freeing_init can be used for freeing memory
which were allocated during this init phase.
The problem can be seen when trying to load a module (via busybox insmod)
when it was already loaded.
free -m
for i in `seq 1 100`; do
/sbin/insmod /lib/modules/*/ath9k.ko >& /dev/null
done
free -m
This simple loop would leak ~3.2 MB.
Signed-off-by: Sven Eckelmann <sven@open-mesh.com>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@46247 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/generic/patches-4.0/305-mips_module_reloc.patch')
-rw-r--r-- | target/linux/generic/patches-4.0/305-mips_module_reloc.patch | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/target/linux/generic/patches-4.0/305-mips_module_reloc.patch b/target/linux/generic/patches-4.0/305-mips_module_reloc.patch index 87c205c7db..8b3975fe09 100644 --- a/target/linux/generic/patches-4.0/305-mips_module_reloc.patch +++ b/target/linux/generic/patches-4.0/305-mips_module_reloc.patch @@ -316,7 +316,7 @@ return 0; } -@@ -287,11 +528,32 @@ int module_finalize(const Elf_Ehdr *hdr, +@@ -287,9 +528,33 @@ int module_finalize(const Elf_Ehdr *hdr, list_add(&me->arch.dbe_list, &dbe_list); spin_unlock_irq(&dbe_lock); } @@ -335,8 +335,8 @@ return 0; } - void module_arch_cleanup(struct module *mod) - { ++void module_arch_freeing_init(struct module *mod) ++{ + if (mod->arch.phys_plt_tbl) { + __module_free(mod->arch.phys_plt_tbl); + mod->arch.phys_plt_tbl = NULL; @@ -345,7 +345,8 @@ + __module_free(mod->arch.virt_plt_tbl); + mod->arch.virt_plt_tbl = NULL; + } ++} + + void module_arch_cleanup(struct module *mod) + { spin_lock_irq(&dbe_lock); - list_del(&mod->arch.dbe_list); - spin_unlock_irq(&dbe_lock); |