Skip to content

Commit 11ddf0e

Browse files
committed
Merge tag 'v5.10.262' into 5.10-main
This is the 5.10.262 stable release # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmprLcQACgkQONu9yGCS # aT7blxAA1rVQZUM9X7FDwyP3IQJnszPPkjg1MykHwLZN5b3GETrYbPKoyxF2ZBXd # R17+dycZzDkYrLv7m0CUI/TgMA5ao0KHVqqF0PcB3lhll4jOmiKIEMQwZv3/Te/3 # pHTxHAN6zbkvqaAHVzsBJampLk9Mq9nUoRufGunTyj9WAeTAibE9NKKYxMQvvVDe # ZysFe4402+sarNhQ2ARnax0OkciJIYffQwJK10tq5fhiJ6Y3knP6gq6WRNxW2FjO # C6h+Wd5MXF5S+N9odduj4NooYMVvfxVFVi1N5d5eczOG3JXlB/dj4agdsF9e3XRF # LLdKVzm8a2ODoI7uD2c31M2I34fKf08yJY/hCuWBhfdyDe7PLszD7YQXIc1eYV+V # gsXFSCnQVagWIrPMWHJp6d+oOOKZuI9J20wiVlhumOfruUtCR3nbVM6e6NGS3S67 # 2Qo4zSEmSH32cKS/rVW1eX0N1MtGSSxADOamTlyrNWXzYsdJofmDoIftud51vNhV # nw93K7XxSxZZUIZzgGl/vxiv1aUOai2aC4BmipTP74/6ObblkWdK4fZUHCXO2cf6 # LAOwHxEI6hAJqoByG8gy3S+rBmeD4zR+DPFto7wDhO5sCJeTv9Nw6wpPP2UKB275 # RJdIS4ma7ECdqa1Ml20c7pXeZ1o+av/6xTU6OmU7KPrYdCzODq8= # =AsDV # -----END PGP SIGNATURE----- # gpg: Signature made Thu Jul 30 12:56:04 2026 CEST # gpg: using RSA key 647F28654894E3BD457199BE38DBBDC86092693E # gpg: Can't check signature: No public key
2 parents 7a6310f + 065a677 commit 11ddf0e

4 files changed

Lines changed: 138 additions & 67 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0
22
VERSION = 5
33
PATCHLEVEL = 10
4-
SUBLEVEL = 261
4+
SUBLEVEL = 262
55
EXTRAVERSION =
66
NAME = Dare mighty things
77

kernel/exit.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,13 @@ static void __exit_signal(struct task_struct *tsk)
200200
* doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals.
201201
*/
202202
flush_sigqueue(&tsk->pending);
203-
tsk->sighand = NULL;
203+
204+
/*
205+
* Ensure that all preceeding state is visible. Pairs with
206+
* the smp_acquire__after_ctrl_dep() in the sighand == NULL
207+
* path of lock_task_sighand().
208+
*/
209+
smp_store_release(&tsk->sighand, NULL);
204210
spin_unlock(&sighand->siglock);
205211

206212
__cleanup_sighand(sighand);

