drivers/char/ppdev.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
PPSETTIME64 supplies the timeval fields as s64 values, but
pp_set_timeout() narrows tv_usec to int and calculates tv_sec * HZ in a
signed long. Large positive values can therefore be truncated or overflow
and install an unintended timeout.
Keep both fields as s64, reject a non-canonical microsecond value, and
use timespec64_to_jiffies() to cap excessively large timeouts at
MAX_JIFFY_OFFSET. This is a behavior change because both PPSETTIME
ioctls could previously accept values with tv_usec >= USEC_PER_SEC.
The validation follows the precedent set by sock_set_timeout().
Fixes: 3b9ab374a1e6 ("ppdev: convert to y2038 safe")
Signed-off-by: Linmao Li <lilinmao@kylinos.cn>
---
drivers/char/ppdev.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 6da817b9849f..8803268b4cdc 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -340,15 +340,17 @@ static enum ieee1284_phase init_phase(int mode)
return IEEE1284_PH_FWD_IDLE;
}
-static int pp_set_timeout(struct pardevice *pdev, long tv_sec, int tv_usec)
+static int pp_set_timeout(struct pardevice *pdev, s64 tv_sec, s64 tv_usec)
{
+ struct timespec64 ts;
long to_jiffies;
- if ((tv_sec < 0) || (tv_usec < 0))
+ if (tv_sec < 0 || tv_usec < 0 || tv_usec >= USEC_PER_SEC)
return -EINVAL;
- to_jiffies = usecs_to_jiffies(tv_usec);
- to_jiffies += tv_sec * HZ;
+ ts.tv_sec = tv_sec;
+ ts.tv_nsec = tv_usec * NSEC_PER_USEC;
+ to_jiffies = timespec64_to_jiffies(&ts);
if (to_jiffies <= 0)
return -EINVAL;
--
2.25.1
On Thu, Jul 16, 2026, at 03:39, Linmao Li wrote:
> PPSETTIME64 supplies the timeval fields as s64 values, but
> pp_set_timeout() narrows tv_usec to int and calculates tv_sec * HZ in a
> signed long. Large positive values can therefore be truncated or overflow
> and install an unintended timeout.
>
> Keep both fields as s64, reject a non-canonical microsecond value, and
> use timespec64_to_jiffies() to cap excessively large timeouts at
> MAX_JIFFY_OFFSET. This is a behavior change because both PPSETTIME
> ioctls could previously accept values with tv_usec >= USEC_PER_SEC.
> The validation follows the precedent set by sock_set_timeout().
>
> Fixes: 3b9ab374a1e6 ("ppdev: convert to y2038 safe")
> Signed-off-by: Linmao Li <lilinmao@kylinos.cn>
Good catch!
> - to_jiffies = usecs_to_jiffies(tv_usec);
> - to_jiffies += tv_sec * HZ;
> + ts.tv_sec = tv_sec;
> + ts.tv_nsec = tv_usec * NSEC_PER_USEC;
> + to_jiffies = timespec64_to_jiffies(&ts);
> if (to_jiffies <= 0)
> return -EINVAL;
This is a bit more expensive, but it's clearly not performance
critical and I agree that the added range checking is a
nice improvement here.
I also checked codesearch.debian.net to see if any callers
might rely on passing out-of-range arguments, but the only
caller I found (pyparallel) is guaranteed to pass a
normalized timeval.
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
© 2016 - 2026 Red Hat, Inc.