Re: [PATCH] Fix do_pages_stat to use compat_uptr_t

From: Andrew Morton
Date: Wed Jun 25 2025 - 16:39:18 EST


On Wed, 25 Jun 2025 17:24:14 +0200 Christoph Berg <myon@xxxxxxxxxx> wrote:

> For arrays with more than 16 entries, the old code would incorrectly
> advance the pages pointer by 16 words instead of 16 compat_uptr_t.
>
> ...
>
> --- a/mm/migrate.c
> +++ b/mm/migrate.c
> @@ -2444,7 +2444,13 @@ static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
> if (copy_to_user(status, chunk_status, chunk_nr * sizeof(*status)))
> break;
>
> - pages += chunk_nr;
> + if (in_compat_syscall()) {
> + compat_uptr_t __user *pages32 = (compat_uptr_t __user *)pages;
> +
> + pages32 += chunk_nr;
> + pages = (const void __user * __user *) pages32;
> + } else
> + pages += chunk_nr;
> status += chunk_nr;
> nr_pages -= chunk_nr;
> }

Seems this has been present since 2010.

I'll update the Subject: as David suggests and I'll add a cc:stable,
thanks. I'll also add a note that David suggested an alternative, so
please let's advance that option.

Also, a coding-style tweak:

--- a/mm/migrate.c~fix-do_pages_stat-to-use-compat_uptr_t-fix
+++ a/mm/migrate.c
@@ -2449,8 +2449,9 @@ static int do_pages_stat(struct mm_struc

pages32 += chunk_nr;
pages = (const void __user * __user *) pages32;
- } else
+ } else {
pages += chunk_nr;
+ }
status += chunk_nr;
nr_pages -= chunk_nr;
}
_