Commit 7d032574 authored by Andrey Konovalov's avatar Andrey Konovalov Committed by Linus Torvalds

userfaultfd: untag user pointers

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.

userfaultfd code use provided user pointers for vma lookups, which can
only by done with untagged pointers.

Untag user pointers in validate_range().

Link: http://lkml.kernel.org/r/cdc59ddd7011012ca2e689bc88c3b65b1ea7e413.1563904656.git.andreyknvl@google.comSigned-off-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Reviewed-by: default avatarMike Rapoport <rppt@linux.ibm.com>
Reviewed-by: default avatarVincenzo Frascino <vincenzo.frascino@arm.com>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Reviewed-by: default avatarKees 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: Khalid Aziz <khalid.aziz@oracle.com>
Cc: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ed8a66b8
...@@ -1272,21 +1272,23 @@ static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx, ...@@ -1272,21 +1272,23 @@ static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx,
} }
static __always_inline int validate_range(struct mm_struct *mm, static __always_inline int validate_range(struct mm_struct *mm,
__u64 start, __u64 len) __u64 *start, __u64 len)
{ {
__u64 task_size = mm->task_size; __u64 task_size = mm->task_size;
if (start & ~PAGE_MASK) *start = untagged_addr(*start);
if (*start & ~PAGE_MASK)
return -EINVAL; return -EINVAL;
if (len & ~PAGE_MASK) if (len & ~PAGE_MASK)
return -EINVAL; return -EINVAL;
if (!len) if (!len)
return -EINVAL; return -EINVAL;
if (start < mmap_min_addr) if (*start < mmap_min_addr)
return -EINVAL; return -EINVAL;
if (start >= task_size) if (*start >= task_size)
return -EINVAL; return -EINVAL;
if (len > task_size - start) if (len > task_size - *start)
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
...@@ -1336,7 +1338,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx, ...@@ -1336,7 +1338,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
goto out; goto out;
} }
ret = validate_range(mm, uffdio_register.range.start, ret = validate_range(mm, &uffdio_register.range.start,
uffdio_register.range.len); uffdio_register.range.len);
if (ret) if (ret)
goto out; goto out;
...@@ -1525,7 +1527,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx, ...@@ -1525,7 +1527,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
if (copy_from_user(&uffdio_unregister, buf, sizeof(uffdio_unregister))) if (copy_from_user(&uffdio_unregister, buf, sizeof(uffdio_unregister)))
goto out; goto out;
ret = validate_range(mm, uffdio_unregister.start, ret = validate_range(mm, &uffdio_unregister.start,
uffdio_unregister.len); uffdio_unregister.len);
if (ret) if (ret)
goto out; goto out;
...@@ -1676,7 +1678,7 @@ static int userfaultfd_wake(struct userfaultfd_ctx *ctx, ...@@ -1676,7 +1678,7 @@ static int userfaultfd_wake(struct userfaultfd_ctx *ctx,
if (copy_from_user(&uffdio_wake, buf, sizeof(uffdio_wake))) if (copy_from_user(&uffdio_wake, buf, sizeof(uffdio_wake)))
goto out; goto out;
ret = validate_range(ctx->mm, uffdio_wake.start, uffdio_wake.len); ret = validate_range(ctx->mm, &uffdio_wake.start, uffdio_wake.len);
if (ret) if (ret)
goto out; goto out;
...@@ -1716,7 +1718,7 @@ static int userfaultfd_copy(struct userfaultfd_ctx *ctx, ...@@ -1716,7 +1718,7 @@ static int userfaultfd_copy(struct userfaultfd_ctx *ctx,
sizeof(uffdio_copy)-sizeof(__s64))) sizeof(uffdio_copy)-sizeof(__s64)))
goto out; goto out;
ret = validate_range(ctx->mm, uffdio_copy.dst, uffdio_copy.len); ret = validate_range(ctx->mm, &uffdio_copy.dst, uffdio_copy.len);
if (ret) if (ret)
goto out; goto out;
/* /*
...@@ -1772,7 +1774,7 @@ static int userfaultfd_zeropage(struct userfaultfd_ctx *ctx, ...@@ -1772,7 +1774,7 @@ static int userfaultfd_zeropage(struct userfaultfd_ctx *ctx,
sizeof(uffdio_zeropage)-sizeof(__s64))) sizeof(uffdio_zeropage)-sizeof(__s64)))
goto out; goto out;
ret = validate_range(ctx->mm, uffdio_zeropage.range.start, ret = validate_range(ctx->mm, &uffdio_zeropage.range.start,
uffdio_zeropage.range.len); uffdio_zeropage.range.len);
if (ret) if (ret)
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment