diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-25 17:54:02 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-25 17:54:02 -1000 |
| commit | ed2bc044a7c8c9759bbe1165b8e487d07dd53b73 (patch) | |
| tree | cd6b916bcfcc9f5dae6b2586a312f31a34d84f78 /kernel/time | |
| parent | 6e723c4f9417663c318d898fa113af211f48a6da (diff) | |
| parent | 6541fbc942f3b63bb8bd44e34eee6223e0abe719 (diff) | |
Merge tag 'timers-urgent-2026-10-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer fixes from Ingo Molnar:
- Clear timer_base::pending_map on CPU hot-unplug, that can
cause temporal timeout processing anomalous on the next
hot-replug (Liang Hao)
- Fix PID refcount leak in the posix-cpu-timers do_cpu_nanosleep()
signal path (Cen Zhang)
- Require (CAP_SYS_TIME) permission to set auxiliary clocks
via aux_clock_set() (Daehyeon Ko)
- Update offsets on sequence counter retry in
ktime_get_update_offsets_now() (Thomas Weißschuh)
* tag 'timers-urgent-2026-10-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
timekeeping: Update offsets on sequence counter retry in ktime_get_update_offsets_now()
timekeeping: Require permission to set auxiliary clocks
posix-cpu-timers: Fix pid refcount leak in do_cpu_nanosleep() signal path
timers: Clear pending_map on CPU hotplug
Diffstat (limited to 'kernel/time')
| -rw-r--r-- | kernel/time/posix-cpu-timers.c | 4 | ||||
| -rw-r--r-- | kernel/time/timekeeping.c | 8 | ||||
| -rw-r--r-- | kernel/time/timer.c | 2 |
3 files changed, 11 insertions, 3 deletions
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index cd75d4bb5b64..2f23d62ad446 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -1687,8 +1687,8 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, */ expires = cpu_timer_getexpires(&timer.it.cpu); error = posix_cpu_timer_set(&timer, 0, &zero_it, &it); - if (!error) { - /* Timer is now unarmed, deletion can not fail. */ + if (error != TIMER_RETRY) { + /* Unarmed or target gone (-ESRCH), deletion can not fail. */ posix_cpu_timer_del(&timer); } else { while (error == TIMER_RETRY) { diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index d54c4d303db6..dcf47f1ffdcf 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -14,6 +14,7 @@ #include <linux/random.h> #include <linux/sched/clock.h> #include <linux/sched/loadavg.h> +#include <linux/security.h> #include <linux/static_key.h> #include <linux/stop_machine.h> #include <linux/syscore_ops.h> @@ -2850,6 +2851,7 @@ ktime_t ktime_get_update_offsets_now(u32 *cwsseq, ktime_t *offs_real, ktime_t *offs_boot, ktime_t *offs_tai) { struct timekeeper *tk = &tk_core.timekeeper; + u32 cwsseq_orig = *cwsseq; unsigned int seq; ktime_t base; u64 nsecs; @@ -2861,7 +2863,7 @@ ktime_t ktime_get_update_offsets_now(u32 *cwsseq, ktime_t *offs_real, nsecs = timekeeping_get_ns(&tk->tkr_mono); base = ktime_add_ns(base, nsecs); - if (*cwsseq != tk->clock_was_set_seq) { + if (cwsseq_orig != tk->clock_was_set_seq) { *cwsseq = tk->clock_was_set_seq; *offs_real = tk->offs_real; *offs_boot = tk->offs_boot; @@ -3217,11 +3219,15 @@ static int aux_clock_set(const clockid_t id, const struct timespec64 *tnew) struct tk_data *aux_tkd = aux_get_tk_data(id); struct timekeeper *aux_tks; ktime_t tnow, nsecs; + int ret; if (!timespec64_valid_settod(tnew)) return -EINVAL; if (!aux_tkd) return -ENODEV; + ret = security_settime64(tnew, NULL); + if (ret) + return ret; aux_tks = &aux_tkd->shadow_timekeeper; diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 42afdcb229d8..a3c4e20a4e36 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -44,6 +44,7 @@ #include <linux/compat.h> #include <linux/random.h> #include <linux/sysctl.h> +#include <linux/bitmap.h> #include <linux/uaccess.h> #include <asm/unistd.h> @@ -2541,6 +2542,7 @@ int timers_dead_cpu(unsigned int cpu) for (i = 0; i < WHEEL_SIZE; i++) migrate_timer_list(new_base, old_base->vectors + i); + bitmap_zero(old_base->pending_map, WHEEL_SIZE); raw_spin_unlock(&old_base->lock); raw_spin_unlock_irq(&new_base->lock); put_cpu_ptr(&timer_bases); |
