Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ptp: Limit time setting of PTP clocks

Networking drivers implementing PTP clocks and kernel socket code
handling hardware timestamps use the 64-bit signed ktime_t type counting
nanoseconds. When a PTP clock reaches the maximum value in year 2262,
the timestamps returned to applications will overflow into year 1667.
The same thing happens when injecting a large offset with
clock_adjtime(ADJ_SETOFFSET).

The commit 7a8e61f84786 ("timekeeping: Force upper bound for setting
CLOCK_REALTIME") limited the maximum accepted value setting the system
clock to 30 years before the maximum representable value (i.e. year
2232) to avoid the overflow, assuming the system will not run for more
than 30 years.

Enforce the same limit for PTP clocks. Don't allow negative values and
values closer than 30 years to the maximum value. Drivers may implement
an even lower limit if the hardware registers cannot represent the whole
interval between years 1970 and 2262 in the required resolution.

Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <jstultz@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20250828103300.1387025-1-mlichvar@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Miroslav Lichvar and committed by
Jakub Kicinski
5a8c02a6 35dface6

+12 -1
+12 -1
drivers/ptp/ptp_clock.c
··· 100 100 return -EBUSY; 101 101 } 102 102 103 + if (!timespec64_valid_settod(tp)) 104 + return -EINVAL; 105 + 103 106 return ptp->info->settime64(ptp->info, tp); 104 107 } 105 108 ··· 133 130 ops = ptp->info; 134 131 135 132 if (tx->modes & ADJ_SETOFFSET) { 136 - struct timespec64 ts; 133 + struct timespec64 ts, ts2; 137 134 ktime_t kt; 138 135 s64 delta; 139 136 ··· 144 141 ts.tv_nsec *= 1000; 145 142 146 143 if ((unsigned long) ts.tv_nsec >= NSEC_PER_SEC) 144 + return -EINVAL; 145 + 146 + /* Make sure the offset is valid */ 147 + err = ptp_clock_gettime(pc, &ts2); 148 + if (err) 149 + return err; 150 + ts2 = timespec64_add(ts2, ts); 151 + if (!timespec64_valid_settod(&ts2)) 147 152 return -EINVAL; 148 153 149 154 kt = timespec64_to_ktime(ts);