From: Greg Kroah-Hartman Date: Thu, 17 Sep 2020 17:40:35 +0000 (+0200) Subject: 5.8-stable patches X-Git-Tag: v4.4.237~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4300e227d3a06463c007f8d117fd9433f9cdce9e;p=thirdparty%2Fkernel%2Fstable-queue.git 5.8-stable patches added patches: firmware_loader-fix-memory-leak-for-paged-buffer.patch --- diff --git a/queue-5.8/firmware_loader-fix-memory-leak-for-paged-buffer.patch b/queue-5.8/firmware_loader-fix-memory-leak-for-paged-buffer.patch new file mode 100644 index 00000000000..924594ab615 --- /dev/null +++ b/queue-5.8/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 +@@ -142,10 +142,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.8/series b/queue-5.8/series index 541cccdb401..82fd8684c74 100644 --- a/queue-5.8/series +++ b/queue-5.8/series @@ -6,3 +6,4 @@ powerpc-add-power10-raw-mode-cputable-entry.patch dt-bindings-pci-intel-lgm-pcie-fix-matching-on-all-snps-dw-pcie-instances.patch hv_netvsc-remove-unlikely-from-netvsc_select_queue.patch loop-set-correct-device-size-when-using-loop_configure.patch +firmware_loader-fix-memory-leak-for-paged-buffer.patch