All of lore.kernel.org
 help / color / mirror / Atom feed
From: Piotr Kwapulinski <kwapulinski.piotr@gmail.com>
To: akpm@linux-foundation.org
Cc: mhocko@suse.com, mtk.manpages@gmail.com, cmetcalf@mellanox.com,
	arnd@arndb.de, viro@zeniv.linux.org.uk, mszeredi@suse.cz,
	dave@stgolabs.net, kirill.shutemov@linux.intel.com,
	vbabka@suse.cz, mingo@kernel.org, dan.j.williams@intel.com,
	dave.hansen@linux.intel.com, koct9i@gmail.com,
	hannes@cmpxchg.org, jack@suse.cz, xiexiuqi@huawei.com,
	iamjoonsoo.kim@lge.com, oleg@redhat.com,
	gang.chen.5i5j@gmail.com, aarcange@redhat.com,
	aryabinin@virtuozzo.com, rientjes@google.com, denc716@gmail.com,
	toshi.kani@hpe.com, ldufour@linux.vnet.ibm.com,
	kuleshovmail@gmail.com, linux-kernel@vger.kernel.org,
	linux-mm@kvack.org, linux-arch@vger.kernel.org,
	Piotr Kwapulinski <kwapulinski.piotr@gmail.com>
Subject: [PATCH 0/3] mm/mmap.c: don't unmap the overlapping VMA(s)
Date: Sat,  2 Apr 2016 21:17:31 +0200	[thread overview]
Message-ID: <1459624654-7955-1-git-send-email-kwapulinski.piotr@gmail.com> (raw)

Currently the mmap(MAP_FIXED) discards the overlapping part of the
existing VMA(s).
Introduce the new MAP_DONTUNMAP flag which forces the mmap to fail
with ENOMEM whenever the overlapping occurs and MAP_FIXED is set.
No existing mapping(s) is discarded.
The implementation tests the MAP_DONTUNMAP flag right before unmapping
the VMA. The tile arch is the dependency of mmap_flags.

I did the isolated tests and also tested it with Gentoo full
installation.

Signed-off-by: Piotr Kwapulinski <kwapulinski.piotr@gmail.com>
---
 arch/tile/mm/elf.c                     |  1 +
 include/linux/mm.h                     |  3 ++-
 include/uapi/asm-generic/mman-common.h |  1 +
 mm/mmap.c                              | 10 +++++++---
 4 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/tile/mm/elf.c b/arch/tile/mm/elf.c
index 6225cc9..dae4b33 100644
--- a/arch/tile/mm/elf.c
+++ b/arch/tile/mm/elf.c
@@ -142,6 +142,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	if (!retval) {
 		unsigned long addr = MEM_USER_INTRPT;
 		addr = mmap_region(NULL, addr, INTRPT_SIZE,
+				   MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,
 				   VM_READ|VM_EXEC|
 				   VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, 0);
 		if (addr > (unsigned long) -PAGE_SIZE)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index ed6407d..31dcdfb 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2048,7 +2048,8 @@ extern int install_special_mapping(struct mm_struct *mm,
 extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 
 extern unsigned long mmap_region(struct file *file, unsigned long addr,
-	unsigned long len, vm_flags_t vm_flags, unsigned long pgoff);
+	unsigned long len, unsigned long mmap_flags,
+	vm_flags_t vm_flags, unsigned long pgoff);
 extern unsigned long do_mmap(struct file *file, unsigned long addr,
 	unsigned long len, unsigned long prot, unsigned long flags,
 	vm_flags_t vm_flags, unsigned long pgoff, unsigned long *populate);
diff --git a/include/uapi/asm-generic/mman-common.h b/include/uapi/asm-generic/mman-common.h
index 5827438..3655be3 100644
--- a/include/uapi/asm-generic/mman-common.h
+++ b/include/uapi/asm-generic/mman-common.h
@@ -19,6 +19,7 @@
 #define MAP_TYPE	0x0f		/* Mask for type of mapping */
 #define MAP_FIXED	0x10		/* Interpret addr exactly */
 #define MAP_ANONYMOUS	0x20		/* don't use a file */
+#define MAP_DONTUNMAP	0x40		/* don't unmap overlapping VMA */
 #ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
 # define MAP_UNINITIALIZED 0x4000000	/* For anonymous mmap, memory could be uninitialized */
 #else
diff --git a/mm/mmap.c b/mm/mmap.c
index bd2e1a53..ab429c3 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1286,7 +1286,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
 			vm_flags |= VM_NORESERVE;
 	}
 
-	addr = mmap_region(file, addr, len, vm_flags, pgoff);
+	addr = mmap_region(file, addr, len, flags, vm_flags, pgoff);
 	if (!IS_ERR_VALUE(addr) &&
 	    ((vm_flags & VM_LOCKED) ||
 	     (flags & (MAP_POPULATE | MAP_NONBLOCK)) == MAP_POPULATE))