kernel/signal.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,8 +1375,16 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
13751375
rcu_read_lock();
13761376
for (;;) {
13771377
sighand = rcu_dereference(tsk->sighand);
1378-
if (unlikely(sighand == NULL))
1378+
if (unlikely(sighand == NULL)) {
1379+
/*
1380+
* Pairs with the smp_store_release() in
1381+
* __exit_signal(). It ensures that all state
1382+
* modifications to the task preceeding the store are
1383+
* visible to the callers of lock_task_sighand().
1384+
*/
1385+
smp_acquire__after_ctrl_dep();
13791386
break;
1387+
}
13801388

13811389
/*
13821390
* This sighand can be already freed and even reused, but

kernel/time/posix-cpu-timers.c

Lines changed: 121 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,110 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
405405
return 0;
406406
}
407407

408+
/*
409+
* Lookup the task via timer->it.cpu.pid and attempt to lock the task's sighand.
410+
*
411+
* This can race with the reaping of the task:
412+
*
413+
* CPU0 CPU1
414+
*
415+
* // Finds task
416+
* p = pid_task(pid, pid_type); __exit_signal(p)
417+
* lock(p, sighand);
418+
* posix_cpu_timers*_exit();
419+
* sighand = lock_task_sighand(p); unhash_task(p);
420+
* p->sighand = NULL;
421+
* unlock(sighand);
422+
*
423+
* In this case sighand is NULL, which means the task and the associated timer
424+
* queue cannot be longer accessed safely.
425+
*
426+
* __exit_signal() invokes posix_cpu_timers_exit() and if the thread group is
427+
* dead it also invokes posix_cpu_timers_group_exit(). These functions delete
428+
* all pending timers from the related timer queues. The POSIX timers (k_itimer)
429+
* themself are still accessible, but not longer connected to the task.
430+
*
431+
* exec() works slightly differently. The task which exec()'s terminates all
432+
* other threads in the thread group and runs __exit_signal() on them. As the
433+
* thread group is not dead they only clean up the per task timers via
434+
* posix_cpu_timers_exit().
435+
*
436+
* As the TGID on exec() stays the same per process timers stay queued, if they
437+
* are armed. This works without a problem when exec() is done by the thread
438+
* group leader. If a non-leader thread exec()'s this can end up in the
439+
* following scenario:
440+
*
441+
* CPU0 CPU1
442+
* // Returns old leader
443+
* p = pid_task(pid, pid_type); de_thread()
444+
* switch_leader()
445+
* release_task(old leader)
446+
* __exit_signal()
447+
* old_leader->sighand = NULL;
448+
* // Returns NULL
449+
* sighand = lock_task_sighand(p)
450+
*
451+
* That's problematic for several functions:
452+
*
453+
* - posix_cpu_timer_del(): If the timer is still enqueued on the task the
454+
* underlying k_itimer will be freed which results in a UAF in
455+
* run_posix_cpu_timers() or on timerqueue related add/delete operations.
456+
* If the timer is not enqueued, the failure is harmless
457+
*
458+
* - posix_cpu_timer_set(): Independent of the enqueued state that results in a
459+
* transient failure which is user space visible (-ESRCH) for regular posix
460+
* timers. But for the use case in do_cpu_nanosleep() it's the same UAF
461+
* problem just that the timer is allocated on the stack.
462+
*
463+
* - posix_cpu_timer_rearm(): Timer is not enqueued at that point, but this
464+
* silently ignores the rearm request, which is a functional problem as the
465+
* timer wont expire anymore.
466+
*/
467+
static struct task_struct *timer_lock_sighand(struct k_itimer *timer, unsigned long *flags)
468+
{
469+
enum pid_type type = clock_pid_type(timer->it_clock);
470+
struct cpu_timer *ctmr = &timer->it.cpu;
471+
472+
guard(rcu)();
473+
474+
for (;;) {
475+
struct task_struct *t = pid_task(timer->it.cpu.pid, type);
476+
477+
/* Fail if the task cannot be found. */
478+
if (!t)
479+
break;
480+
481+
/* Try to lock the task's sighand */
482+
if (lock_task_sighand(t, flags))
483+
return t;
484+
485+
/*
486+
* The next PID lookup might either fail or return the new
487+
* leader. This is correct for both exit() and exec().
488+
*/
489+
}
490+
491+
/*
492+
* If the timer is still enqueued, warn. There is nothing safe to do
493+
* here as there might be two timers in there which are removed in
494+
* parallel and that will cause more damage than good. This should never
495+
* happen!
496+
*
497+
* Ensure that the stores to the timer and timerqueue are visible:
498+
*
499+
* __exit_signal()
500+
* posix_cpu_timers*_exit()
501+
* write_seqlock(seqlock)
502+
* smp_wmb(); <-------
503+
* __unhash_process() | !pid_task()
504+
* ----> smp_rmb();
505+
* WARN_ON_ONCE(...)
506+
*/
507+
smp_rmb();
508+
WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
509+
return NULL;
510+
}
511+
408512
/*
409513
* Clean up a CPU-clock timer that is about to be destroyed.
410514
* This is called from timer deletion with the timer already locked.
@@ -414,28 +518,13 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
414518
static int posix_cpu_timer_del(struct k_itimer *timer)
415519
{
416520
struct cpu_timer *ctmr = &timer->it.cpu;
417-
struct sighand_struct *sighand;
418521
struct task_struct *p;
419522
unsigned long flags;
420523
int ret = 0;
421524

422-
rcu_read_lock();
423-
p = cpu_timer_task_rcu(timer);
424-
if (!p)
425-
goto out;
525+
p = timer_lock_sighand(timer, &flags);
426526

427-
/*
428-
* Protect against sighand release/switch in exit/exec and process/
429-
* thread timer list entry concurrent read/writes.
430-
*/
431-
sighand = lock_task_sighand(p, &flags);
432-
if (unlikely(sighand == NULL)) {
433-
/*
434-
* This raced with the reaping of the task. The exit cleanup
435-
* should have removed this timer from the timer queue.
436-
*/
437-
WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
438-
} else {
527+
if (likely(p)) {
439528
if (timer->it.cpu.firing)
440529
ret = TIMER_RETRY;
441530
else
@@ -444,8 +533,6 @@ static int posix_cpu_timer_del(struct k_itimer *timer)
444533
unlock_task_sighand(p, &flags);
445534
}
446535

447-
out:
448-
rcu_read_unlock();
449536
if (!ret)
450537
put_pid(ctmr->pid);
451538

@@ -575,42 +662,24 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
575662
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
576663
u64 old_expires, new_expires, old_incr, val;
577664
struct cpu_timer *ctmr = &timer->it.cpu;
578-
struct sighand_struct *sighand;
579665
struct task_struct *p;
580666
unsigned long flags;
581667
int ret = 0;
582668

583-
rcu_read_lock();
584-
p = cpu_timer_task_rcu(timer);
585-
if (!p) {
586-
/*
587-
* If p has just been reaped, we can no
588-
* longer get any information about it at all.
589-
*/
590-
rcu_read_unlock();
669+
p = timer_lock_sighand(timer, &flags);
670+
/*
671+
* If p has just been reaped, we can no longer get any information about
672+
* it at all.
673+
*/
674+
if (!p)
591675
return -ESRCH;
592-
}
593676

594677
/*
595678
* Use the to_ktime conversion because that clamps the maximum
596679
* value to KTIME_MAX and avoid multiplication overflows.
597680
*/
598681
new_expires = ktime_to_ns(timespec64_to_ktime(new->it_value));
599682

600-
/*
601-
* Protect against sighand release/switch in exit/exec and p->cpu_timers
602-
* and p->signal->cpu_timers read/write in arm_timer()
603-
*/
604-
sighand = lock_task_sighand(p, &flags);
605-
/*
606-
* If p has just been reaped, we can no
607-
* longer get any information about it at all.
608-
*/
609-
if (unlikely(sighand == NULL)) {
610-
rcu_read_unlock();
611-
return -ESRCH;
612-
}
613-
614683
/*
615684
* Disarm any old timer after extracting its expiry time.
616685
*/
@@ -659,6 +728,8 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
659728
old->it_value.tv_sec = 0;
660729
}
661730
}
731+
732+
old->it_interval = ns_to_timespec64(old_incr);
662733
}
663734

