From: Greg Kroah-Hartman Date: Thu, 17 Sep 2020 17:40:19 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v4.4.237~44 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e6d9da3345596148badf3f74b756d21d15985b5b;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: firmware_loader-fix-memory-leak-for-paged-buffer.patch --- diff --git a/queue-5.4/firmware_loader-fix-memory-leak-for-paged-buffer.patch b/queue-5.4/firmware_loader-fix-memory-leak-for-paged-buffer.patch new file mode 100644 index 00000000000..8109737aca5 --- /dev/null +++ b/queue-5.4/firmware_loader-fix-memory-leak-for-paged-buffer.patch @@ -0,0 +1,92 @@ +From 4965b8cd1bc1ffb017e5c58e622da82b55e49414 Mon Sep 17 00:00:00 2001 +From: Prateek Sood +Date: Fri, 21 Aug 2020 02:27:50 +0530 +Subject: firmware_loader: fix memory leak for paged buffer + +From: Prateek Sood + +commit 4965b8cd1bc1ffb017e5c58e622da82b55e49414 upstream. + +vfree() is being called on paged buffer allocated +using alloc_page() and mapped using vmap(). + +Freeing of pages in vfree() relies on nr_pages of +struct vm_struct. vmap() does not update nr_pages. +It can lead to memory leaks. + +Fixes: ddaf29fd9bb6 ("firmware: Free temporary page table after vmapping") +Signed-off-by: Prateek Sood +Reviewed-by: Takashi Iwai +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/1597957070-27185-1-git-send-email-prsood@codeaurora.org +Cc: Shuah Khan +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/base/firmware_loader/firmware.h | 2 ++ + drivers/base/firmware_loader/main.c | 17 +++++++++++------ + 2 files changed, 13 insertions(+), 6 deletions(-) + +--- a/drivers/base/firmware_loader/firmware.h ++++ b/drivers/base/firmware_loader/firmware.h +@@ -139,10 +139,12 @@ int assign_fw(struct firmware *fw, struc + void fw_free_paged_buf(struct fw_priv *fw_priv); + int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed); + int fw_map_paged_buf(struct fw_priv *fw_priv); ++bool fw_is_paged_buf(struct fw_priv *fw_priv); + #else + static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {} + static inline int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; } + static inline int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; } ++static inline bool fw_is_paged_buf(struct fw_priv *fw_priv) { return false; } + #endif + + #endif /* __FIRMWARE_LOADER_H */ +--- a/drivers/base/firmware_loader/main.c ++++ b/drivers/base/firmware_loader/main.c +@@ -252,9 +252,11 @@ static void __free_fw_priv(struct kref * + list_del(&fw_priv->list); + spin_unlock(&fwc->lock); + +- fw_free_paged_buf(fw_priv); /* free leftover pages */ +- if (!fw_priv->allocated_size) ++ if (fw_is_paged_buf(fw_priv)) ++ fw_free_paged_buf(fw_priv); ++ else if (!fw_priv->allocated_size) + vfree(fw_priv->data); ++ + kfree_const(fw_priv->fw_name); + kfree(fw_priv); + } +@@ -268,6 +270,11 @@ static void free_fw_priv(struct fw_priv + } + + #ifdef CONFIG_FW_LOADER_PAGED_BUF ++bool fw_is_paged_buf(struct fw_priv *fw_priv) ++{ ++ return fw_priv->is_paged_buf; ++} ++ + void fw_free_paged_buf(struct fw_priv *fw_priv) + { + int i; +@@ -275,6 +282,8 @@ void fw_free_paged_buf(struct fw_priv *f + if (!fw_priv->pages) + return; + ++ vunmap(fw_priv->data); ++ + for (i = 0; i < fw_priv->nr_pages; i++) + __free_page(fw_priv->pages[i]); + kvfree(fw_priv->pages); +@@ -328,10 +337,6 @@ int fw_map_paged_buf(struct fw_priv *fw_ + if (!fw_priv->data) + return -ENOMEM; + +- /* page table is no longer needed after mapping, let's free */ +- kvfree(fw_priv->pages); +- fw_priv->pages = NULL; +- + return 0; + } + #endif diff --git a/queue-5.4/series b/queue-5.4/series index 0132d8d1c18..9de3c7f4b24 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -4,3 +4,4 @@ e1000e-add-support-for-comet-lake.patch dsa-allow-forwarding-of-redirected-igmp-traffic.patch net-handle-the-return-value-of-pskb_carve_frag_list-correctly.patch hv_netvsc-remove-unlikely-from-netvsc_select_queue.patch +firmware_loader-fix-memory-leak-for-paged-buffer.patch