>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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.