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.

posix-timers: Embed sigqueue in struct k_itimer

To cure the SIG_IGN handling for posix interval timers, the preallocated
sigqueue needs to be embedded into struct k_itimer to prevent life time
races of all sorts.

Now that the prerequisites are in place, embed the sigqueue into struct
k_itimer and fixup the relevant usage sites.

Aside of preparing for proper SIG_IGN handling, this spares an extra
allocation.

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/20241105064213.719695194@linutronix.de

+87 -47
+2 -2
fs/proc/base.c
··· 2553 2553 2554 2554 seq_printf(m, "ID: %d\n", timer->it_id); 2555 2555 seq_printf(m, "signal: %d/%px\n", 2556 - timer->sigq->info.si_signo, 2557 - timer->sigq->info.si_value.sival_ptr); 2556 + timer->sigq.info.si_signo, 2557 + timer->sigq.info.si_value.sival_ptr); 2558 2558 seq_printf(m, "notify: %s/%s.%d\n", 2559 2559 nstr[notify & ~SIGEV_THREAD_ID], 2560 2560 (notify & SIGEV_THREAD_ID) ? "tid" : "pid",
+21 -2
include/linux/posix-timers.h
··· 39 39 40 40 #ifdef CONFIG_POSIX_TIMERS 41 41 42 + #include <linux/signal_types.h> 43 + 42 44 /** 43 45 * cpu_timer - Posix CPU timer representation for k_itimer 44 46 * @node: timerqueue node to queue in the task/sig ··· 168 166 * @it_pid: The pid of the process/task targeted by the signal 169 167 * @it_process: The task to wakeup on clock_nanosleep (CPU timers) 170 168 * @rcuref: Reference count for life time management 171 - * @sigq: Pointer to preallocated sigqueue 169 + * @sigq: Embedded sigqueue 172 170 * @it: Union representing the various posix timer type 173 171 * internals. 174 172 * @rcu: RCU head for freeing the timer. ··· 192 190 struct pid *it_pid; 193 191 struct task_struct *it_process; 194 192 }; 195 - struct sigqueue *sigq; 193 + struct sigqueue sigq; 196 194 rcuref_t rcuref; 197 195 union { 198 196 struct { ··· 220 218 if (rcuref_put(&tmr->rcuref)) 221 219 posixtimer_free_timer(tmr); 222 220 } 221 + 222 + static inline void posixtimer_sigqueue_getref(struct sigqueue *q) 223 + { 224 + struct k_itimer *tmr = container_of(q, struct k_itimer, sigq); 225 + 226 + WARN_ON_ONCE(!rcuref_get(&tmr->rcuref)); 227 + } 228 + 229 + static inline void posixtimer_sigqueue_putref(struct sigqueue *q) 230 + { 231 + struct k_itimer *tmr = container_of(q, struct k_itimer, sigq); 232 + 233 + posixtimer_putref(tmr); 234 + } 235 + #else /* CONFIG_POSIX_TIMERS */ 236 + static inline void posixtimer_sigqueue_getref(struct sigqueue *q) { } 237 + static inline void posixtimer_sigqueue_putref(struct sigqueue *q) { } 223 238 #endif /* !CONFIG_POSIX_TIMERS */ 224 239 225 240 #endif
+12 -7
kernel/signal.c
··· 460 460 461 461 static void __sigqueue_free(struct sigqueue *q) 462 462 { 463 - if (q->flags & SIGQUEUE_PREALLOC) 463 + if (q->flags & SIGQUEUE_PREALLOC) { 464 + posixtimer_sigqueue_putref(q); 464 465 return; 466 + } 465 467 if (q->ucounts) { 466 468 dec_rlimit_put_ucounts(q->ucounts, UCOUNT_RLIMIT_SIGPENDING); 467 469 q->ucounts = NULL; ··· 571 569 copy_siginfo(info, &first->info); 572 570 573 571 /* 574 - * posix-timer signals are preallocated and freed when the 575 - * timer goes away. Either directly or by clearing 576 - * SIGQUEUE_PREALLOC so that the next delivery will free 577 - * them. Spare the extra round through __sigqueue_free() 578 - * which is ignoring preallocated signals. 572 + * posix-timer signals are preallocated and freed when the last 573 + * reference count is dropped in posixtimer_deliver_signal() or 574 + * immediately on timer deletion when the signal is not pending. 575 + * Spare the extra round through __sigqueue_free() which is 576 + * ignoring preallocated signals. 579 577 */ 580 578 if (unlikely((first->flags & SIGQUEUE_PREALLOC) && (info->si_code == SI_TIMER))) 581 579 *timer_sigq = first; ··· 1991 1989 1992 1990 int posixtimer_send_sigqueue(struct k_itimer *tmr) 1993 1991 { 1994 - struct sigqueue *q = tmr->sigq; 1992 + struct sigqueue *q = &tmr->sigq; 1995 1993 int sig = q->info.si_signo; 1996 1994 struct task_struct *t; 1997 1995 unsigned long flags; ··· 2022 2020 2023 2021 ret = 0; 2024 2022 if (unlikely(!list_empty(&q->list))) { 2023 + /* This holds a reference count already */ 2025 2024 result = TRACE_SIGNAL_ALREADY_PENDING; 2026 2025 goto out; 2027 2026 } 2027 + 2028 + posixtimer_sigqueue_getref(q); 2028 2029 posixtimer_queue_sigqueue(q, t, tmr->it_pid_type); 2029 2030 result = TRACE_SIGNAL_DELIVERED; 2030 2031 out:
+52 -36
kernel/time/posix-timers.c
··· 250 250 hrtimer_restart(timer); 251 251 } 252 252 253 + static bool __posixtimer_deliver_signal(struct kernel_siginfo *info, struct k_itimer *timr) 254 + { 255 + guard(spinlock)(&timr->it_lock); 256 + 257 + /* 258 + * Check if the timer is still alive or whether it got modified 259 + * since the signal was queued. In either case, don't rearm and 260 + * drop the signal. 261 + */ 262 + if (timr->it_signal_seq != info->si_sys_private || WARN_ON_ONCE(!timr->it_signal)) 263 + return false; 264 + 265 + if (!timr->it_interval || WARN_ON_ONCE(timr->it_status != POSIX_TIMER_REQUEUE_PENDING)) 266 + return true; 267 + 268 + timr->kclock->timer_rearm(timr); 269 + timr->it_status = POSIX_TIMER_ARMED; 270 + timr->it_overrun_last = timr->it_overrun; 271 + timr->it_overrun = -1LL; 272 + ++timr->it_signal_seq; 273 + info->si_overrun = timer_overrun_to_int(timr); 274 + return true; 275 + } 276 + 253 277 /* 254 278 * This function is called from the signal delivery code. It decides 255 - * whether the signal should be dropped and rearms interval timers. 279 + * whether the signal should be dropped and rearms interval timers. The 280 + * timer can be unconditionally accessed as there is a reference held on 281 + * it. 256 282 */ 257 283 bool posixtimer_deliver_signal(struct kernel_siginfo *info, struct sigqueue *timer_sigq) 258 284 { 259 - struct k_itimer *timr; 260 - unsigned long flags; 261 - bool ret = false; 285 + struct k_itimer *timr = container_of(timer_sigq, struct k_itimer, sigq); 286 + bool ret; 262 287 263 288 /* 264 289 * Release siglock to ensure proper locking order versus ··· 291 266 */ 292 267 spin_unlock(&current->sighand->siglock); 293 268 294 - timr = lock_timer(info->si_tid, &flags); 295 - if (!timr) 296 - goto out; 269 + ret = __posixtimer_deliver_signal(info, timr); 297 270 298 - if (timr->it_signal_seq != info->si_sys_private) 299 - goto out_unlock; 271 + /* Drop the reference which was acquired when the signal was queued */ 272 + posixtimer_putref(timr); 300 273 301 - if (timr->it_interval && !WARN_ON_ONCE(timr->it_status != POSIX_TIMER_REQUEUE_PENDING)) { 302 - timr->kclock->timer_rearm(timr); 303 - 304 - timr->it_status = POSIX_TIMER_ARMED; 305 - timr->it_overrun_last = timr->it_overrun; 306 - timr->it_overrun = -1LL; 307 - ++timr->it_signal_seq; 308 - 309 - info->si_overrun = timer_overrun_to_int(timr); 310 - } 311 - ret = true; 312 - 313 - out_unlock: 314 - unlock_timer(timr, flags); 315 - out: 316 274 spin_lock(&current->sighand->siglock); 317 275 318 276 /* Don't expose the si_sys_private value to userspace */ ··· 412 404 } 413 405 } 414 406 415 - static struct k_itimer * alloc_posix_timer(void) 407 + static struct k_itimer *alloc_posix_timer(void) 416 408 { 417 409 struct k_itimer *tmr = kmem_cache_zalloc(posix_timers_cache, GFP_KERNEL); 418 410 419 411 if (!tmr) 420 412 return tmr; 421 - if (unlikely(!(tmr->sigq = sigqueue_alloc()))) { 413 + 414 + if (unlikely(!posixtimer_init_sigqueue(&tmr->sigq))) { 422 415 kmem_cache_free(posix_timers_cache, tmr); 423 416 return NULL; 424 417 } 425 - clear_siginfo(&tmr->sigq->info); 426 418 rcuref_init(&tmr->rcuref, 1); 427 419 return tmr; 428 420 } ··· 430 422 void posixtimer_free_timer(struct k_itimer *tmr) 431 423 { 432 424 put_pid(tmr->it_pid); 433 - sigqueue_free(tmr->sigq); 425 + if (tmr->sigq.ucounts) 426 + dec_rlimit_put_ucounts(tmr->sigq.ucounts, UCOUNT_RLIMIT_SIGPENDING); 434 427 kfree_rcu(tmr, rcu); 435 428 } 436 429 ··· 493 484 goto out; 494 485 } 495 486 new_timer->it_sigev_notify = event->sigev_notify; 496 - new_timer->sigq->info.si_signo = event->sigev_signo; 497 - new_timer->sigq->info.si_value = event->sigev_value; 487 + new_timer->sigq.info.si_signo = event->sigev_signo; 488 + new_timer->sigq.info.si_value = event->sigev_value; 498 489 } else { 499 490 new_timer->it_sigev_notify = SIGEV_SIGNAL; 500 - new_timer->sigq->info.si_signo = SIGALRM; 501 - memset(&new_timer->sigq->info.si_value, 0, sizeof(sigval_t)); 502 - new_timer->sigq->info.si_value.sival_int = new_timer->it_id; 491 + new_timer->sigq.info.si_signo = SIGALRM; 492 + memset(&new_timer->sigq.info.si_value, 0, sizeof(sigval_t)); 493 + new_timer->sigq.info.si_value.sival_int = new_timer->it_id; 503 494 new_timer->it_pid = get_pid(task_tgid(current)); 504 495 } 505 496 ··· 508 499 else 509 500 new_timer->it_pid_type = PIDTYPE_TGID; 510 501 511 - new_timer->sigq->info.si_tid = new_timer->it_id; 512 - new_timer->sigq->info.si_code = SI_TIMER; 502 + new_timer->sigq.info.si_tid = new_timer->it_id; 503 + new_timer->sigq.info.si_code = SI_TIMER; 513 504 514 505 if (copy_to_user(created_timer_id, &new_timer_id, sizeof (new_timer_id))) { 515 506 error = -EFAULT; ··· 593 584 * 1) Set timr::it_signal to NULL with timr::it_lock held 594 585 * 2) Release timr::it_lock 595 586 * 3) Remove from the hash under hash_lock 596 - * 4) Call RCU for removal after the grace period 587 + * 4) Put the reference count. 588 + * 589 + * The reference count might not drop to zero if timr::sigq is 590 + * queued. In that case the signal delivery or flush will put the 591 + * last reference count. 592 + * 593 + * When the reference count reaches zero, the timer is scheduled 594 + * for RCU removal after the grace period. 597 595 * 598 596 * Holding rcu_read_lock() accross the lookup ensures that 599 597 * the timer cannot be freed.