Pablo Greco 08b3cc
From a34309d16f41c48ffd90e56a6f865d6a1a8c49f0 Mon Sep 17 00:00:00 2001
Pablo Greco 08b3cc
From: Catalin Marinas <catalin.marinas@arm.com>
Pablo Greco 08b3cc
Date: Wed, 19 Feb 2020 12:31:56 +0000
Pablo Greco 08b3cc
Subject: [PATCH] mm: Avoid creating virtual address aliases in
Pablo Greco 08b3cc
 brk()/mmap()/mremap()
Pablo Greco 08b3cc
Pablo Greco 08b3cc
Currently the arm64 kernel ignores the top address byte passed to brk(),
Pablo Greco 08b3cc
mmap() and mremap(). When the user is not aware of the 56-bit address
Pablo Greco 08b3cc
limit or relies on the kernel to return an error, untagging such
Pablo Greco 08b3cc
pointers has the potential to create address aliases in user-space.
Pablo Greco 08b3cc
Passing a tagged address to munmap(), madvise() is permitted since the
Pablo Greco 08b3cc
tagged pointer is expected to be inside an existing mapping.
Pablo Greco 08b3cc
Pablo Greco 08b3cc
The current behaviour breaks the existing glibc malloc() implementation
Pablo Greco 08b3cc
which relies on brk() with an address beyond 56-bit to be rejected by
Pablo Greco 08b3cc
the kernel.
Pablo Greco 08b3cc
Pablo Greco 08b3cc
Remove untagging in the above functions by partially reverting commit
Pablo Greco 08b3cc
ce18d171cb73 ("mm: untag user pointers in mmap/munmap/mremap/brk"). In
Pablo Greco 08b3cc
addition, update the arm64 tagged-address-abi.rst document accordingly.
Pablo Greco 08b3cc
Pablo Greco 08b3cc
Link: https://bugzilla.redhat.com/1797052
Pablo Greco 08b3cc
Fixes: ce18d171cb73 ("mm: untag user pointers in mmap/munmap/mremap/brk")
Pablo Greco 08b3cc
Cc: <stable@vger.kernel.org> # 5.4.x-
Pablo Greco 08b3cc
Cc: Andrew Morton <akpm@linux-foundation.org>
Pablo Greco 08b3cc
Cc: Florian Weimer <fweimer@redhat.com>
Pablo Greco 08b3cc
Reported-by: Victor Stinner <vstinner@redhat.com>
Pablo Greco 08b3cc
Acked-by: Will Deacon <will@kernel.org>
Pablo Greco 08b3cc
Acked-by: Andrey Konovalov <andreyknvl@google.com>
Pablo Greco 08b3cc
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Pablo Greco 08b3cc
---
Pablo Greco 08b3cc
 Documentation/arm64/tagged-address-abi.rst | 11 +++++++++--
Pablo Greco 08b3cc
 mm/mmap.c                                  |  4 ----
Pablo Greco 08b3cc
 mm/mremap.c                                |  1 -
Pablo Greco 08b3cc
 3 files changed, 9 insertions(+), 7 deletions(-)
Pablo Greco 08b3cc
Pablo Greco 08b3cc
diff --git a/Documentation/arm64/tagged-address-abi.rst b/Documentation/arm64/tagged-address-abi.rst
Pablo Greco 08b3cc
index d4a85d535bf9..f6289116893c 100644
Pablo Greco 08b3cc
--- a/Documentation/arm64/tagged-address-abi.rst
Pablo Greco 08b3cc
+++ b/Documentation/arm64/tagged-address-abi.rst
Pablo Greco 08b3cc
@@ -44,8 +44,15 @@ The AArch64 Tagged Address ABI has two stages of relaxation depending
Pablo Greco 08b3cc
 how the user addresses are used by the kernel:
Pablo Greco 08b3cc
 
Pablo Greco 08b3cc
 1. User addresses not accessed by the kernel but used for address space
Pablo Greco 08b3cc
-   management (e.g. ``mmap()``, ``mprotect()``, ``madvise()``). The use
Pablo Greco 08b3cc
-   of valid tagged pointers in this context is always allowed.
Pablo Greco 08b3cc
+   management (e.g. ``mprotect()``, ``madvise()``). The use of valid
Pablo Greco 08b3cc
+   tagged pointers in this context is allowed with the exception of
Pablo Greco 08b3cc
+   ``brk()``, ``mmap()`` and the ``new_address`` argument to
Pablo Greco 08b3cc
+   ``mremap()`` as these have the potential of aliasing with existing
Pablo Greco 08b3cc
+   user addresses.
Pablo Greco 08b3cc
+
Pablo Greco 08b3cc
+   NOTE: This behaviour changed in v5.6 and so some earlier kernels may
Pablo Greco 08b3cc
+   incorrectly accept valid tagged pointers for the ``brk()``,
Pablo Greco 08b3cc
+   ``mmap()`` and ``mremap()`` system calls.
Pablo Greco 08b3cc
 
Pablo Greco 08b3cc
 2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
Pablo Greco 08b3cc
    relaxation is disabled by default and the application thread needs to
Pablo Greco 08b3cc
diff --git a/mm/mmap.c b/mm/mmap.c
Pablo Greco 08b3cc
index 4390dbea4aa5..514cc19c5916 100644
Pablo Greco 08b3cc
--- a/mm/mmap.c
Pablo Greco 08b3cc
+++ b/mm/mmap.c
Pablo Greco 08b3cc
@@ -195,8 +195,6 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
Pablo Greco 08b3cc
 	bool downgraded = false;
Pablo Greco 08b3cc
 	LIST_HEAD(uf);
Pablo Greco 08b3cc
 
Pablo Greco 08b3cc
-	brk = untagged_addr(brk);
Pablo Greco 08b3cc
-
Pablo Greco 08b3cc
 	if (down_write_killable(&mm->mmap_sem))
Pablo Greco 08b3cc
 		return -EINTR;
Pablo Greco 08b3cc
 
Pablo Greco 08b3cc
@@ -1583,8 +1581,6 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
Pablo Greco 08b3cc
 	struct file *file = NULL;
Pablo Greco 08b3cc
 	unsigned long retval;
Pablo Greco 08b3cc
 
Pablo Greco 08b3cc
-	addr = untagged_addr(addr);
Pablo Greco 08b3cc
-
Pablo Greco 08b3cc
 	if (!(flags & MAP_ANONYMOUS)) {
Pablo Greco 08b3cc
 		audit_mmap_fd(fd, flags);
Pablo Greco 08b3cc
 		file = fget(fd);
Pablo Greco 08b3cc
diff --git a/mm/mremap.c b/mm/mremap.c
Pablo Greco 08b3cc
index 1fc8a29fbe3f..1d98281f7204 100644
Pablo Greco 08b3cc
--- a/mm/mremap.c
Pablo Greco 08b3cc
+++ b/mm/mremap.c
Pablo Greco 08b3cc
@@ -607,7 +607,6 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
Pablo Greco 08b3cc
 	LIST_HEAD(uf_unmap);
Pablo Greco 08b3cc
 
Pablo Greco 08b3cc
 	addr = untagged_addr(addr);
Pablo Greco 08b3cc
-	new_addr = untagged_addr(new_addr);
Pablo Greco 08b3cc
 
Pablo Greco 08b3cc
 	if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
Pablo Greco 08b3cc
 		return ret;
Pablo Greco 08b3cc
-- 
Pablo Greco 08b3cc
2.24.1
Pablo Greco 08b3cc