664735
if (unlikely(ret)) {
@@ -669,7 +740,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
669740
* it as an overrun (thanks to bump_cpu_timer above).
670741
*/
671742
unlock_task_sighand(p, &flags);
672-
goto out;
743+
return ret;
673744
}
674745

675746
if (new_expires != 0 && !(timer_flags & TIMER_ABSTIME)) {
@@ -686,7 +757,6 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
686757
arm_timer(timer, p);
687758
}
688759

689-
unlock_task_sighand(p, &flags);
690760
/*
691761
* Install the new reload setting, and
692762
* set up the signal and overrun bookkeeping.
@@ -703,6 +773,8 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
703773
timer->it_overrun_last = 0;
704774
timer->it_overrun = -1;
705775

776+
unlock_task_sighand(p, &flags);
777+
706778
if (new_expires != 0 && !(val < new_expires)) {
707779
/*
708780
* The designated time already passed, so we notify
@@ -712,13 +784,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
712784
cpu_timer_fire(timer);
713785
}
714786

715-
ret = 0;
716-
out:
717-
rcu_read_unlock();
718-
if (old)
719-
old->it_interval = ns_to_timespec64(old_incr);
720-
721-
return ret;
787+
return 0;
722788
}
723789

724790
static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp)
@@ -984,19 +1050,12 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
9841050
{
9851051
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
9861052
struct task_struct *p;
987-
struct sighand_struct *sighand;
9881053
unsigned long flags;
9891054
u64 now;
9901055

991-
rcu_read_lock();
992-
p = cpu_timer_task_rcu(timer);
993-
if (!p)
994-
goto out;
995-
996-
/* Protect timer list r/w in arm_timer() */
997-
sighand = lock_task_sighand(p, &flags);
998-
if (unlikely(sighand == NULL))
999-
goto out;
1056+
p = timer_lock_sighand(timer, &flags);
1057+
if (unlikely(!p))
1058+
return;
10001059

10011060
/*
10021061
* Fetch the current sample and update the timer's expiry time.
@@ -1013,8 +1072,6 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
10131072
*/
10141073
arm_timer(timer, p);
10151074
unlock_task_sighand(p, &flags);
1016-
out:
1017-
rcu_read_unlock();
10181075
}
10191076

10201077
/**

0 commit comments

Comments
 (0)