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.

signal: Confine POSIX_TIMERS properly

Move the itimer rearming out of the signal code and consolidate all posix
timer related functions in the signal code under one ifdef.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/all/20241001083835.314100569@linutronix.de

+80 -85
+4 -1
include/linux/posix-timers.h
··· 100 100 { 101 101 pct->bases[CPUCLOCK_SCHED].nextevt = runtime; 102 102 } 103 + void posixtimer_rearm_itimer(struct task_struct *p); 104 + void posixtimer_rearm(struct kernel_siginfo *info); 103 105 104 106 /* Init task static initializer */ 105 107 #define INIT_CPU_TIMERBASE(b) { \ ··· 124 122 static inline void posix_cputimers_init(struct posix_cputimers *pct) { } 125 123 static inline void posix_cputimers_group_init(struct posix_cputimers *pct, 126 124 u64 cpu_limit) { } 125 + static inline void posixtimer_rearm_itimer(struct task_struct *p) { } 126 + static inline void posixtimer_rearm(struct kernel_siginfo *info) { } 127 127 #endif 128 128 129 129 #ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK ··· 200 196 201 197 int update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new); 202 198 203 - void posixtimer_rearm(struct kernel_siginfo *info); 204 199 #endif
+42 -81
kernel/signal.c
··· 478 478 } 479 479 EXPORT_SYMBOL(flush_signals); 480 480 481 - #ifdef CONFIG_POSIX_TIMERS 482 - static void __flush_itimer_signals(struct sigpending *pending) 483 - { 484 - sigset_t signal, retain; 485 - struct sigqueue *q, *n; 486 - 487 - signal = pending->signal; 488 - sigemptyset(&retain); 489 - 490 - list_for_each_entry_safe(q, n, &pending->list, list) { 491 - int sig = q->info.si_signo; 492 - 493 - if (likely(q->info.si_code != SI_TIMER)) { 494 - sigaddset(&retain, sig); 495 - } else { 496 - sigdelset(&signal, sig); 497 - list_del_init(&q->list); 498 - __sigqueue_free(q); 499 - } 500 - } 501 - 502 - sigorsets(&pending->signal, &signal, &retain); 503 - } 504 - 505 - void flush_itimer_signals(void) 506 - { 507 - struct task_struct *tsk = current; 508 - unsigned long flags; 509 - 510 - spin_lock_irqsave(&tsk->sighand->siglock, flags); 511 - __flush_itimer_signals(&tsk->pending); 512 - __flush_itimer_signals(&tsk->signal->shared_pending); 513 - spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 514 - } 515 - #endif 516 - 517 481 void ignore_signals(struct task_struct *t) 518 482 { 519 483 int i; ··· 600 636 *type = PIDTYPE_TGID; 601 637 signr = __dequeue_signal(&tsk->signal->shared_pending, 602 638 mask, info, &resched_timer); 603 - #ifdef CONFIG_POSIX_TIMERS 604 - /* 605 - * itimer signal ? 606 - * 607 - * itimers are process shared and we restart periodic 608 - * itimers in the signal delivery path to prevent DoS 609 - * attacks in the high resolution timer case. This is 610 - * compliant with the old way of self-restarting 611 - * itimers, as the SIGALRM is a legacy signal and only 612 - * queued once. Changing the restart behaviour to 613 - * restart the timer in the signal dequeue path is 614 - * reducing the timer noise on heavy loaded !highres 615 - * systems too. 616 - */ 617 - if (unlikely(signr == SIGALRM)) { 618 - struct hrtimer *tmr = &tsk->signal->real_timer; 619 639 620 - if (!hrtimer_is_queued(tmr) && 621 - tsk->signal->it_real_incr != 0) { 622 - hrtimer_forward(tmr, tmr->base->get_time(), 623 - tsk->signal->it_real_incr); 624 - hrtimer_restart(tmr); 625 - } 626 - } 627 - #endif 640 + if (unlikely(signr == SIGALRM)) 641 + posixtimer_rearm_itimer(tsk); 628 642 } 629 643 630 644 recalc_sigpending(); ··· 624 682 */ 625 683 current->jobctl |= JOBCTL_STOP_DEQUEUED; 626 684 } 627 - #ifdef CONFIG_POSIX_TIMERS 628 - if (resched_timer) { 629 - /* 630 - * Release the siglock to ensure proper locking order 631 - * of timer locks outside of siglocks. Note, we leave 632 - * irqs disabled here, since the posix-timers code is 633 - * about to disable them again anyway. 634 - */ 635 - spin_unlock(&tsk->sighand->siglock); 636 - posixtimer_rearm(info); 637 - spin_lock(&tsk->sighand->siglock); 638 685 639 - /* Don't expose the si_sys_private value to userspace */ 640 - info->si_sys_private = 0; 686 + if (IS_ENABLED(CONFIG_POSIX_TIMERS)) { 687 + if (unlikely(resched_timer)) 688 + posixtimer_rearm(info); 641 689 } 642 - #endif 690 + 643 691 return signr; 644 692 } 645 693 EXPORT_SYMBOL_GPL(dequeue_signal); ··· 1854 1922 } 1855 1923 EXPORT_SYMBOL(kill_pid); 1856 1924 1925 + #ifdef CONFIG_POSIX_TIMERS 1857 1926 /* 1858 - * These functions support sending signals using preallocated sigqueue 1859 - * structures. This is needed "because realtime applications cannot 1860 - * afford to lose notifications of asynchronous events, like timer 1861 - * expirations or I/O completions". In the case of POSIX Timers 1862 - * we allocate the sigqueue structure from the timer_create. If this 1863 - * allocation fails we are able to report the failure to the application 1864 - * with an EAGAIN error. 1927 + * These functions handle POSIX timer signals. POSIX timers use 1928 + * preallocated sigqueue structs for sending signals. 1865 1929 */ 1930 + static void __flush_itimer_signals(struct sigpending *pending) 1931 + { 1932 + sigset_t signal, retain; 1933 + struct sigqueue *q, *n; 1934 + 1935 + signal = pending->signal; 1936 + sigemptyset(&retain); 1937 + 1938 + list_for_each_entry_safe(q, n, &pending->list, list) { 1939 + int sig = q->info.si_signo; 1940 + 1941 + if (likely(q->info.si_code != SI_TIMER)) { 1942 + sigaddset(&retain, sig); 1943 + } else { 1944 + sigdelset(&signal, sig); 1945 + list_del_init(&q->list); 1946 + __sigqueue_free(q); 1947 + } 1948 + } 1949 + 1950 + sigorsets(&pending->signal, &signal, &retain); 1951 + } 1952 + 1953 + void flush_itimer_signals(void) 1954 + { 1955 + struct task_struct *tsk = current; 1956 + 1957 + guard(spinlock_irqsave)(&tsk->sighand->siglock); 1958 + __flush_itimer_signals(&tsk->pending); 1959 + __flush_itimer_signals(&tsk->signal->shared_pending); 1960 + } 1961 + 1866 1962 struct sigqueue *sigqueue_alloc(void) 1867 1963 { 1868 1964 return __sigqueue_alloc(-1, current, GFP_KERNEL, 0, SIGQUEUE_PREALLOC); ··· 1987 2027 rcu_read_unlock(); 1988 2028 return ret; 1989 2029 } 2030 + #endif /* CONFIG_POSIX_TIMERS */ 1990 2031 1991 2032 void do_notify_pidfd(struct task_struct *task) 1992 2033 {
+21 -1
kernel/time/itimer.c
··· 151 151 #endif 152 152 153 153 /* 154 - * The timer is automagically restarted, when interval != 0 154 + * Invoked from dequeue_signal() when SIG_ALRM is delivered. 155 + * 156 + * Restart the ITIMER_REAL timer if it is armed as periodic timer. Doing 157 + * this in the signal delivery path instead of self rearming prevents a DoS 158 + * with small increments in the high reolution timer case and reduces timer 159 + * noise in general. 160 + */ 161 + void posixtimer_rearm_itimer(struct task_struct *tsk) 162 + { 163 + struct hrtimer *tmr = &tsk->signal->real_timer; 164 + 165 + if (!hrtimer_is_queued(tmr) && tsk->signal->it_real_incr != 0) { 166 + hrtimer_forward(tmr, tmr->base->get_time(), 167 + tsk->signal->it_real_incr); 168 + hrtimer_restart(tmr); 169 + } 170 + } 171 + 172 + /* 173 + * Interval timers are restarted in the signal delivery path. See 174 + * posixtimer_rearm_itimer(). 155 175 */ 156 176 enum hrtimer_restart it_real_fn(struct hrtimer *timer) 157 177 {
+13 -2
kernel/time/posix-timers.c
··· 251 251 252 252 /* 253 253 * This function is called from the signal delivery code if 254 - * info->si_sys_private is not zero, which indicates that the timer has to 254 + * info::si_sys_private is not zero, which indicates that the timer has to 255 255 * be rearmed. Restart the timer and update info::si_overrun. 256 256 */ 257 257 void posixtimer_rearm(struct kernel_siginfo *info) ··· 259 259 struct k_itimer *timr; 260 260 unsigned long flags; 261 261 262 + /* 263 + * Release siglock to ensure proper locking order versus 264 + * timr::it_lock. Keep interrupts disabled. 265 + */ 266 + spin_unlock(&current->sighand->siglock); 267 + 262 268 timr = lock_timer(info->si_tid, &flags); 263 269 if (!timr) 264 - return; 270 + goto out; 265 271 266 272 if (timr->it_interval && timr->it_requeue_pending == info->si_sys_private) { 267 273 timr->kclock->timer_rearm(timr); ··· 281 275 } 282 276 283 277 unlock_timer(timr, flags); 278 + out: 279 + spin_lock(&current->sighand->siglock); 280 + 281 + /* Don't expose the si_sys_private value to userspace */ 282 + info->si_sys_private = 0; 284 283 } 285 284 286 285 int posix_timer_queue_signal(struct k_itimer *timr)