From 7a6f93b0a873ad24631088c349e9d1ca3d4cf852 Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Date: Mon, 29 Apr 2013 15:08:39 -0700 Subject: [PATCH] firmware, memmap: fix firmware_map_entry leak When hot removing memory, a firmware_map_entry which has memory range of the memory is released by release_firmware_map_entry(). If the entry is allocated by bootmem, release_firmware_map_entry() adds the entry to map_entires_bootmem list when firmware_map_find_entry() finds the entry from map_entries list. But firmware_map_find_entry never find the entry sicne map_entires list does not have the entry. So the entry just leaks. Here are steps of leaking firmware_map_entry: firmware_map_remove() -> firmware_map_find_entry() Find released entry from map_entries list -> firmware_map_remove_entry() Delete the entry from map_entries list -> remove_sysfs_fw_map_entry() ... -> release_firmware_map_entry() -> firmware_map_find_entry() Find the entry from map_entries list but the entry has been deleted from map_entries list. So the entry is not added to map_entries_bootmem. Thus the entry leaks release_firmware_map_entry() should not call firmware_map_find_entry() since releaed entry has been deleted from map_entries list. So the patch delete firmware_map_find_entry() from releae_firmware_map_entry() Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Reviewed-by: Wanpeng Li <liwanp@linux.vnet.ibm.com> Reviewed-by: Tang Chen <tangchen@cn.fujitsu.com> Acked-by: Toshi Kani <toshi.kani@hp.com> Cc: Wen Congyang <wency@cn.fujitsu.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/firmware/memmap.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c index 0b5b5f619c755..e2e04b007e155 100644 --- a/drivers/firmware/memmap.c +++ b/drivers/firmware/memmap.c @@ -114,12 +114,9 @@ static void __meminit release_firmware_map_entry(struct kobject *kobj) * map_entries_bootmem here, and deleted from &map_entries in * firmware_map_remove_entry(). */ - if (firmware_map_find_entry(entry->start, entry->end, - entry->type)) { - spin_lock(&map_entries_bootmem_lock); - list_add(&entry->list, &map_entries_bootmem); - spin_unlock(&map_entries_bootmem_lock); - } + spin_lock(&map_entries_bootmem_lock); + list_add(&entry->list, &map_entries_bootmem); + spin_unlock(&map_entries_bootmem_lock); return; } -- 2.39.5