mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-07 14:32:23 +00:00
mm: userfaultfd: check for start + len overflow in validate_range
Most userfaultfd ioctls take a `start + len` range as an argument. We have the validate_range helper to check that such ranges are valid. However, some (but not all!) ioctls *also* check that `start + len` doesn't wrap around (overflow). Just check for this in validate_range. This saves some repetitive code, and adds the check to some ioctls which weren't bothering to check for it before. [axelrasmussen@google.com: call validate_range() on the src range too] Link: https://lkml.kernel.org/r/20230714182932.2608735-1-axelrasmussen@google.com [axelrasmussen@google.com: fix src/dst validation] Link: https://lkml.kernel.org/r/20230810192128.1855570-1-axelrasmussen@google.com Link: https://lkml.kernel.org/r/20230707215540.2324998-3-axelrasmussen@google.com Signed-off-by: Axel Rasmussen <axelrasmussen@google.com> Reviewed-by: Peter Xu <peterx@redhat.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Brian Geffon <bgeffon@google.com> Cc: Christian Brauner <brauner@kernel.org> Cc: David Hildenbrand <david@redhat.com> Cc: Gaosheng Cui <cuigaosheng1@huawei.com> Cc: Huang, Ying <ying.huang@intel.com> Cc: Hugh Dickins <hughd@google.com> Cc: James Houghton <jthoughton@google.com> Cc: Jan Alexander Steffens (heftig) <heftig@archlinux.org> Cc: Jiaqi Yan <jiaqiyan@google.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Kefeng Wang <wangkefeng.wang@huawei.com> Cc: Liam R. Howlett <Liam.Howlett@oracle.com> Cc: Miaohe Lin <linmiaohe@huawei.com> Cc: Mike Kravetz <mike.kravetz@oracle.com> Cc: Mike Rapoport (IBM) <rppt@kernel.org> Cc: Muchun Song <muchun.song@linux.dev> Cc: Nadav Amit <namit@vmware.com> Cc: Naoya Horiguchi <naoya.horiguchi@nec.com> Cc: Ryan Roberts <ryan.roberts@arm.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Suleiman Souhlal <suleiman@google.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: T.J. Alumbaugh <talumbau@google.com> Cc: Yu Zhao <yuzhao@google.com> Cc: ZhangPeng <zhangpeng362@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
f92cedfa39
commit
2ef5d7245d
@ -1289,13 +1289,11 @@ static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx,
|
||||
__wake_userfault(ctx, range);
|
||||
}
|
||||
|
||||
static __always_inline int validate_range(struct mm_struct *mm,
|
||||
__u64 start, __u64 len)
|
||||
static __always_inline int validate_unaligned_range(
|
||||
struct mm_struct *mm, __u64 start, __u64 len)
|
||||
{
|
||||
__u64 task_size = mm->task_size;
|
||||
|
||||
if (start & ~PAGE_MASK)
|
||||
return -EINVAL;
|
||||
if (len & ~PAGE_MASK)
|
||||
return -EINVAL;
|
||||
if (!len)
|
||||
@ -1306,9 +1304,20 @@ static __always_inline int validate_range(struct mm_struct *mm,
|
||||
return -EINVAL;
|
||||
if (len > task_size - start)
|
||||
return -EINVAL;
|
||||
if (start + len <= start)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline int validate_range(struct mm_struct *mm,
|
||||
__u64 start, __u64 len)
|
||||
{
|
||||
if (start & ~PAGE_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
return validate_unaligned_range(mm, start, len);
|
||||
}
|
||||
|
||||
static int userfaultfd_register(struct userfaultfd_ctx *ctx,
|
||||
unsigned long arg)
|
||||
{
|
||||
@ -1757,17 +1766,15 @@ static int userfaultfd_copy(struct userfaultfd_ctx *ctx,
|
||||
sizeof(uffdio_copy)-sizeof(__s64)))
|
||||
goto out;
|
||||
|
||||
ret = validate_unaligned_range(ctx->mm, uffdio_copy.src,
|
||||
uffdio_copy.len);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = validate_range(ctx->mm, uffdio_copy.dst, uffdio_copy.len);
|
||||
if (ret)
|
||||
goto out;
|
||||
/*
|
||||
* double check for wraparound just in case. copy_from_user()
|
||||
* will later check uffdio_copy.src + uffdio_copy.len to fit
|
||||
* in the userland range.
|
||||
*/
|
||||
|
||||
ret = -EINVAL;
|
||||
if (uffdio_copy.src + uffdio_copy.len <= uffdio_copy.src)
|
||||
goto out;
|
||||
if (uffdio_copy.mode & ~(UFFDIO_COPY_MODE_DONTWAKE|UFFDIO_COPY_MODE_WP))
|
||||
goto out;
|
||||
if (uffdio_copy.mode & UFFDIO_COPY_MODE_WP)
|
||||
@ -1927,11 +1934,6 @@ static int userfaultfd_continue(struct userfaultfd_ctx *ctx, unsigned long arg)
|
||||
goto out;
|
||||
|
||||
ret = -EINVAL;
|
||||
/* double check for wraparound just in case. */
|
||||
if (uffdio_continue.range.start + uffdio_continue.range.len <=
|
||||
uffdio_continue.range.start) {
|
||||
goto out;
|
||||
}
|
||||
if (uffdio_continue.mode & ~(UFFDIO_CONTINUE_MODE_DONTWAKE |
|
||||
UFFDIO_CONTINUE_MODE_WP))
|
||||
goto out;
|
||||
|
Loading…
Reference in New Issue
Block a user