All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] riscv: Make mmap allocation top-down by default
@ 2019-01-27 16:53 Alexandre Ghiti
  0 siblings, 0 replies; only message in thread
From: Alexandre Ghiti @ 2019-01-27 16:53 UTC (permalink / raw)
  To: Palmer Dabbelt, Albert Ou, hch, linux-riscv; +Cc: Alexandre Ghiti

In order to avoid wasting user address space by using bottom-up mmap
allocation scheme, prefer top-down scheme when possible.

This patch is based on arm64 implementation.

Before:

root@qemuriscv64:~# cat /proc/176/maps
00010000-000be000 r-xp 00000000 fe:00 6355     /bin/bash.bash
000be000-000bf000 r--p 000ad000 fe:00 6355     /bin/bash.bash
000bf000-000c8000 rw-p 000ae000 fe:00 6355     /bin/bash.bash
000c8000-00114000 rw-p 00000000 00:00 0        [heap]
2000000000-2000017000 r-xp 00000000 fe:00 7193 /lib/ld-2.28.so
2000017000-2000018000 r--p 00016000 fe:00 7193 /lib/ld-2.28.so
2000018000-2000019000 rw-p 00017000 fe:00 7193 /lib/ld-2.28.so
2000019000-200001a000 rw-p 00000000 00:00 0
200001a000-200001c000 r-xp 00000000 00:00 0    [vdso]
200001e000-2000020000 rw-p 00000000 00:00 0
2000020000-2000041000 r-xp 00000000 fe:00 7176 /lib/libtinfo.so.5.9
2000041000-2000045000 r--p 00020000 fe:00 7176 /lib/libtinfo.so.5.9
2000045000-2000046000 rw-p 00024000 fe:00 7176 /lib/libtinfo.so.5.9
2000046000-2000048000 r-xp 00000000 fe:00 7112 /lib/libdl-2.28.so
2000048000-2000049000 r--p 00001000 fe:00 7112 /lib/libdl-2.28.so
2000049000-200004a000 rw-p 00002000 fe:00 7112 /lib/libdl-2.28.so
200004a000-2000148000 r-xp 00000000 fe:00 7187 /lib/libc-2.28.so
2000148000-200014c000 r--p 000fd000 fe:00 7187 /lib/libc-2.28.so
200014c000-200014e000 rw-p 00101000 fe:00 7187 /lib/libc-2.28.so
200014e000-2000154000 rw-p 00000000 00:00 0
2000154000-2000159000 r-xp 00000000 fe:00 7100 /lib/libnss_compat-2.28.so
2000159000-200015a000 r--p 00004000 fe:00 7100 /lib/libnss_compat-2.28.so
200015a000-200015b000 rw-p 00005000 fe:00 7100 /lib/libnss_compat-2.28.so
3fff9a4000-3fff9c5000 rw-p 00000000 00:00 0    [stack]

After:

root@qemuriscv64:~# cat /proc/173/maps
00010000-000be000 r-xp 00000000 fe:00 6355     /bin/bash.bash
000be000-000bf000 r--p 000ad000 fe:00 6355     /bin/bash.bash
000bf000-000c8000 rw-p 000ae000 fe:00 6355     /bin/bash.bash
000c8000-00114000 rw-p 00000000 00:00 0        [heap]
3fdd8d0000-3fdd8d5000 r-xp 00000000 fe:00 7100 /lib/libnss_compat-2.28.so
3fdd8d5000-3fdd8d6000 r--p 00004000 fe:00 7100 /lib/libnss_compat-2.28.so
3fdd8d6000-3fdd8d7000 rw-p 00005000 fe:00 7100 /lib/libnss_compat-2.28.so
3fdd8d7000-3fdd8d9000 rw-p 00000000 00:00 0
3fdd8d9000-3fdd9d7000 r-xp 00000000 fe:00 7187 /lib/libc-2.28.so
3fdd9d7000-3fdd9db000 r--p 000fd000 fe:00 7187 /lib/libc-2.28.so
3fdd9db000-3fdd9dd000 rw-p 00101000 fe:00 7187 /lib/libc-2.28.so
3fdd9dd000-3fdd9e1000 rw-p 00000000 00:00 0
3fdd9e1000-3fdd9e3000 r-xp 00000000 fe:00 7112 /lib/libdl-2.28.so
3fdd9e3000-3fdd9e4000 r--p 00001000 fe:00 7112 /lib/libdl-2.28.so
3fdd9e4000-3fdd9e5000 rw-p 00002000 fe:00 7112 /lib/libdl-2.28.so
3fdd9e5000-3fdda06000 r-xp 00000000 fe:00 7176 /lib/libtinfo.so.5.9
3fdda06000-3fdda0a000 r--p 00020000 fe:00 7176 /lib/libtinfo.so.5.9
3fdda0a000-3fdda0b000 rw-p 00024000 fe:00 7176 /lib/libtinfo.so.5.9
3fdda0b000-3fdda0d000 rw-p 00000000 00:00 0
3fdda0f000-3fdda11000 r-xp 00000000 00:00 0    [vdso]
3fdda11000-3fdda28000 r-xp 00000000 fe:00 7193 /lib/ld-2.28.so
3fdda28000-3fdda29000 r--p 00016000 fe:00 7193 /lib/ld-2.28.so
3fdda29000-3fdda2a000 rw-p 00017000 fe:00 7193 /lib/ld-2.28.so
3fdda2a000-3fdda2b000 rw-p 00000000 00:00 0
3ffff8e000-3ffffaf000 rw-p 00000000 00:00 0    [stack]

