NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/60602: tmpfs size calculation overflows on 32-bit ports when memory plus swap exceeds 4GB
>Number: 60602
>Category: kern
>Synopsis: tmpfs size calculation overflows on 32-bit ports when memory plus swap exceeds 4GB
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Aug 16 06:45:01 +0000 2026
>Originator: Hashimoto Kenichi
>Release: NetBSD 10.1
>Organization:
genetec corporation
>Environment:
System: NetBSD 10.1 (GENERIC) i386, 2.9GB RAM, 32GB swap (QEMU/NVMM guest)
>Description:
In tmpfs_bytes_max() (sys/fs/tmpfs/tmpfs_mem.c rev 1.8):
psize_t freepages = tmpfs_mem_info(false);
uint64_t avail_mem;
...
avail_mem = round_page(mp->tm_bytes_used) + (freepages << PAGE_SHIFT);
The shift is evaluated in the width of psize_t before the addition.
On i386 without PAE, psize_t is unsigned long, i.e. 32 bits.
tmpfs_mem_info() returns a page count covering main memory and swap,
so once it exceeds 2^20 pages the result wraps modulo 2^32.
Two measurements, df(1) and vmstat(1) run from a single command line:
07:23:16 14:29:34 delta
pages free 24,233 193,815 +169,582
cached file pages 281,540 157,941 -123,599
swap pages in use 512,841 515,106 +2,265
(swap pages 8,421,126, wired 2,827, freetarg 5,461: unchanged)
------------------------------------------------------------
sum 8,205,770 8,249,488 +43,718
df -k /tmp Size 4,186,968 148,488 -4,038,480
The input grew by 43,718 pages while the reported size fell by 4GB.
tmpfs_bytes_max() is monotonic in freepages, so this requires
truncation. The delta matches one crossing of a 2^32 boundary to
within the error of reading swpgavail/swpgonly from vmstat.
This mount has no -s option (size_max=18446744073709551615), so MIN()
always selects the overflowed term. A -sram%25 mount on the same
system was clamped to the same wrong value.
tmpfs_mem_incr() uses the same function, so this is not only a
reporting problem: build.sh failed with
fatal error: error writing to /tmp//cc5cFXCC.s: No space left on device
while df reported 100M free on an idle /tmp.
An amd64 system running 11.0 reports expected values, consistent with
psize_t being 64 bits there. PAE kernels should be unaffected
(untested). rev 1.7 used size_t, also 32 bits on i386, so this is not
specific to the psize_t change.
>How-To-Repeat:
On a 32-bit port with main memory plus swap exceeding 4GB, mount a
tmpfs without -s and observe over time:
{ date +%T; df -k /tmp; \
vmstat -s | grep -E 'pages free|cached file pages|swap pages'; }
The reported size does not track the page counts monotonically.
512MB RAM with 5GB swap should suffice but is unverified; the data
above is from a system in production use.
>Fix:
Unknown.
Home |
Main Index |
Thread Index |
Old Index