Describe the bug
Same root cause as #2563: on 32-bit platforms where unsigned long is 32 bits (e.g. armv5tel/ILP32), Swap's /proc/meminfo fallback path parses swap size with strtoul, which silently saturates instead of reporting the real value for large swap sizes.
This is currently dormant rather than live-observed — it only triggers past ~4 TiB of swap, and only when the fallback path is actually used (see below) — but it's the identical defect class, found while auditing the codebase after #2563.
Where
src/detection/swap/swap_linux.c, detectByProcMeminfo():
uint64_t swapTotal = 0, swapFree = 0;
char* token = nullptr;
if ((token = strstr(buf, "SwapTotal:")) != nullptr) {
swapTotal = strtoul(token + strlen("SwapTotal:"), nullptr, 10);
}
if ((token = strstr(buf, "SwapFree:")) != nullptr) {
swapFree = strtoul(token + strlen("SwapFree:"), nullptr, 10);
}
FFSwapResult* swap = FF_LIST_ADD(FFSwapResult, *result);
ffStrbufInitStatic(&swap->name, "Total");
swap->bytesTotal = swapTotal * 1024lu;
swap->bytesUsed = (swapTotal - swapFree) * 1024lu;
SwapTotal/SwapFree in /proc/meminfo are reported in kB. strtoul returns unsigned long, 32 bits wide on ILP32 platforms — max 4294967295. A swap size in kB that exceeds that (i.e. swap larger than ~4 TiB) overflows and strtoul saturates at ULONG_MAX per C99 7.24.1.4, silently producing a wrong bytesTotal/bytesUsed instead of the real size — exactly the same failure mode as the PhysicalDisk bug in #2563, just parsing /proc/meminfo instead of /sys/block/*/size.
Per the comment above this function (// For Android, // Ref: #620), this path is a fallback used only when /proc/swaps can't be read (e.g. some Android/Termux environments) — ffDetectSwap() tries detectByProcSwaps() (which correctly uses sscanf(..., "%" SCNu64 "%" SCNu64, ...) straight into uint64_t, no overflow risk) first. So on a typical Linux desktop/server this code path never runs. It's still worth fixing for correctness/consistency and because the exact set of environments that hit this fallback (and their swap configurations) isn't something this report can rule out.
Suggested fix
Same fix as #2563 — use a 64-bit-safe parse:
swapTotal = strtoull(token + strlen("SwapTotal:"), nullptr, 10);
...
swapFree = strtoull(token + strlen("SwapFree:"), nullptr, 10);
(src/detection/memory/memory_linux.c's equivalent /proc/meminfo parsing already does this correctly with strtoull — this file is the outlier.)
Related
Found while auditing the codebase for the same overflow class after filing #2563 (PhysicalDisk size wrong on 32-bit hosts for disks >2 TiB). Everything else checked (memory_linux.c, disk_linux.c's statvfs64-based mount sizing, and all other strtoul call sites, which are for PCI IDs/PIDs/CPU part numbers/colors — inherently small values) was confirmed 64-bit-safe.
Describe the bug
Same root cause as #2563: on 32-bit platforms where
unsigned longis 32 bits (e.g.armv5tel/ILP32),Swap's/proc/meminfofallback path parses swap size withstrtoul, which silently saturates instead of reporting the real value for large swap sizes.This is currently dormant rather than live-observed — it only triggers past ~4 TiB of swap, and only when the fallback path is actually used (see below) — but it's the identical defect class, found while auditing the codebase after #2563.
Where
src/detection/swap/swap_linux.c,detectByProcMeminfo():SwapTotal/SwapFreein/proc/meminfoare reported in kB.strtoulreturnsunsigned long, 32 bits wide on ILP32 platforms — max4294967295. A swap size in kB that exceeds that (i.e. swap larger than ~4 TiB) overflows andstrtoulsaturates atULONG_MAXper C99 7.24.1.4, silently producing a wrongbytesTotal/bytesUsedinstead of the real size — exactly the same failure mode as thePhysicalDiskbug in #2563, just parsing/proc/meminfoinstead of/sys/block/*/size.Per the comment above this function (
// For Android,// Ref: #620), this path is a fallback used only when/proc/swapscan't be read (e.g. some Android/Termux environments) —ffDetectSwap()triesdetectByProcSwaps()(which correctly usessscanf(..., "%" SCNu64 "%" SCNu64, ...)straight intouint64_t, no overflow risk) first. So on a typical Linux desktop/server this code path never runs. It's still worth fixing for correctness/consistency and because the exact set of environments that hit this fallback (and their swap configurations) isn't something this report can rule out.Suggested fix
Same fix as #2563 — use a 64-bit-safe parse:
(
src/detection/memory/memory_linux.c's equivalent/proc/meminfoparsing already does this correctly withstrtoull— this file is the outlier.)Related
Found while auditing the codebase for the same overflow class after filing #2563 (
PhysicalDisksize wrong on 32-bit hosts for disks >2 TiB). Everything else checked (memory_linux.c,disk_linux.c'sstatvfs64-based mount sizing, and all otherstrtoulcall sites, which are for PCI IDs/PIDs/CPU part numbers/colors — inherently small values) was confirmed 64-bit-safe.