Signed-off-by: Alexandre Ghiti <alex@ghiti.fr>
---
 arch/riscv/Kconfig                 | 12 ++++++
 arch/riscv/include/asm/processor.h |  1 +
 arch/riscv/mm/Makefile             |  1 +
 arch/riscv/mm/mmap.c               | 69 ++++++++++++++++++++++++++++++
 4 files changed, 83 insertions(+)
 create mode 100644 arch/riscv/mm/mmap.c

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index e0d7d61779a6..684f3e00e9f8 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -47,6 +47,18 @@ config RISCV
 	select GENERIC_IRQ_MULTI_HANDLER
 	select ARCH_HAS_PTE_SPECIAL
 
+config HAVE_ARCH_MMAP_RND_BITS
+	def_bool y
+
+config ARCH_MMAP_RND_BITS_MIN
+	default 18
+
+# max bits determined by the following formula:
+#  VA_BITS - PAGE_SHIFT - 3
+config ARCH_MMAP_RND_BITS_MAX
+	default 33 if 64BIT # SV48 based
+	default 18
+
 config MMU
 	def_bool y
 
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index 0531f49af5c3..5ea9119f173c 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -23,6 +23,7 @@
  * space during mmap's.
  */
 #define TASK_UNMAPPED_BASE	PAGE_ALIGN(TASK_SIZE >> 1)
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
 
 #define STACK_TOP		TASK_SIZE
 #define STACK_TOP_MAX		STACK_TOP
diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
index eb22ab49b3e0..0eb23b10d0bd 100644
--- a/arch/riscv/mm/Makefile
+++ b/arch/riscv/mm/Makefile
@@ -3,3 +3,4 @@ obj-y += fault.o
 obj-y += extable.o
 obj-y += ioremap.o
 obj-y += cacheflush.o
+obj-y += mmap.o
diff --git a/arch/riscv/mm/mmap.c b/arch/riscv/mm/mmap.c
new file mode 100644
index 000000000000..d182ac66d2e7
--- /dev/null
+++ b/arch/riscv/mm/mmap.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/mm.h>
+#include <linux/sched/mm.h>
+#include <linux/sizes.h>
+#include <linux/personality.h>
+#include <linux/random.h>
+
+/*
+ * Leave enough space between the mmap area and the stack to honour ulimit in
+ * the face of randomisation.
+ */
+#define MIN_GAP (SZ_128M)
+#define MAX_GAP	(TASK_SIZE / 6 * 5)
+
+static int mmap_is_legacy(struct rlimit *rlim_stack)
+{
+	if (current->personality & ADDR_COMPAT_LAYOUT)
+		return 1;
+
+	if (rlim_stack->rlim_cur == RLIM_INFINITY)
+		return 1;
+
+	return sysctl_legacy_va_layout;
+}
+
+static unsigned long arch_mmap_rnd(void)
+{
+	unsigned long rnd;
+
+	rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
+
+	return rnd << PAGE_SHIFT;
+}
+
+static unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack)
+{
+	unsigned long gap = rlim_stack->rlim_cur;
+
+	if (gap < MIN_GAP)
+		gap = MIN_GAP;
+	else if (gap > MAX_GAP)
+		gap = MAX_GAP;
+
+	return PAGE_ALIGN(TASK_SIZE - gap - rnd);
+}
+
+/*
+ * This function, called very early during the creation of a new process VM
+ * image, sets up which VM layout function to use:
+ */
+void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
+{
+	unsigned long random_factor = 0UL;
+
+	if (current->flags & PF_RANDOMIZE)
+		random_factor = arch_mmap_rnd();
+
+	/*
+	 * Fall back to the standard layout if the personality bit is set, or
+	 * if the expected stack growth is unlimited:
+	 */
+	if (mmap_is_legacy(rlim_stack)) {
+		mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
+		mm->get_unmapped_area = arch_get_unmapped_area;
+	} else {
+		mm->mmap_base = mmap_base(random_factor, rlim_stack);
+		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+	}
+}
-- 
2.20.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2019-01-27 16:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-27 16:53 [PATCH] riscv: Make mmap allocation top-down by default Alexandre Ghiti

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.