Re: Bertrand Drouvot
> Yes, I think compat_uptr_t usage is missing in do_pages_stat() (while it's 
> used
> in do_pages_move()).

I was also reading the kernel source around that place but you spotted
the problem before me. This patch resolves the issue here:

diff --git a/mm/migrate.c b/mm/migrate.c
index 8cf0f9c9599..542c81ec3ed 100644
--- 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;
        }


> Having a chunk size <= DO_PAGES_STAT_CHUNK_NR ensures we are not affected
> by the wrong pointer arithmetic.

Good idea. Buggy kernels will be around for some time.

> +               #define NUMA_QUERY_CHUNK_SIZE 16  /* has to be <= 
> DO_PAGES_STAT_CHUNK_NR (do_pages_stat())*/
> +
> +               for (uint64 chunk_start = 0; chunk_start < 
> shm_ent_page_count; chunk_start += NUMA_QUERY_CHUNK_SIZE) {

Perhaps optimize it to this:

#if sizeof(void *) == 4
#define NUMA_QUERY_CHUNK_SIZE 16  /* has to be <= DO_PAGES_STAT_CHUNK_NR 
(do_pages_stat())*/
#else
#define NUMA_QUERY_CHUNK_SIZE 1024
#endif

... or some other bigger number.

The loop could also include CHECK_FOR_INTERRUPTS();

> > I don't have much
> > experience with the kernel code, so don't want to rely too much on my
> > interpretation of it.
> 
> I don't have that much experience too but I think the issue is in 
> do_pages_stat()
> and that "pages += chunk_nr" should be advanced by sizeof(compat_uptr_t) 
> instead.

Me neither, but I'll try submit this fix.

Christoph


Reply via email to