Skip to content

Commit

Permalink
mm: untag user pointers passed to memory syscalls
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Khalid Aziz <[email protected]>
Reviewed-by: Vincenzo Frascino <[email protected]>
Reviewed-by: Catalin Marinas <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Cc: Al Viro <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: Eric Auger <[email protected]>
Cc: Felix Kuehling <[email protected]>
Cc: Jens Wiklander <[email protected]>
Cc: Mauro Carvalho Chehab <[email protected]>
Cc: Mike Rapoport <[email protected]>
Cc: Will Deacon <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
xairy authored and torvalds committed Sep 26, 2019
1 parent 903f433 commit 057d338
Show file tree
Hide file tree
Showing 8 changed files with 23 additions and 1 deletion.
2 changes: 2 additions & 0 deletions mm/madvise.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
3 changes: 3 additions & 0 deletions mm/mempolicy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion mm/migrate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions mm/mincore.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions mm/mlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions mm/mprotect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions mm/mremap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions mm/msync.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit 057d338

Please sign in to comment.