@@ -1422,7 +1422,8 @@ static inline int accountable_mapping(struct file *file, vm_flags_t vm_flags)
 }
 
 unsigned long mmap_region(struct file *file, unsigned long addr,
-		unsigned long len, vm_flags_t vm_flags, unsigned long pgoff)
+		unsigned long len, unsigned long mmap_flags,
+		vm_flags_t vm_flags, unsigned long pgoff)
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma, *prev;
@@ -1448,7 +1449,10 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
 	/* Clear old maps */
 	while (find_vma_links(mm, addr, addr + len, &prev, &rb_link,
 			      &rb_parent)) {
-		if (do_munmap(mm, addr, len))
+		const bool dont_unmap =
+				(mmap_flags & (MAP_DONTUNMAP | MAP_FIXED))
+				== (MAP_DONTUNMAP | MAP_FIXED);
+		if (dont_unmap || do_munmap(mm, addr, len))
 			return -ENOMEM;
 	}
 
-- 
2.7.4

WARNING: multiple messages have this Message-ID (diff)
From: Piotr Kwapulinski <kwapulinski.piotr@gmail.com>
To: akpm@linux-foundation.org
Cc: mhocko@suse.com, mtk.manpages@gmail.com, cmetcalf@mellanox.com,
	arnd@arndb.de, viro@zeniv.linux.org.uk, mszeredi@suse.cz,
	dave@stgolabs.net, kirill.shutemov@linux.intel.com,
	vbabka@suse.cz, mingo@kernel.org, dan.j.williams@intel.com,
	dave.hansen@linux.intel.com, koct9i@gmail.com,
	hannes@cmpxchg.org, jack@suse.cz, xiexiuqi@huawei.com,
	iamjoonsoo.kim@lge.com, oleg@redhat.com,
	gang.chen.5i5j@gmail.com, aarcange@redhat.com,
	aryabinin@virtuozzo.com, rientjes@google.com, denc716@gmail.com,
	toshi.kani@hpe.com, ldufour@linux.vnet.ibm.com,
	kuleshovmail@gmail.com, linux-kernel@vger.kernel.org,
	linux-mm@kvack.org, linux-arch@vger.kernel.org,
	Piotr Kwapulinski <kwapulinski.piotr@gmail.com>
Subject: [PATCH 0/3] mm/mmap.c: don't unmap the overlapping VMA(s)
Date: Sat,  2 Apr 2016 21:17:31 +0200	[thread overview]
Message-ID: <1459624654-7955-1-git-send-email-kwapulinski.piotr@gmail.com> (raw)

Currently the mmap(MAP_FIXED) discards the overlapping part of the
existing VMA(s).
Introduce the new MAP_DONTUNMAP flag which forces the mmap to fail
with ENOMEM whenever the overlapping occurs and MAP_FIXED is set.
No existing mapping(s) is discarded.
The implementation tests the MAP_DONTUNMAP flag right before unmapping
the VMA. The tile arch is the dependency of mmap_flags.

I did the isolated tests and also tested it with Gentoo full
installation.

Signed-off-by: Piotr Kwapulinski <kwapulinski.piotr@gmail.com>
---
 arch/tile/mm/elf.c                     |  1 +
 include/linux/mm.h                     |  3 ++-
 include/uapi/asm-generic/mman-common.h |  1 +
 mm/mmap.c                              | 10 +++++++---
 4 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/tile/mm/elf.c b/arch/tile/mm/elf.c
index 6225cc9..dae4b33 100644
--- a/arch/tile/mm/elf.c
+++ b/arch/tile/mm/elf.c
@@ -142,6 +142,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	if (!retval) {
 		unsigned long addr = MEM_USER_INTRPT;
 		addr = mmap_region(NULL, addr, INTRPT_SIZE,
+				   MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,
 				   VM_READ|VM_EXEC|
 				   VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, 0);
 		if (addr > (unsigned long) -PAGE_SIZE)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index ed6407d..31dcdfb 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2048,7 +2048,8 @@ extern int install_special_mapping(struct mm_struct *mm,
 extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 
 extern unsigned long mmap_region(struct file *file, unsigned long addr,
-	unsigned long len, vm_flags_t vm_flags, unsigned long pgoff);
+	unsigned long len, unsigned long mmap_flags,
+	vm_flags_t vm_flags, unsigned long pgoff);
 extern unsigned long do_mmap(struct file *file, unsigned long addr,
 	unsigned long len, unsigned long prot, unsigned long flags,
 	vm_flags_t vm_flags, unsigned long pgoff, unsigned long *populate);
diff --git a/include/uapi/asm-generic/mman-common.h b/include/uapi/asm-generic/mman-common.h
index 5827438..3655be3 100644
--- a/include/uapi/asm-generic/mman-common.h
+++ b/include/uapi/asm-generic/mman-common.h
@@ -19,6 +19,7 @@
 #define MAP_TYPE	0x0f		/* Mask for type of mapping */
 #define MAP_FIXED	0x10		/* Interpret addr exactly */
 #define MAP_ANONYMOUS	0x20		/* don't use a file */
+#define MAP_DONTUNMAP	0x40		/* don't unmap overlapping VMA */
 #ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
 # define MAP_UNINITIALIZED 0x4000000	/* For anonymous mmap, memory could be uninitialized */
 #else
diff --git a/mm/mmap.c b/mm/mmap.c
index bd2e1a53..ab429c3 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1286,7 +1286,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
 			vm_flags |= VM_NORESERVE;
 	}
 
