Skip to content

Commit 2ef5d72

Browse files
CmdrMoozyakpm00
authored andcommitted
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. [[email protected]: call validate_range() on the src range too] Link: https://lkml.kernel.org/r/[email protected] [[email protected]: fix src/dst validation] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Axel Rasmussen <[email protected]> Reviewed-by: Peter Xu <[email protected]> Cc: Al Viro <[email protected]> Cc: Brian Geffon <[email protected]> Cc: Christian Brauner <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Gaosheng Cui <[email protected]> Cc: Huang, Ying <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: James Houghton <[email protected]> Cc: Jan Alexander Steffens (heftig) <[email protected]> Cc: Jiaqi Yan <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Kefeng Wang <[email protected]> Cc: Liam R. Howlett <[email protected]> Cc: Miaohe Lin <[email protected]> Cc: Mike Kravetz <[email protected]> Cc: Mike Rapoport (IBM) <[email protected]> Cc: Muchun Song <[email protected]> Cc: Nadav Amit <[email protected]> Cc: Naoya Horiguchi <[email protected]> Cc: Ryan Roberts <[email protected]> Cc: Shuah Khan <[email protected]> Cc: Suleiman Souhlal <[email protected]> Cc: Suren Baghdasaryan <[email protected]> Cc: T.J. Alumbaugh <[email protected]> Cc: Yu Zhao <[email protected]> Cc: ZhangPeng <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent f92cedf commit 2ef5d72

File tree

1 file changed

+18
-16
lines changed

1 file changed

+18
-16
lines changed

fs/userfaultfd.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,13 +1289,11 @@ static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx,
12891289
__wake_userfault(ctx, range);
12901290
}
12911291

1292-
static __always_inline int validate_range(struct mm_struct *mm,
1293-
__u64 start, __u64 len)
1292+
static __always_inline int validate_unaligned_range(
1293+
struct mm_struct *mm, __u64 start, __u64 len)
12941294
{
12951295
__u64 task_size = mm->task_size;
12961296

1297-
if (start & ~PAGE_MASK)
1298-
return -EINVAL;
12991297
if (len & ~PAGE_MASK)
13001298
return -EINVAL;
13011299
if (!len)
@@ -1306,9 +1304,20 @@ static __always_inline int validate_range(struct mm_struct *mm,
13061304
return -EINVAL;
13071305
if (len > task_size - start)
13081306
return -EINVAL;
1307+
if (start + len <= start)
1308+
return -EINVAL;
13091309
return 0;
13101310
}
13111311

1312+
static __always_inline int validate_range(struct mm_struct *mm,
1313+
__u64 start, __u64 len)
1314+
{
1315+
if (start & ~PAGE_MASK)
1316+
return -EINVAL;
1317+
1318+
return validate_unaligned_range(mm, start, len);
1319+
}
1320+
13121321
static int userfaultfd_register(struct userfaultfd_ctx *ctx,
13131322
unsigned long arg)
13141323
{
@@ -1757,17 +1766,15 @@ static int userfaultfd_copy(struct userfaultfd_ctx *ctx,
17571766
sizeof(uffdio_copy)-sizeof(__s64)))
17581767
goto out;
17591768

1769+
ret = validate_unaligned_range(ctx->mm, uffdio_copy.src,
1770+
uffdio_copy.len);
1771+
if (ret)
1772+
goto out;
17601773
ret = validate_range(ctx->mm, uffdio_copy.dst, uffdio_copy.len);
17611774
if (ret)
17621775
goto out;
1763-
/*
1764-
* double check for wraparound just in case. copy_from_user()
1765-
* will later check uffdio_copy.src + uffdio_copy.len to fit
1766-
* in the userland range.
1767-
*/
1776+
17681777
ret = -EINVAL;
1769-
if (uffdio_copy.src + uffdio_copy.len <= uffdio_copy.src)
1770-
goto out;
17711778
if (uffdio_copy.mode & ~(UFFDIO_COPY_MODE_DONTWAKE|UFFDIO_COPY_MODE_WP))
17721779
goto out;
17731780
if (uffdio_copy.mode & UFFDIO_COPY_MODE_WP)
@@ -1927,11 +1934,6 @@ static int userfaultfd_continue(struct userfaultfd_ctx *ctx, unsigned long arg)
19271934
goto out;
19281935

19291936
ret = -EINVAL;
1930-
/* double check for wraparound just in case. */
1931-
if (uffdio_continue.range.start + uffdio_continue.range.len <=
1932-
uffdio_continue.range.start) {
1933-
goto out;
1934-
}
19351937
if (uffdio_continue.mode & ~(UFFDIO_CONTINUE_MODE_DONTWAKE |
19361938
UFFDIO_CONTINUE_MODE_WP))
19371939
goto out;

0 commit comments

Comments
 (0)