All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bradley Morgan <brads@mainlining.org>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Bradley Morgan <brads@mainlining.org>,
	Arnd Bergmann <arnd@arndb.de>,
	linux-kernel@vger.kernel.org
Subject: [PATCH 3/3] compat: make compat_sysinfo() scale far enough to actually fit
Date: Thu,  5 Nov 2026 00:31:29 +0000	[thread overview]
Message-ID: <20261105003129.3130709-4-brads@mainlining.org> (raw)
In-Reply-To: <20261105003129.3130709-1-brads@mainlining.org>

compat_sysinfo() checks whether totalram or totalswap is too big for the
compat struct and scales the values down to fit, but the loop stops as
soon as s.mem_unit reaches PAGE_SIZE.  That caps the compression at one
page, 12 bits with 4K pages.  On a 64 bit kernel do_sysinfo() always
hands it values in bytes with mem_unit == 1, its own overflow math runs
on unsigned long so it does not bail until 16 EiB, so the loop runs its
12 turns, the values come back out as a page count, and anything past
2^32 pages still does not fit.  Storing that into the u32 field then
just drops the top bits.

So a 32 bit process on a box past 2^32 pages gets a wrapped number
instead of a coarse one, with 4K pages that starts at 16 TiB:

  ram      old                  new
  8 TiB    2147483648 x 4096    unchanged
  16 TiB   0 x 4096             2147483648 x 8192
  17 TiB   268435456 x 4096     2281701376 x 8192
  32 TiB   0 x 4096             2147483648 x 16384

The 17 TiB row is the nasty one, a 32 bit process is told the box has
1 TiB of ram.  Keep scaling until the values fit instead of until the
unit reaches a page, the unit then says how coarse the number is, which
is what mem_unit is for.

Nothing that works today changes.  I ran both loops side by side over
ram from 1 MiB to 2^56 with 4K and 64K pages, they disagree on exactly
the inputs where the old one dropped bits and agree on every one it got
right.

Signed-off-by: Bradley Morgan <brads@mainlining.org>
---
 kernel/sys.c | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/kernel/sys.c b/kernel/sys.c
index c4839c986f5e0..8f683b6bb87b8 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -3035,24 +3035,22 @@ COMPAT_SYSCALL_DEFINE1(sysinfo, struct compat_sysinfo __user *, info)
 	do_sysinfo(&s);
 
 	/* Check to see if any memory value is too large for 32-bit and scale
-	 *  down if needed
+	 * down if needed.  Keep going until the values fit, not just until the
+	 * unit reaches a page.  The values halve each turn, so this ends.
 	 */
 	if (upper_32_bits(s.totalram) || upper_32_bits(s.totalswap)) {
-		int bitcount = 0;
-
-		while (s.mem_unit < PAGE_SIZE) {
+		while (s.mem_unit < PAGE_SIZE || upper_32_bits(s.totalram) ||
+		       upper_32_bits(s.totalswap)) {
 			s.mem_unit <<= 1;
-			bitcount++;
+			s.totalram >>= 1;
+			s.freeram >>= 1;
+			s.sharedram >>= 1;
+			s.bufferram >>= 1;
+			s.totalswap >>= 1;
+			s.freeswap >>= 1;
+			s.totalhigh >>= 1;
+			s.freehigh >>= 1;
 		}
-
-		s.totalram >>= bitcount;
-		s.freeram >>= bitcount;
-		s.sharedram >>= bitcount;
-		s.bufferram >>= bitcount;
-		s.totalswap >>= bitcount;
-		s.freeswap >>= bitcount;
-		s.totalhigh >>= bitcount;
-		s.freehigh >>= bitcount;
 	}
 
 	memset(&s_32, 0, sizeof(s_32));
-- 
2.53.0

  parent reply	other threads:[~2026-11-05  0:31 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-05  0:31 [PATCH 0/3] two small fixes out of kernel/sys.c Bradley Morgan
2026-11-05  0:31 ` [PATCH 1/3] tools: pass the unused prctl() args explicitly for PR_FUTEX_HASH Bradley Morgan
2026-11-05  0:35   ` sashiko-bot
2026-11-05  0:31 ` [PATCH 2/3] futex: reject the unused PR_FUTEX_HASH arguments Bradley Morgan
2026-11-09 21:32   ` André Almeida
2026-11-05  0:31 ` Bradley Morgan [this message]
2026-11-05  7:25   ` [PATCH 3/3] compat: make compat_sysinfo() scale far enough to actually fit Arnd Bergmann
2026-11-05 16:47     ` Bradley Morgan
2026-11-05 16:52       ` Arnd Bergmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261105003129.3130709-4-brads@mainlining.org \
    --to=brads@mainlining.org \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.