--- /dev/null
+From 824135c46b00df7fb369ec7f1f8607427bbebeb0 Mon Sep 17 00:00:00 2001
+From: "Liam R. Howlett" <Liam.Howlett@oracle.com>
+Date: Fri, 29 Sep 2023 14:30:40 -0400
+Subject: mmap: fix error paths with dup_anon_vma()
+
+From: Liam R. Howlett <Liam.Howlett@oracle.com>
+
+commit 824135c46b00df7fb369ec7f1f8607427bbebeb0 upstream.
+
+When the calling function fails after the dup_anon_vma(), the
+duplication of the anon_vma is not being undone. Add the necessary
+unlink_anon_vma() call to the error paths that are missing them.
+
+This issue showed up during inspection of the error path in vma_merge()
+for an unrelated vma iterator issue.
+
+Users may experience increased memory usage, which may be problematic as
+the failure would likely be caused by a low memory situation.
+
+Link: https://lkml.kernel.org/r/20230929183041.2835469-3-Liam.Howlett@oracle.com
+Fixes: d4af56c5c7c6 ("mm: start tracking VMAs with maple tree")
+Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
+Reviewed-by: Lorenzo Stoakes <lstoakes@gmail.com>
+Acked-by: Vlastimil Babka <vbabka@suse.cz>
+Cc: Jann Horn <jannh@google.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/mmap.c | 30 ++++++++++++++++++++++--------
+ 1 file changed, 22 insertions(+), 8 deletions(-)
+
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -603,11 +603,12 @@ again:
+ * dup_anon_vma() - Helper function to duplicate anon_vma
+ * @dst: The destination VMA
+ * @src: The source VMA
++ * @dup: Pointer to the destination VMA when successful.
+ *
+ * Returns: 0 on success.
+ */
+ static inline int dup_anon_vma(struct vm_area_struct *dst,
+- struct vm_area_struct *src)
++ struct vm_area_struct *src, struct vm_area_struct **dup)
+ {
+ /*
+ * Easily overlooked: when mprotect shifts the boundary, make sure the
+@@ -615,9 +616,15 @@ static inline int dup_anon_vma(struct vm
+ * anon pages imported.
+ */
+ if (src->anon_vma && !dst->anon_vma) {
++ int ret;
++
+ vma_start_write(dst);
+ dst->anon_vma = src->anon_vma;
+- return anon_vma_clone(dst, src);
++ ret = anon_vma_clone(dst, src);
++ if (ret)
++ return ret;
++
++ *dup = dst;
+ }
+
+ return 0;
+@@ -644,6 +651,7 @@ int vma_expand(struct vma_iterator *vmi,
+ unsigned long start, unsigned long end, pgoff_t pgoff,
+ struct vm_area_struct *next)
+ {
++ struct vm_area_struct *anon_dup = NULL;
+ bool remove_next = false;
+ struct vma_prepare vp;
+
+@@ -651,7 +659,7 @@ int vma_expand(struct vma_iterator *vmi,
+ int ret;
+
+ remove_next = true;
+- ret = dup_anon_vma(vma, next);
++ ret = dup_anon_vma(vma, next, &anon_dup);
+ if (ret)
+ return ret;
+ }
+@@ -683,6 +691,8 @@ int vma_expand(struct vma_iterator *vmi,
+ return 0;
+
+ nomem:
++ if (anon_dup)
++ unlink_anon_vmas(anon_dup);
+ return -ENOMEM;
+ }
+
+@@ -881,6 +891,7 @@ struct vm_area_struct *vma_merge(struct
+ {
+ struct vm_area_struct *curr, *next, *res;
+ struct vm_area_struct *vma, *adjust, *remove, *remove2;
++ struct vm_area_struct *anon_dup = NULL;
+ struct vma_prepare vp;
+ pgoff_t vma_pgoff;
+ int err = 0;
+@@ -945,16 +956,16 @@ struct vm_area_struct *vma_merge(struct
+ is_mergeable_anon_vma(prev->anon_vma, next->anon_vma, NULL)) {
+ remove = next; /* case 1 */
+ vma_end = next->vm_end;
+- err = dup_anon_vma(prev, next);
++ err = dup_anon_vma(prev, next, &anon_dup);
+ if (curr) { /* case 6 */
+ remove = curr;
+ remove2 = next;
+ if (!next->anon_vma)
+- err = dup_anon_vma(prev, curr);
++ err = dup_anon_vma(prev, curr, &anon_dup);
+ }
+ } else if (merge_prev) { /* case 2 */
+ if (curr) {
+- err = dup_anon_vma(prev, curr);
++ err = dup_anon_vma(prev, curr, &anon_dup);
+ if (end == curr->vm_end) { /* case 7 */
+ remove = curr;
+ } else { /* case 5 */
+@@ -968,7 +979,7 @@ struct vm_area_struct *vma_merge(struct
+ vma_end = addr;
+ adjust = next;
+ adj_start = -(prev->vm_end - addr);
+- err = dup_anon_vma(next, prev);
++ err = dup_anon_vma(next, prev, &anon_dup);
+ } else {
+ /*
+ * Note that cases 3 and 8 are the ONLY ones where prev
+@@ -981,7 +992,7 @@ struct vm_area_struct *vma_merge(struct
+ if (curr) { /* case 8 */
+ vma_pgoff = curr->vm_pgoff;
+ remove = curr;
+- err = dup_anon_vma(next, curr);
++ err = dup_anon_vma(next, curr, &anon_dup);
+ }
+ }
+ }
+@@ -1026,6 +1037,9 @@ struct vm_area_struct *vma_merge(struct
+ return res;
+
+ prealloc_fail:
++ if (anon_dup)
++ unlink_anon_vmas(anon_dup);
++
+ anon_vma_fail:
+ vma_iter_set(vmi, addr);
+ vma_iter_load(vmi);
--- /dev/null
+From 1419430c8abb5a00590169068590dd54d86590ba Mon Sep 17 00:00:00 2001
+From: "Liam R. Howlett" <Liam.Howlett@oracle.com>
+Date: Fri, 29 Sep 2023 14:30:39 -0400
+Subject: mmap: fix vma_iterator in error path of vma_merge()
+
+From: Liam R. Howlett <Liam.Howlett@oracle.com>
+
+commit 1419430c8abb5a00590169068590dd54d86590ba upstream.
+
+During the error path, the vma iterator may not be correctly positioned or
+set to the correct range. Undo the vma_prev() call by resetting to the
+passed in address. Re-walking to the same range will fix the range to the
+area previously passed in.
+
+Users would notice increased cycles as vma_merge() would be called an
+extra time with vma == prev, and thus would fail to merge and return.
+
+Link: https://lore.kernel.org/linux-mm/CAG48ez12VN1JAOtTNMY+Y2YnsU45yL5giS-Qn=ejtiHpgJAbdQ@mail.gmail.com/
+Link: https://lkml.kernel.org/r/20230929183041.2835469-2-Liam.Howlett@oracle.com
+Fixes: 18b098af2890 ("vma_merge: set vma iterator to correct position.")
+Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
+Reported-by: Jann Horn <jannh@google.com>
+Closes: https://lore.kernel.org/linux-mm/CAG48ez12VN1JAOtTNMY+Y2YnsU45yL5giS-Qn=ejtiHpgJAbdQ@mail.gmail.com/
+Reviewed-by: Lorenzo Stoakes <lstoakes@gmail.com>
+Acked-by: Vlastimil Babka <vbabka@suse.cz>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/mmap.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -988,10 +988,10 @@ struct vm_area_struct *vma_merge(struct
+
+ /* Error in anon_vma clone. */
+ if (err)
+- return NULL;
++ goto anon_vma_fail;
+
+ if (vma_iter_prealloc(vmi))
+- return NULL;
++ goto prealloc_fail;
+
+ init_multi_vma_prep(&vp, vma, adjust, remove, remove2);
+ VM_WARN_ON(vp.anon_vma && adjust && adjust->anon_vma &&
+@@ -1024,6 +1024,12 @@ struct vm_area_struct *vma_merge(struct
+ khugepaged_enter_vma(res, vm_flags);
+
+ return res;
++
++prealloc_fail:
++anon_vma_fail:
++ vma_iter_set(vmi, addr);
++ vma_iter_load(vmi);
++ return NULL;
+ }
+
+ /*