-	addr = mmap_region(file, addr, len, vm_flags, pgoff);
+	addr = mmap_region(file, addr, len, flags, vm_flags, pgoff);
 	if (!IS_ERR_VALUE(addr) &&
 	    ((vm_flags & VM_LOCKED) ||
 	     (flags & (MAP_POPULATE | MAP_NONBLOCK)) == MAP_POPULATE))
@@ -1422,7 +1422,8 @@ static inline int accountable_mapping(struct file *file, vm_flags_t vm_flags)
 }
 
 unsigned long mmap_region(struct file *file, unsigned long addr,
-		unsigned long len, vm_flags_t vm_flags, unsigned long pgoff)
+		unsigned long len, unsigned long mmap_flags,
+		vm_flags_t vm_flags, unsigned long pgoff)
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma, *prev;
@@ -1448,7 +1449,10 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
 	/* Clear old maps */
 	while (find_vma_links(mm, addr, addr + len, &prev, &rb_link,
 			      &rb_parent)) {
-		if (do_munmap(mm, addr, len))
+		const bool dont_unmap =
+				(mmap_flags & (MAP_DONTUNMAP | MAP_FIXED))
+				== (MAP_DONTUNMAP | MAP_FIXED);
+		if (dont_unmap || do_munmap(mm, addr, len))
 			return -ENOMEM;
 	}
 
-- 
2.7.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

             reply	other threads:[~2016-04-02 19:18 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-02 19:17 Piotr Kwapulinski [this message]
2016-04-02 19:17 ` [PATCH 0/3] mm/mmap.c: don't unmap the overlapping VMA(s) Piotr Kwapulinski
2016-04-02 19:17 ` [PATCH 1/3] man/mmap.2: " Piotr Kwapulinski
2016-04-02 19:17   ` Piotr Kwapulinski
2016-04-02 19:17 ` [PATCH 2/3] mm/mremap.c: " Piotr Kwapulinski
2016-04-02 19:17   ` Piotr Kwapulinski
2016-04-02 19:17 ` [PATCH 3/3] man/mremap.2: " Piotr Kwapulinski
2016-04-02 19:17   ` Piotr Kwapulinski
2016-04-02 21:54 ` [PATCH 0/3] mm/mmap.c: " Kirill A. Shutemov
2016-04-02 21:54   ` Kirill A. Shutemov
2016-04-03  5:52 ` Konstantin Khlebnikov
2016-04-03  5:52   ` Konstantin Khlebnikov
2016-04-03  5:52   ` Konstantin Khlebnikov
2016-04-04  7:31 ` Michal Hocko
2016-04-04  7:31   ` Michal Hocko
2016-04-04 15:26   ` Vlastimil Babka
2016-04-04 15:26     ` Vlastimil Babka
2016-04-07 16:11     ` Piotr Kwapulinski
2016-04-07 16:11       ` Piotr Kwapulinski
2016-04-07 16:31       ` Michal Hocko
2016-04-07 16:31         ` Michal Hocko
2016-04-08 15:32         ` Piotr Kwapulinski
2016-04-08 15:32           ` Piotr Kwapulinski
2016-04-07 16:20     ` Piotr Kwapulinski
2016-04-07 16:20       ` Piotr Kwapulinski

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=1459624654-7955-1-git-send-email-kwapulinski.piotr@gmail.com \
    --to=kwapulinski.piotr@gmail.com \
    --cc=aarcange@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=aryabinin@virtuozzo.com \
    --cc=cmetcalf@mellanox.com \
    --cc=dan.j.williams@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=dave@stgolabs.net \
    --cc=denc716@gmail.com \
    --cc=gang.chen.5i5j@gmail.com \
    --cc=hannes@cmpxchg.org \
    --cc=iamjoonsoo.kim@lge.com \
    --cc=jack@suse.cz \
    --cc=kirill.shutemov@linux.intel.com \
    --cc=koct9i@gmail.com \
    --cc=kuleshovmail@gmail.com \
    --cc=ldufour@linux.vnet.ibm.com \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mhocko@suse.com \
    --cc=mingo@kernel.org \
    --cc=mszeredi@suse.cz \
    --cc=mtk.manpages@gmail.com \
    --cc=oleg@redhat.com \
    --cc=rientjes@google.com \
    --cc=toshi.kani@hpe.com \
    --cc=vbabka@suse.cz \
    --cc=viro@zeniv.linux.org.uk \
    --cc=xiexiuqi@huawei.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.