[Bug 297401] devel/tevent: fix poll(2) EINVAL busy-loop on far-future timers

[email protected] Sun, 09 Aug 2026 16:48:30 +0000
Newsgroups gmane.os.freebsd.devel.ports.bugs
Message-ID <[email protected]/bugzilla/>
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=297401

            Bug ID: 297401
           Summary: devel/tevent: fix poll(2) EINVAL busy-loop on
                    far-future timers
           Product: Ports & Packages
           Version: Latest
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: Individual Port(s)
          Assignee: [email protected]
          Reporter: [email protected]
             Flags: maintainer-feedback?([email protected])
          Assignee: [email protected]

Created attachment 273578
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=273578&action=edit
patch

tevent_poll.c: poll_event_loop_poll() computes the poll(2) timeout in
milliseconds as

    timeout = tvalp->tv_sec * 1000;
    timeout += (tvalp->tv_usec + 999) / 1000;

tv_sec is a time_t (64-bit), but the result is stored in the int
"timeout". When a consumer arms a tevent timer far in the future,
tv_sec * 1000 exceeds INT_MAX and the assignment truncates to a negative
int.

poll(2) accepts only -1 (INFTIM) as a valid negative timeout; any other
negative value returns EINVAL. tevent does not back off, so the event
loop spins at 100% CPU, never sleeping:

    gettimeofday(...); poll(..., -1414506808) = -1 EINVAL;
    gettimeofday(...); poll(..., -1414506808) = -1 EINVAL; ...

Reproduced on 16.0-CURRENT (amd64) with net/freeipa-server's certmonger:
it arms a single tevent timer at a certificate's renewal time, ~33 days
out. tv_sec ~= 2880460 -> tv_sec * 1000 = 2880460488 ms, which as a
signed 32-bit int is -1414506808 -- exactly the value seen in a truss(1)
of the runaway certmonger process:

    poll({ 4/POLLIN|POLLHUP ... },18,-1414506808) ERR#22 'Invalid argument'

Fix: clamp the millisecond timeout to INT_MAX (~24.8 days) before it can
overflow. A timer that far out just wakes the loop early; tevent then
recomputes the delay and sleeps again -- harmless.

Patch bumps PORTREVISION and adds files/patch-tevent__poll.c.

Tested with:
    poudriere testport -j 16amd64 -p ports devel/tevent
Also verified the patched tevent_poll.c compiles clean under -Werror and
links into libtevent.so.

-- 
You are receiving this mail because:
You are the assignee for the bug.