git: 0e8f351be793 - main - timerfd: Use saturating sbintime conversions
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 20 Mar 2026 07:16:16 UTC
The branch main has been updated by jfree:
URL: https://cgit.FreeBSD.org/src/commit/?id=0e8f351be7935729bf67dc1b7aa4d178cf154931
commit 0e8f351be7935729bf67dc1b7aa4d178cf154931
Author: Jake Freeland <jfree@FreeBSD.org>
AuthorDate: 2026-03-20 06:33:38 +0000
Commit: Jake Freeland <jfree@FreeBSD.org>
CommitDate: 2026-03-20 07:15:08 +0000
timerfd: Use saturating sbintime conversions
Some timerfd consumers set expirations with timespec tv_sec components
larger than 2^31 - 1. In such cases, converting that timespec to
sbintime results in data loss or sign flip, yielding a shorter
expiration than desired.
To avoid this problem, use saturating timespec-to-sbintime conversion
functions. These will clamp the converted sbintime to SBT_MAX under
circumstances where the normal conversion functions would overflow.
Saturating conversions still result in data loss, but the consequences
are less severe, causing problems only after SBT_MAX (~68 years) of
system uptime elapses.
Reviewed by: imp
Differential Revision: https://reviews.freebsd.org/D55792
MFC after: 2 weeks
---
sys/kern/sys_timerfd.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/sys/kern/sys_timerfd.c b/sys/kern/sys_timerfd.c
index 236dfe8bb96a..f2a66e21cd63 100644
--- a/sys/kern/sys_timerfd.c
+++ b/sys/kern/sys_timerfd.c
@@ -165,7 +165,7 @@ timerfd_jumped(void)
&diff, &tfd->tfd_time.it_value);
if (callout_stop(&tfd->tfd_callout) == 1) {
callout_schedule_sbt(&tfd->tfd_callout,
- tstosbt(tfd->tfd_time.it_value),
+ tstosbt_sat(tfd->tfd_time.it_value),
0, C_ABSOLUTE);
}
}
@@ -398,10 +398,10 @@ timerfd_expire(void *arg)
++tfd->tfd_count;
tfd->tfd_expired = true;
if (timespecisset(&tfd->tfd_time.it_interval)) {
- exp = tstosbt(tfd->tfd_time.it_value);
- interval = tstosbt(tfd->tfd_time.it_interval);
+ exp = tstosbt_sat(tfd->tfd_time.it_value);
+ interval = tstosbt_sat(tfd->tfd_time.it_interval);
now = sbinuptime();
- next = now + interval;
+ next = now > SBT_MAX - interval ? SBT_MAX : now + interval;
/* Count missed events. */
if (now > exp) {
@@ -553,7 +553,7 @@ kern_timerfd_settime(struct thread *td, int fd, int flags,
&tfd->tfd_time.it_value);
}
callout_reset_sbt(&tfd->tfd_callout,
- tstosbt(tfd->tfd_time.it_value),
+ tstosbt_sat(tfd->tfd_time.it_value),
0, timerfd_expire, tfd, C_ABSOLUTE);
} else {
callout_stop(&tfd->tfd_callout);