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: Split up __sigqueue_alloc()

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.

Reorganize __sigqueue_alloc() so the ucounts retrieval and the
initialization can be used independently.

No functional change.

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

+35 -17
+35 -17
kernel/signal.c
··· 396 396 task_set_jobctl_pending(task, mask | JOBCTL_STOP_PENDING); 397 397 } 398 398 399 - /* 400 - * allocate a new signal queue record 401 - * - this may be called without locks if and only if t == current, otherwise an 402 - * appropriate lock must be held to stop the target task from exiting 403 - */ 404 - static struct sigqueue * 405 - __sigqueue_alloc(int sig, struct task_struct *t, gfp_t gfp_flags, 406 - int override_rlimit, const unsigned int sigqueue_flags) 399 + static struct ucounts *sig_get_ucounts(struct task_struct *t, int sig, 400 + int override_rlimit) 407 401 { 408 - struct sigqueue *q = NULL; 409 402 struct ucounts *ucounts; 410 403 long sigpending; 411 404 ··· 417 424 if (!sigpending) 418 425 return NULL; 419 426 420 - if (override_rlimit || likely(sigpending <= task_rlimit(t, RLIMIT_SIGPENDING))) { 421 - q = kmem_cache_alloc(sigqueue_cachep, gfp_flags); 422 - } else { 427 + if (unlikely(!override_rlimit && sigpending > task_rlimit(t, RLIMIT_SIGPENDING))) { 428 + dec_rlimit_put_ucounts(ucounts, UCOUNT_RLIMIT_SIGPENDING); 423 429 print_dropped_signal(sig); 430 + return NULL; 424 431 } 425 432 426 - if (unlikely(q == NULL)) { 433 + return ucounts; 434 + } 435 + 436 + static void __sigqueue_init(struct sigqueue *q, struct ucounts *ucounts, 437 + const unsigned int sigqueue_flags) 438 + { 439 + INIT_LIST_HEAD(&q->list); 440 + q->flags = sigqueue_flags; 441 + q->ucounts = ucounts; 442 + } 443 + 444 + /* 445 + * allocate a new signal queue record 446 + * - this may be called without locks if and only if t == current, otherwise an 447 + * appropriate lock must be held to stop the target task from exiting 448 + */ 449 + static struct sigqueue *__sigqueue_alloc(int sig, struct task_struct *t, gfp_t gfp_flags, 450 + int override_rlimit, const unsigned int sigqueue_flags) 451 + { 452 + struct ucounts *ucounts = sig_get_ucounts(t, sig, override_rlimit); 453 + struct sigqueue *q; 454 + 455 + if (!ucounts) 456 + return NULL; 457 + 458 + q = kmem_cache_alloc(sigqueue_cachep, gfp_flags); 459 + if (!q) { 427 460 dec_rlimit_put_ucounts(ucounts, UCOUNT_RLIMIT_SIGPENDING); 428 - } else { 429 - INIT_LIST_HEAD(&q->list); 430 - q->flags = sigqueue_flags; 431 - q->ucounts = ucounts; 461 + return NULL; 432 462 } 463 + 464 + __sigqueue_init(q, ucounts, sigqueue_flags); 433 465 return q; 434 466 } 435 467