mm: untag user pointers passed to memory syscalls
authorAndrey Konovalov <andreyknvl@google.com>
Wed, 25 Sep 2019 23:48:30 +0000 (16:48 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 26 Sep 2019 00:51:41 +0000 (17:51 -0700)
This patch is a part of a series that extends kernel ABI to allow to pass
tagged user pointers (with the top byte set to something else other than
0x00) as syscall arguments.

This patch allows tagged pointers to be passed to the following memory
syscalls: get_mempolicy, madvise, mbind, mincore, mlock, mlock2, mprotect,
mremap, msync, munlock, move_pages.

The mmap and mremap syscalls do not currently accept tagged addresses.
Architectures may interpret the tag as a background colour for the
corresponding vma.

Link: http://lkml.kernel.org/r/aaf0c0969d46b2feb9017f3e1b3ef3970b633d91.1563904656.git.andreyknvl@google.com
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
Reviewed-by: Khalid Aziz <khalid.aziz@oracle.com>
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Felix Kuehling <Felix.Kuehling@amd.com>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Cc: Mike Rapoport <rppt@linux.ibm.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/madvise.c
mm/mempolicy.c
mm/migrate.c
mm/mincore.c
mm/mlock.c
mm/mprotect.c
mm/mremap.c
mm/msync.c

index 68ab988ad4333b43ae6102d147e94891097c0ae6..1f8a6fdc687856f12b406bb381acfc75946519e3 100644 (file)
@@ -784,6 +784,8 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior)
        size_t len;
        struct blk_plug plug;
 
+       start = untagged_addr(start);
+
        if (!madvise_behavior_valid(behavior))
                return error;
 
index 464406e8da9109b63d705132c3ea5f2187dd8c2e..de27d08b1ff8d286ce0eb463041eefc8a746d869 100644 (file)
@@ -1405,6 +1405,7 @@ static long kernel_mbind(unsigned long start, unsigned long len,
        int err;
        unsigned short mode_flags;
 
+       start = untagged_addr(start);
        mode_flags = mode & MPOL_MODE_FLAGS;
        mode &= ~MPOL_MODE_FLAGS;
        if (mode >= MPOL_MAX)
@@ -1558,6 +1559,8 @@ static int kernel_get_mempolicy(int __user *policy,
        int uninitialized_var(pval);
        nodemask_t nodes;
 
+       addr = untagged_addr(addr);
+
        if (nmask != NULL && maxnode < nr_node_ids)
                return -EINVAL;
 
index 73d476d690b10555909b8ac3974a9077faec5cf0..4fe45d1428c8676133cf17d4a84e9cbbd6d27bbb 100644 (file)
@@ -1612,7 +1612,7 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes,
                        goto out_flush;
                if (get_user(node, nodes + i))
                        goto out_flush;
-               addr = (unsigned long)p;
+               addr = (unsigned long)untagged_addr(p);
 
                err = -ENODEV;
                if (node < 0 || node >= MAX_NUMNODES)
index f9a9dbe8cd330107b312aef9764dbc74b8f6a766..49b6fa2f6aa1d6ef84eddfddbbf9754ae7858893 100644 (file)
@@ -256,6 +256,8 @@ SYSCALL_DEFINE3(mincore, unsigned long, start, size_t, len,
        unsigned long pages;
        unsigned char *tmp;
 
+       start = untagged_addr(start);
+
        /* Check the start address: needs to be page-aligned.. */
        if (start & ~PAGE_MASK)
                return -EINVAL;
index a90099da4fb41658a21ed290cfe7c8528273f5ea..a72c1eeded7729482e3e93eb47150b7d9d2f763a 100644 (file)
@@ -674,6 +674,8 @@ static __must_check int do_mlock(unsigned long start, size_t len, vm_flags_t fla
        unsigned long lock_limit;
        int error = -ENOMEM;
 
+       start = untagged_addr(start);
+
        if (!can_do_mlock())
                return -EPERM;
 
@@ -735,6 +737,8 @@ SYSCALL_DEFINE2(munlock, unsigned long, start, size_t, len)
 {
        int ret;
 
+       start = untagged_addr(start);
+
        len = PAGE_ALIGN(len + (offset_in_page(start)));
        start &= PAGE_MASK;
 
index 675e5d34a5077303648f72bb2af9439449d9544c..7967825f6d3352b3b57ccd23018d461d41498b78 100644 (file)
@@ -459,6 +459,8 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
        const bool rier = (current->personality & READ_IMPLIES_EXEC) &&
                                (prot & PROT_READ);
 
+       start = untagged_addr(start);
+
        prot &= ~(PROT_GROWSDOWN|PROT_GROWSUP);
        if (grows == (PROT_GROWSDOWN|PROT_GROWSUP)) /* can't be both */
                return -EINVAL;
index fc241d23cd97ab34fa73d232e7cb8ce1785f784c..64c9a3b8be0aa2c8f5b1472b8cbb21f20b1c754f 100644 (file)
@@ -606,6 +606,13 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
        LIST_HEAD(uf_unmap_early);
        LIST_HEAD(uf_unmap);
 
+       /*
+        * Architectures may interpret the tag passed to mmap as a background
+        * colour for the corresponding vma. For mremap we don't allow tagged
+        * new_addr to preserve similar behaviour to mmap.
+        */
+       addr = untagged_addr(addr);
+
        if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
                return ret;
 
index ef30a429623a2f8191d9364a0c9a8b4aab0ddc8e..c3bd3e75f68764514e6f92914b4f05253146a3ea 100644 (file)
@@ -37,6 +37,8 @@ SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags)
        int unmapped_error = 0;
        int error = -EINVAL;
 
+       start = untagged_addr(start);
+
        if (flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC))
                goto out;
        if (offset_in_page(start))