linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH mm-unstable fix] mm: userfaultfd: check for start + len overflow in validate_range: fix
@ 2023-08-10 19:21 Axel Rasmussen
  2023-08-10 19:30 ` Yu Zhao
  2023-08-11 20:51 ` Peter Xu
  0 siblings, 2 replies; 7+ messages in thread
From: Axel Rasmussen @ 2023-08-10 19:21 UTC (permalink / raw)
  To: Alexander Viro, Andrew Morton, Brian Geffon, Christian Brauner,
	David Hildenbrand, Gaosheng Cui, Huang Ying, Hugh Dickins,
	James Houghton, Jiaqi Yan, Jonathan Corbet, Kefeng Wang,
	Liam R. Howlett, Miaohe Lin, Mike Kravetz, Mike Rapoport (IBM),
	Muchun Song, Nadav Amit, Naoya Horiguchi, Peter Xu, Ryan Roberts,
	Shuah Khan, Steven Barrett, Suleiman Souhlal, Suren Baghdasaryan,
	T.J. Alumbaugh, Yu Zhao, ZhangPeng
  Cc: linux-doc, linux-kernel, linux-fsdevel, linux-mm, linux-kselftest,
	Axel Rasmussen

A previous fixup to this commit fixed one issue, but introduced another:
we're now overly strict when validating the src address for UFFDIO_COPY.

Most of the validation in validate_range is useful to apply to src as
well as dst, but page alignment is only a requirement for dst, not src.
So, split the function up so src can use an "unaligned" variant, while
still allowing us to share the majority of the code between the
different cases.

Reported-by: Ryan Roberts <ryan.roberts@arm.com>
Closes: https://lore.kernel.org/linux-mm/8fbb5965-28f7-4e9a-ac04-1406ed8fc2d4@arm.com/T/#t
Signed-off-by: Axel Rasmussen <axelrasmussen@google.com>
---
 fs/userfaultfd.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index bb5c474a0a77..1091cb461747 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -1287,13 +1287,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)
@@ -1309,6 +1307,15 @@ static __always_inline int validate_range(struct mm_struct *mm,
 	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)
 {
@@ -1759,7 +1766,8 @@ static int userfaultfd_copy(struct userfaultfd_ctx *ctx,
 			   sizeof(uffdio_copy)-sizeof(__s64)))
 		goto out;

-	ret = validate_range(ctx->mm, uffdio_copy.src, uffdio_copy.len);
+	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);
--
2.41.0.640.ga95def55d0-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread
* [PATCH mm-unstable fix] mm: userfaultfd: check for start + len overflow in validate_range: fix
@ 2023-07-14 18:29 Axel Rasmussen
  2023-08-10 15:53 ` Ryan Roberts
  0 siblings, 1 reply; 7+ messages in thread
From: Axel Rasmussen @ 2023-07-14 18:29 UTC (permalink / raw)
  To: Alexander Viro, Andrew Morton, Brian Geffon, Christian Brauner,
	David Hildenbrand, Gaosheng Cui, Huang Ying, Hugh Dickins,
	James Houghton, Jiaqi Yan, Jonathan Corbet, Kefeng Wang,
	Liam R. Howlett, Miaohe Lin, Mike Kravetz, Mike Rapoport (IBM),
	Muchun Song, Nadav Amit, Naoya Horiguchi, Peter Xu, Shuah Khan,
	Steven Barrett, Suleiman Souhlal, Suren Baghdasaryan,
	T.J. Alumbaugh, Yu Zhao, ZhangPeng
  Cc: linux-doc, linux-kernel, linux-fsdevel, linux-mm, linux-kselftest,
	Axel Rasmussen, syzbot+42309678e0bc7b32f8e9

This commit removed an extra check for zero-length ranges, and folded it
into the common validate_range() helper used by all UFFD ioctls.

It failed to notice though that UFFDIO_COPY *only* called validate_range
on the dst range, not the src range. So removing this check actually let
us proceed with zero-length source ranges, eventually hitting a BUG
further down in the call stack.

The correct fix seems clear: call validate_range() on the src range too.

Other ioctls are not affected by this, as they only have one range, not
two (src + dst).

Reported-by: syzbot+42309678e0bc7b32f8e9@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=42309678e0bc7b32f8e9
Signed-off-by: Axel Rasmussen <axelrasmussen@google.com>
---
 fs/userfaultfd.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 53a7220c4679..36d233759233 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -1759,6 +1759,9 @@ static int userfaultfd_copy(struct userfaultfd_ctx *ctx,
 			   sizeof(uffdio_copy)-sizeof(__s64)))
 		goto out;
 
+	ret = validate_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;
-- 
2.41.0.255.g8b1d071c50-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-08-11 20:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-10 19:21 [PATCH mm-unstable fix] mm: userfaultfd: check for start + len overflow in validate_range: fix Axel Rasmussen
2023-08-10 19:30 ` Yu Zhao
2023-08-11 20:51 ` Peter Xu
  -- strict thread matches above, loose matches on Subject: below --
2023-07-14 18:29 Axel Rasmussen
2023-08-10 15:53 ` Ryan Roberts
2023-08-10 16:49   ` David Hildenbrand
2023-08-10 19:23     ` Axel Rasmussen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).