From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1BBDCC7EE30 for ; Tue, 1 Jul 2025 16:58:40 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id A63266B00AD; Tue, 1 Jul 2025 12:58:39 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id A13DE6B00AE; Tue, 1 Jul 2025 12:58:39 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 902556B00B0; Tue, 1 Jul 2025 12:58:39 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 7EAEC6B00AD for ; Tue, 1 Jul 2025 12:58:39 -0400 (EDT) Received: from smtpin15.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id EA8C91605A2 for ; Tue, 1 Jul 2025 16:58:38 +0000 (UTC) X-FDA: 83616304716.15.B0A9EF0 Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [80.241.56.151]) by imf13.hostedemail.com (Postfix) with ESMTP id CF5EF20014 for ; Tue, 1 Jul 2025 16:58:36 +0000 (UTC) Authentication-Results: imf13.hostedemail.com; spf=pass (imf13.hostedemail.com: domain of cb@df7cb.de designates 80.241.56.151 as permitted sender) smtp.mailfrom=cb@df7cb.de ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1751389117; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-transfer-encoding: in-reply-to:in-reply-to:references; bh=o6pO2Nnur/B1EBNhcZAU6gYdlTTd66lRuNkRv2D3zWw=; b=VN0vySAtD/sk6DnaNfG0WyhC0sFeRhvykjw+EA0VTs+xa/85fZLBERy2mI2zoynejjNGW0 LYBwnc4h9r5gXNj8hv0k/bwnOpqRl8BG6YFucNlCR5yiKz+s0A7TifV3onc700PzMZSpUo GD3yRww1h6I+1eT/dyx978sbwiW0UbQ= ARC-Authentication-Results: i=1; imf13.hostedemail.com; dkim=none; spf=pass (imf13.hostedemail.com: domain of cb@df7cb.de designates 80.241.56.151 as permitted sender) smtp.mailfrom=cb@df7cb.de; dmarc=none ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1751389117; a=rsa-sha256; cv=none; b=jLa05xatVMF2PE4X4emc2OIEhplaMm+2eCiPPoEtxVtB3fwchHWsHGODZHHQSYj6kQbJHR YDyAZWDoNDle+sHd1HAnxyOyeWopzexWUOt1PpPwJjxdJt0tJM4GQZYnFGptS7yd8mWE0p cpFhtDXAwF76ZR77zBPEj+Z3mZbvX5o= Received: from smtp2.mailbox.org (smtp2.mailbox.org [IPv6:2001:67c:2050:b231:465::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4bWq3r1njDz9sqc; Tue, 1 Jul 2025 18:58:32 +0200 (CEST) Date: Tue, 1 Jul 2025 18:58:28 +0200 From: Christoph Berg To: David Hildenbrand , Andrew Morton Cc: Zi Yan , Matthew Brost , Joshua Hahn , Rakie Kim , Byungchul Park , Gregory Price , Ying Huang , Alistair Popple , "open list:MEMORY MANAGEMENT - MEMORY POLICY AND MIGRATION" , open list Subject: [PATCH v2] mm/migrate: Fix do_pages_stat in 32-bit mode Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20250625133909.1a054c24d933cd97afd0027d@linux-foundation.org> X-Rspam-User: X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: CF5EF20014 X-Stat-Signature: yre6dwmb4wg17ga3h4h68ykur19ai6wq X-HE-Tag: 1751389116-629400 X-HE-Meta: U2FsdGVkX1+ZTVJRqioJaMUXFTe6edFI/EMKP2RCGmu/gyuUPoWgCdFW4c3ydErze86B3utbqrnpPlXqVGtz8HaJX4cJ8jWDMOBeDvM03k3e5BREC+bq2dK9+r9Q9pVZX68npLAtuR9pWlwbzSe/1K7UPAoslts+PZ6ffxOI50HNSWZ3Yy/FE3t61V2ji/vbeKcQMxa6UBjsx9rHOcXwHGZ43U4dEvJru0mzTKT3TgJYQCFfo1wLLtzkLieMV4weucrEP/Oia0qjP+9bQ4axg+kyE/14czSztqExfUl9xm2hMpWCR8ZOlhVnbM4ry4iq4OFqS3pe9S6/0x5FbEhdTJH3wfy5plLK4NtFf6hWL/Nv+E87TZBjhPx3SK2QO6dVMBfeNqGPCMy6Qn2LX9LVb0U/eYXs7JksEsXfs02SNXX6V8ddPcIrj/FHVcXZ1S6pP5d8WIQwN2esTWB0QDmCvs8BRmwbpm3v3obciSQiUYqGWX67I66EI0b0KF+qi/AvngIS0QWsUyXiko2e3bc5WkSP3pTfn4LFkt6c+9ivXArjVoQG9AhPUzualzDIMjD3fxG1mHnYpAPxPyo+8eSOq+iGo02zemHtYKtVbS99F7nGBV7dN8DBictHu0bN9qFE9xWBMO/Lv0S06SZiybnR508XcU4hRc96ggKdLpArQjaZvmgxZZAe1UwNMwQMZll/ZN2LslWBo61ZBKChOVFAMa+9XSqFr899yDfZgnL2vVc3mao4UwXL5zyLEHbo89ytViaQtn7YLaAIg1LOvjlfqIjQX4wQrx6Vefiy4p1zRtr/pvMsF0IxB0BLnHO0QMKnjQw4Pi0FdXUnm8mggudyQ8ZFnNmow9JGvjGnIs7YOGP26BaWp6odK83FMgXlnvLEoq0eEwXkPUflg35qpIjg8buD1V+/Z7IdFa0HlU/TmwrRWfCjATYLRGr26VB8lQ9otRHvuqpCD6rj4Agjqip 7KwtU0O9 PuWpBsEddFc6kZig2oUCWTQZcX9hVZY5+9onPBoPdZE4DXhfYBPDM3gNhyzLETmIKAG7EAmplLSxJNE0X4MDaDmWOd3djlel6Pl6OUlIG8CuYyftpKCKNXgQnU9Osw9GdRxKCW3uenOmA7+Dn6G0GByINK+v8cPMkHJNwy5sGlMWvu05TcxgGro1VVO658Z5W4AXczmKc6mkBSaim7CcXhPztahdu1CdrVjgbUzH4Aur4CZnB5ZTULP8GcIhtlfp8SnZFOmG8jz0ARHuYvZQ30sTMKSLO+9cWk4wShODSv3gqv8vXVClZ3x7F9VBEvmmeWuFGp+uuCZgq18ospTfbM+4pjDNQOA6UZ/jV3ikGXj4yBMPCt+pQUZku4Q== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Re: David Hildenbrand > Subject should start with "mm/migrate:" > Likely we want a > Fixes: > and then this is probably "Reported-by:" paired with a "Closes:" link > to any such report. I included these now, except for "Closes:" which I have to idea what to put in. > But I'm wondering how long this has already been like that. :) The now-offending "pages += chunk_nr" line is from 2010, but I think the bug is rather from 5b1b561ba73c8ab9c98e5dfd14dc7ee47efb6530 (2021) which reshuffled the array-vs-32-bit handling. > Something a bit more elegant might be: Thanks, I used your patch draft with some minor changes. > static int get_compat_pages_array(const void __user *chunk_pages[], > const void __user * __user *pages, > + unsigned long chunk_offs, I replaced chunk_offs with "chunk_offset" since "offs" looked too much like plural (list of offsets) to me. > if (in_compat_syscall()) { > if (get_compat_pages_array(chunk_pages, pages, > - chunk_nr)) > + chunk_offs, chunk_nr)) > break; > } else { > if (copy_from_user(chunk_pages, pages, The else branch here needs tweaking as well: } else { - if (copy_from_user(chunk_pages, pages, + if (copy_from_user(chunk_pages, pages + chunk_offset, chunk_nr * sizeof(*chunk_pages))) > @@ -2440,11 +2442,11 @@ static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages, > do_pages_stat_array(mm, chunk_nr, chunk_pages, chunk_status); > - if (copy_to_user(status, chunk_status, chunk_nr * sizeof(*status))) > + if (copy_to_user(status + chunk_offs, chunk_status, > + chunk_nr * sizeof(*status))) This seems to work, but honestly I am wondering, if copy_from_user needs a special 32-bit case, doesn't copy_to_user need special casing as well? > (untested, of course) The attached patch makes PG18's new numa test pass on amd64 kernels both in amd64 and i386 userlands. (In the meantime, PG git head got a workaround that limits the chunk size to the same 16 as used in do_pages_stat; I tested with the version before that.) Christoph >From fdbcbc88825bc2e857dfeeebc91d62864e0774dd Mon Sep 17 00:00:00 2001 From: Christoph Berg Date: Tue, 24 Jun 2025 16:44:27 +0200 Subject: [PATCH v2] mm/migrate: Fix do_pages_stat in 32-bit mode 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. Fix by doing the pointer arithmetic inside get_compat_pages_array where pages32 is already a correctly-typed pointer. Discovered while working on PostgreSQL 18's new NUMA introspection code. Signed-off-by: Christoph Berg Reported-by: Bertrand Drouvot Reported-by: Tomas Vondra Suggested-by: David Hildenbrand Fixes: 5b1b561ba73c8ab9c98e5dfd14dc7ee47efb6530 --- mm/migrate.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/mm/migrate.c b/mm/migrate.c index 8cf0f9c9599d..2c88f3b33833 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -2399,6 +2399,7 @@ static void do_pages_stat_array(struct mm_struct *mm, unsigned long nr_pages, static int get_compat_pages_array(const void __user *chunk_pages[], const void __user * __user *pages, + unsigned long chunk_offset, unsigned long chunk_nr) { compat_uptr_t __user *pages32 = (compat_uptr_t __user *)pages; @@ -2406,7 +2407,7 @@ static int get_compat_pages_array(const void __user *chunk_pages[], int i; for (i = 0; i < chunk_nr; i++) { - if (get_user(p, pages32 + i)) + if (get_user(p, pages32 + chunk_offset + i)) return -EFAULT; chunk_pages[i] = compat_ptr(p); } @@ -2425,27 +2426,28 @@ static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages, #define DO_PAGES_STAT_CHUNK_NR 16UL const void __user *chunk_pages[DO_PAGES_STAT_CHUNK_NR]; int chunk_status[DO_PAGES_STAT_CHUNK_NR]; + unsigned long chunk_offset = 0; while (nr_pages) { unsigned long chunk_nr = min(nr_pages, DO_PAGES_STAT_CHUNK_NR); if (in_compat_syscall()) { if (get_compat_pages_array(chunk_pages, pages, - chunk_nr)) + chunk_offset, chunk_nr)) break; } else { - if (copy_from_user(chunk_pages, pages, + if (copy_from_user(chunk_pages, pages + chunk_offset, chunk_nr * sizeof(*chunk_pages))) break; } do_pages_stat_array(mm, chunk_nr, chunk_pages, chunk_status); - if (copy_to_user(status, chunk_status, chunk_nr * sizeof(*status))) + if (copy_to_user(status + chunk_offset, chunk_status, + chunk_nr * sizeof(*status))) break; - pages += chunk_nr; - status += chunk_nr; + chunk_offset += chunk_nr; nr_pages -= chunk_nr; } return nr_pages ? -EFAULT : 0; -- 2.47.2