https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=298891
Bug ID: 298891
Summary: ps(1), top(1), systat(1): Fix floating-point underflow
/ SIGFPE in weighted CPU calculation
Product: Base System
Version: 14.4-RELEASE
Hardware: arm
OS: Any
Status: New
Severity: Affects Some People
Priority: ---
Component: bin
Assignee: [email protected]
Reporter: [email protected]
Created attachment 275162
--> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=275162&action=edit
underflow patch for bin/ps/print.c usr.bin/top/machine.c usr.bin/systat/pigs.c
A critical floating-point underflow bug exists in the weighted CPU percentage
calculation across three core utilities in the base system: bin/ps/print.c,
usr.bin/top/machine.c, and usr.bin/systat/pigs.c.
Problem:
When a process accumulates a very large `ki_swtime` (swap/residence time), the
exponent expression `(ki_swtime * log(ccpu))` or `(ki_swtime * logcpu)` yields
a large negative value.
Due to hardware floating-point boundaries, passing this extreme negative value
directly to exp() causes a floating-point underflow. On specific architectures
(such as ARMv6/ARM), this triggers an unmasked floating-point exception
(SIGFPE), causin
g intermittent core dumps in top(1), ps(1), and potentially systat(1).
Proposed Fixes:
To mitigate this, the exponent value must be clamped to a safe hardware
threshold (-700.0) before evaluating exp(), preventing underflow and subsequent
division issues.
1. In bin/ps/print.c:
Modify the return statement to clamp the intermediate double value:
double d = k->ki_p->ki_swtime * log(fxtofl(ccpu));
if (d < -700.0)
d = -700.0;
return (100.0 * fxtofl(k->ki_p->ki_pctcpu) / (1.0 - exp(d)));
2. In usr.bin/top/machine.c:
Convert the `weighted_cpu` macro into a static inline function (using const
struct kinfo_proc * for type safety) and clamp the exponent:
static inline double
weighted_cpu(double pct, const struct kinfo_proc *pp)
{
if (pp->ki_swtime == 0)
return (0.0);
double d = pp->ki_swtime * logcpu;
if (d < -700.0)
d = -700.0;
return (pct / (1.0 - exp(d)));
}
3. In usr.bin/systat/pigs.c:
Clamp the `ftime * lccpu` value inside the process evaluation loop:
double d = ftime * lccpu;
if (d < -700.0)
d = -700.0;
*pctp = ((double) kpp[i].ki_pctcpu / fscale) / (1.0 - exp(d));
All three patches have been successfully compiled and verified on FreeBSD
14-RELEASE on armv6 target (Raspberry Pi zero 1). The fixes eliminate the
crashes under high ki_swtime conditions.
--
You are receiving this mail because:
You are the assignee for the bug.