[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220613094933.634623237@linuxfoundation.org>
Date: Mon, 13 Jun 2022 12:12:56 +0200
From: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To: linux-kernel@...r.kernel.org
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
stable@...r.kernel.org,
syzbot+9e27a75a8c24f3fe75c1@...kaller.appspotmail.com,
"Matthew Wilcox (Oracle)" <willy@...radead.org>
Subject: [PATCH 5.17 282/298] mm/huge_memory: Fix xarray node memory leak
From: Matthew Wilcox (Oracle) <willy@...radead.org>
commit 69a37a8ba1b408a1c7616494aa7018e4b3844cbe upstream.
If xas_split_alloc() fails to allocate the necessary nodes to complete the
xarray entry split, it sets the xa_state to -ENOMEM, which xas_nomem()
then interprets as "Please allocate more memory", not as "Please free
any unnecessary memory" (which was the intended outcome). It's confusing
to use xas_nomem() to free memory in this context, so call xas_destroy()
instead.
Reported-by: syzbot+9e27a75a8c24f3fe75c1@...kaller.appspotmail.com
Fixes: 6b24ca4a1a8d ("mm: Use multi-index entries in the page cache")
Cc: stable@...r.kernel.org
Signed-off-by: Matthew Wilcox (Oracle) <willy@...radead.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
---
include/linux/xarray.h | 1 +
lib/xarray.c | 5 +++--
mm/huge_memory.c | 3 +--
3 files changed, 5 insertions(+), 4 deletions(-)
--- a/include/linux/xarray.h
+++ b/include/linux/xarray.h
@@ -1506,6 +1506,7 @@ void *xas_find_marked(struct xa_state *,
void xas_init_marks(const struct xa_state *);
bool xas_nomem(struct xa_state *, gfp_t);
+void xas_destroy(struct xa_state *);
void xas_pause(struct xa_state *);
void xas_create_range(struct xa_state *);
--- a/lib/xarray.c
+++ b/lib/xarray.c
@@ -264,9 +264,10 @@ static void xa_node_free(struct xa_node
* xas_destroy() - Free any resources allocated during the XArray operation.
* @xas: XArray operation state.
*
- * This function is now internal-only.
+ * Most users will not need to call this function; it is called for you
+ * by xas_nomem().
*/
-static void xas_destroy(struct xa_state *xas)
+void xas_destroy(struct xa_state *xas)
{
struct xa_node *next, *node = xas->xa_alloc;
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2736,8 +2736,7 @@ out_unlock:
if (mapping)
i_mmap_unlock_read(mapping);
out:
- /* Free any memory we didn't use */
- xas_nomem(&xas, 0);
+ xas_destroy(&xas);
count_vm_event(!ret ? THP_SPLIT_PAGE : THP_SPLIT_PAGE_FAILED);
return ret;
}
Powered by blists - more mailing lists