From: "Liam R. Howlett" <Liam.Howlett@oracle.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org,
Suren Baghdasaryan <surenb@google.com>,
Lorenzo Stoakes <lorenzo.stoakes@oracle.com>,
Matthew Wilcox <willy@infradead.org>,
Vlastimil Babka <vbabka@suse.cz>,
sidhartha.kumar@oracle.com, Bert Karwatzki <spasswolf@web.de>,
Jiri Olsa <olsajiri@gmail.com>, Kees Cook <kees@kernel.org>,
"Paul E . McKenney" <paulmck@kernel.org>,
"Liam R. Howlett" <Liam.Howlett@Oracle.com>
Subject: [PATCH v6 15/20] mm: Change failure of MAP_FIXED to restoring the gap on failure
Date: Tue, 20 Aug 2024 19:57:24 -0400 [thread overview]
Message-ID: <20240820235730.2852400-16-Liam.Howlett@oracle.com> (raw)
In-Reply-To: <20240820235730.2852400-1-Liam.Howlett@oracle.com>
From: "Liam R. Howlett" <Liam.Howlett@Oracle.com>
Prior to call_mmap(), the vmas that will be replaced need to clear the
way for what may happen in the call_mmap(). This clean up work includes
clearing the ptes and calling the close() vm_ops. Some users do more
setup than can be restored by calling the vm_ops open() function. It is
safer to store the gap in the vma tree in these cases.
That is to say that the failure scenario that existed before the
MAP_FIXED gap exposure is restored as it is safer than trying to undo a
partial mapping.
There is also a secondary failure that may occur if there is not enough
memory to store the gap. In this case, the vmas are reattached and
resources freed. If the system cannot complete the call_mmap() and
fails to allocate with GFP_KERNEL, then the system will print a warning
about the failure.
Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
---
mm/mmap.c | 3 +--
mm/vma.h | 62 +++++++++++++++++++++++++++++++++++++------------------
2 files changed, 43 insertions(+), 22 deletions(-)
diff --git a/mm/mmap.c b/mm/mmap.c
index 6550d9470d3a..c1b3d17f97be 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1622,8 +1622,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
vm_unacct_memory(charged);
abort_munmap:
- if (vms.nr_pages)
- abort_munmap_vmas(&mas_detach, vms.closed_vm_ops);
+ vms_abort_munmap_vmas(&vms, &mas_detach, vms.closed_vm_ops);
validate_mm(mm);
return error;
}
diff --git a/mm/vma.h b/mm/vma.h
index 756dd42a6ec4..7618ddbfd2b2 100644
--- a/mm/vma.h
+++ b/mm/vma.h
@@ -82,6 +82,22 @@ int vma_expand(struct vma_iterator *vmi, struct vm_area_struct *vma,
int vma_shrink(struct vma_iterator *vmi, struct vm_area_struct *vma,
unsigned long start, unsigned long end, pgoff_t pgoff);
+static inline int vma_iter_store_gfp(struct vma_iterator *vmi,
+ struct vm_area_struct *vma, gfp_t gfp)
+
+{
+ if (vmi->mas.status != ma_start &&
+ ((vmi->mas.index > vma->vm_start) || (vmi->mas.last < vma->vm_start)))
+ vma_iter_invalidate(vmi);
+
+ __mas_set_range(&vmi->mas, vma->vm_start, vma->vm_end - 1);
+ mas_store_gfp(&vmi->mas, vma, gfp);
+ if (unlikely(mas_is_err(&vmi->mas)))
+ return -ENOMEM;
+
+ return 0;
+}
+
/*
* init_vma_munmap() - Initializer wrapper for vma_munmap_struct
* @vms: The vma munmap struct
@@ -136,15 +152,37 @@ static inline void abort_munmap_vmas(struct ma_state *mas_detach, bool closed)
struct vm_area_struct *vma;
mas_set(mas_detach, 0);
- mas_for_each(mas_detach, vma, ULONG_MAX) {
+ mas_for_each(mas_detach, vma, ULONG_MAX)
vma_mark_detached(vma, false);
- if (closed && vma->vm_ops && vma->vm_ops->open)
- vma->vm_ops->open(vma);
- }
__mt_destroy(mas_detach->tree);
}
+static inline void vms_abort_munmap_vmas(struct vma_munmap_struct *vms,
+ struct ma_state *mas_detach, bool closed)
+{
+ if (!vms->nr_pages)
+ return;
+
+ if (vms->clear_ptes)
+ return abort_munmap_vmas(mas_detach, vms->closed_vm_ops);
+
+ /*
+ * Aborting cannot just call the vm_ops open() because they are often
+ * not symmetrical and state data has been lost. Resort to the old
+ * failure method of leaving a gap where the MAP_FIXED mapping failed.
+ */
+ if (unlikely(vma_iter_store_gfp(vms->vmi, NULL, GFP_KERNEL))) {
+ pr_warn_once("%s: (%d) Unable to abort munmap() operation\n",
+ current->comm, current->pid);
+ /* Leaving vmas detached and in-tree may hamper recovery */
+ abort_munmap_vmas(mas_detach, vms->closed_vm_ops);
+ } else {
+ /* Clean up the insertion of unfortunate the gap */
+ vms_complete_munmap_vmas(vms, mas_detach);
+ }
+}
+
int
do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
struct mm_struct *mm, unsigned long start,
@@ -297,22 +335,6 @@ static inline struct vm_area_struct *vma_prev_limit(struct vma_iterator *vmi,
return mas_prev(&vmi->mas, min);
}
-static inline int vma_iter_store_gfp(struct vma_iterator *vmi,
- struct vm_area_struct *vma, gfp_t gfp)
-{
- if (vmi->mas.status != ma_start &&
- ((vmi->mas.index > vma->vm_start) || (vmi->mas.last < vma->vm_start)))
- vma_iter_invalidate(vmi);
-
- __mas_set_range(&vmi->mas, vma->vm_start, vma->vm_end - 1);
- mas_store_gfp(&vmi->mas, vma, gfp);
- if (unlikely(mas_is_err(&vmi->mas)))
- return -ENOMEM;
-
- return 0;
-}
-
-
/*
* These three helpers classifies VMAs for virtual memory accounting.
*/
--
2.43.0
next prev parent reply other threads:[~2024-08-20 23:58 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-20 23:57 [PATCH v6 00/20] Avoid MAP_FIXED gap exposure Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 01/20] mm/vma: Correctly position vma_iterator in __split_vma() Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 02/20] mm/vma: Introduce abort_munmap_vmas() Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 03/20] mm/vma: Introduce vmi_complete_munmap_vmas() Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 04/20] mm/vma: Extract the gathering of vmas from do_vmi_align_munmap() Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 05/20] mm/vma: Introduce vma_munmap_struct for use in munmap operations Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 06/20] mm/vma: Change munmap to use vma_munmap_struct() for accounting and surrounding vmas Liam R. Howlett
2024-08-21 9:59 ` Lorenzo Stoakes
2024-08-21 13:17 ` Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 07/20] mm/vma: Extract validate_mm() from vma_complete() Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 08/20] mm/vma: Inline munmap operation in mmap_region() Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 09/20] mm/vma: Expand mmap_region() munmap call Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 10/20] mm/vma: Support vma == NULL in init_vma_munmap() Liam R. Howlett
2024-08-21 10:07 ` Lorenzo Stoakes
2024-08-21 13:18 ` Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 11/20] mm/mmap: Reposition vma iterator in mmap_region() Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 12/20] mm/vma: Track start and end for munmap in vma_munmap_struct Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 13/20] mm: Clean up unmap_region() argument list Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 14/20] mm/mmap: Avoid zeroing vma tree in mmap_region() Liam R. Howlett
2024-08-21 11:02 ` Lorenzo Stoakes
2024-08-21 15:09 ` Liam R. Howlett
2024-08-20 23:57 ` Liam R. Howlett [this message]
2024-08-21 11:56 ` [PATCH v6 15/20] mm: Change failure of MAP_FIXED to restoring the gap on failure Lorenzo Stoakes
2024-08-21 13:31 ` Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 16/20] mm/mmap: Use PHYS_PFN in mmap_region() Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 17/20] mm/mmap: Use vms accounted pages " Liam R. Howlett
2024-08-21 16:35 ` Paul Moore
2024-08-21 17:15 ` Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 18/20] ipc/shm, mm: Drop do_vma_munmap() Liam R. Howlett
2024-08-21 11:59 ` Lorenzo Stoakes
2024-08-20 23:57 ` [PATCH v6 19/20] mm: Move may_expand_vm() check in mmap_region() Liam R. Howlett
2024-08-20 23:57 ` [PATCH v6 20/20] mm/vma: Drop incorrect comment from vms_gather_munmap_vmas() Liam R. Howlett
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240820235730.2852400-16-Liam.Howlett@oracle.com \
--to=liam.howlett@oracle.com \
--cc=akpm@linux-foundation.org \
--cc=kees@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lorenzo.stoakes@oracle.com \
--cc=olsajiri@gmail.com \
--cc=paulmck@kernel.org \
--cc=sidhartha.kumar@oracle.com \
--cc=spasswolf@web.de \
--cc=surenb@google.com \
--cc=vbabka@suse.cz \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox