Skip to content

Commit 2579ef9

Browse files
committed
Merge tag 'v6.12.100' into 6.12-main
This is the 6.12.100 stable release # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmprL/AACgkQONu9yGCS # aT5pyg/6Aqs1D7MndA9XqtiHwQ0EhXqY4rM5YvRpb7x356Hd2JBK19f2nGTFhx/w # 4okogE/WGMmgMabwWnhrV3wCmCRTauqQiAlMTBnrBbu+CyrKv86fO1cggbs8XvDU # 8gafiA2AIRaAQ2u7Zd71niM/yJPpgeMi/BfguU8RdIkQh6mVK4kVwzSUxja4KEOJ # HM8y5KvZpvMiVDGtPuI4ycRTsAHAxuDEiPfYb+ZFLqSY7s3+oX+rhjfgrs1Plh6Y # S7ZqX9MpgsCvIiU+biaU+kpZVxAF+bTNfLKI2+aUqqCBTZafoM37q6WI8nbToNW5 # B6zKDiSpgj9DGkbEAY99Ov854pjAzAhygO0HL6UQw/gHP08bLoFmYk6iyYjFVw2X # 0tsRObIUX2bwMACwQBGugWiEehYAHeaCvV+1sK5SjGdA4yvqkZgJR4CGn5xPPmFh # w1lHoqPCvnleVjB8gS8l8N/Whcybt3F3YvtX5tF+c9m3AzH9sD4oQo9r2ERCBZWl # w+LSHjl4jccWY2WeD5/umkrYhBYz/ARQmeK4b30FH3OpoptqcvQi8kj73Q7vqGLx # Lp6RHIhq8A0b+j/Wy2E/hJ+r3AgOT5aPE004jL2jLVmffBw7bXAv8pWsazKPNnlE # s8H0dTHnAOwslYCYCku4ePg0ZSzihK8bB4tWeXuX3FAsOmI092w= # =Pd+V # -----END PGP SIGNATURE----- # gpg: Signature made Thu Jul 30 13:05:20 2026 CEST # gpg: using RSA key 647F28654894E3BD457199BE38DBBDC86092693E # gpg: Can't check signature: No public key
2 parents 9256bd1 + 52a355b commit 2579ef9

4 files changed

Lines changed: 133 additions & 63 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 = 6
33
PATCHLEVEL = 12
4-
SUBLEVEL = 99
4+
SUBLEVEL = 100
55
EXTRAVERSION =
66
NAME = Baby Opossum Posse
77

kernel/exit.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,13 @@ static void __exit_signal(struct task_struct *tsk)
205205
* doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals.
206206
*/
207207
flush_sigqueue(&tsk->pending);
208-
tsk->sighand = NULL;
208+
209+
/*
210+
* Ensure that all preceeding state is visible. Pairs with
211+
* the smp_acquire__after_ctrl_dep() in the sighand == NULL
212+
* path of lock_task_sighand().
213+
*/
214+
smp_store_release(&tsk->sighand, NULL);
209215
spin_unlock(&sighand->siglock);
210216

211217
__cleanup_sighand(sighand);

kernel/signal.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1395,8 +1395,16 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
13951395
rcu_read_lock();
13961396
for (;;) {
13971397
sighand = rcu_dereference(tsk->sighand);
1398-
if (unlikely(sighand == NULL))
1398+
if (unlikely(sighand == NULL)) {
1399+
/*
1400+
* Pairs with the smp_store_release() in
1401+
* __exit_signal(). It ensures that all state
1402+
* modifications to the task preceeding the store are
1403+
* visible to the callers of lock_task_sighand().
1404+
*/
1405+
smp_acquire__after_ctrl_dep();
13991406
break;
1407+
}
14001408

14011409
/*
14021410
* This sighand can be already freed and even reused, but

kernel/time/posix-cpu-timers.c

Lines changed: 116 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,109 @@ static void disarm_timer(struct k_itimer *timer, struct task_struct *p)
462462
trigger_base_recalc_expires(timer, p);
463463
}
464464

465+
/*
466+
* Lookup the task via timer->it.cpu.pid and attempt to lock the task's sighand.
467+
*
468+
* This can race with the reaping of the task:
469+
*
470+
* CPU0 CPU1
471+
*
472+
* // Finds task
473+
* p = pid_task(pid, pid_type); __exit_signal(p)
474+
* lock(p, sighand);
475+
* posix_cpu_timers*_exit();
476+
* sighand = lock_task_sighand(p); unhash_task(p);
477+
* p->sighand = NULL;
478+
* unlock(sighand);
479+
*
480+
* In this case sighand is NULL, which means the task and the associated timer
481+
* queue cannot be longer accessed safely.
482+
*
483+
* __exit_signal() invokes posix_cpu_timers_exit() and if the thread group is
484+
* dead it also invokes posix_cpu_timers_group_exit(). These functions delete
485+
* all pending timers from the related timer queues. The POSIX timers (k_itimer)
486+
* themself are still accessible, but not longer connected to the task.
487+
*
488+
* exec() works slightly differently. The task which exec()'s terminates all
489+
* other threads in the thread group and runs __exit_signal() on them. As the
490+
* thread group is not dead they only clean up the per task timers via
491+
* posix_cpu_timers_exit().
492+
*
493+
* As the TGID on exec() stays the same per process timers stay queued, if they
494+
* are armed. This works without a problem when exec() is done by the thread
495+
* group leader. If a non-leader thread exec()'s this can end up in the
496+
* following scenario:
497+
*
498+
* CPU0 CPU1
499+
* // Returns old leader
500+
* p = pid_task(pid, pid_type); de_thread()
501+
* switch_leader()
502+
* release_task(old leader)
503+
* __exit_signal()
504+
* old_leader->sighand = NULL;
505+
* // Returns NULL
506+
* sighand = lock_task_sighand(p)
507+
*
508+
* That's problematic for several functions:
509+
*
510+
* - posix_cpu_timer_del(): If the timer is still enqueued on the task the
511+
* underlying k_itimer will be freed which results in a UAF in
512+
* run_posix_cpu_timers() or on timerqueue related add/delete operations.
513+
* If the timer is not enqueued, the failure is harmless
514+
*
515+
* - posix_cpu_timer_set(): Independent of the enqueued state that results in a
516+
* transient failure which is user space visible (-ESRCH) for regular posix
517+
* timers. But for the use case in do_cpu_nanosleep() it's the same UAF
518+
* problem just that the timer is allocated on the stack.
519+
*
520+
* - posix_cpu_timer_rearm(): Timer is not enqueued at that point, but this
521+
* silently ignores the rearm request, which is a functional problem as the
522+
* timer wont expire anymore.
523+
*/
524+
static struct task_struct *timer_lock_sighand(struct k_itimer *timer, unsigned long *flags)
525+
{
526+
enum pid_type type = clock_pid_type(timer->it_clock);
527+
struct cpu_timer *ctmr = &timer->it.cpu;
528+
529+
guard(rcu)();
530+
531+
for (;;) {
532+
struct task_struct *t = pid_task(timer->it.cpu.pid, type);
533+
534+
/* Fail if the task cannot be found. */
535+
if (!t)
536+
break;
537+
538+
/* Try to lock the task's sighand */
539+
if (lock_task_sighand(t, flags))
540+
return t;
541+
542+
/*
543+
* The next PID lookup might either fail or return the new
544+
* leader. This is correct for both exit() and exec().
545+
*/
546+
}
547+
548+
/*
549+
* If the timer is still enqueued, warn. There is nothing safe to do
550+
* here as there might be two timers in there which are removed in
551+
* parallel and that will cause more damage than good. This should never
552+
* happen!
553+
*
554+
* Ensure that the stores to the timer and timerqueue are visible:
555+
*
556+
* __exit_signal()
557+
* posix_cpu_timers*_exit()
558+
* write_seqlock(seqlock)
559+
* smp_wmb(); <-------
560+
* __unhash_process() | !pid_task()
561+
* ----> smp_rmb();
562+
* WARN_ON_ONCE(...)
563+
*/
564+
smp_rmb();
565+
WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
566+
return NULL;
567+
}
465568

466569
/*
467570
* Clean up a CPU-clock timer that is about to be destroyed.
@@ -471,29 +574,13 @@ static void disarm_timer(struct k_itimer *timer, struct task_struct *p)
471574
*/
472575
static int posix_cpu_timer_del(struct k_itimer *timer)
473576
{
474-
struct cpu_timer *ctmr = &timer->it.cpu;
475-
struct sighand_struct *sighand;
476577
struct task_struct *p;
477578
unsigned long flags;
478579
int ret = 0;
479580

480-
rcu_read_lock();
481-
p = cpu_timer_task_rcu(timer);
482-
if (!p)
483-
goto out;
581+
p = timer_lock_sighand(timer, &flags);
484582

485-
/*
486-
* Protect against sighand release/switch in exit/exec and process/
487-
* thread timer list entry concurrent read/writes.
488-
*/
489-
sighand = lock_task_sighand(p, &flags);
490-
if (unlikely(sighand == NULL)) {
491-
/*
492-
* This raced with the reaping of the task. The exit cleanup
493-
* should have removed this timer from the timer queue.
494-
*/
495-
WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
496-
} else {
583+
if (likely(p)) {
497584
if (timer->it.cpu.firing)
498585
ret = TIMER_RETRY;
499586
else
@@ -502,10 +589,8 @@ static int posix_cpu_timer_del(struct k_itimer *timer)
502589
unlock_task_sighand(p, &flags);
503590
}
504591

505-
out:
506-
rcu_read_unlock();
507592
if (!ret)
508-
put_pid(ctmr->pid);
593+
put_pid(timer->it.cpu.pid);
509594

510595
return ret;
511596
}
@@ -627,42 +712,24 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
627712
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
628713
struct cpu_timer *ctmr = &timer->it.cpu;
629714
u64 old_expires, new_expires, now;
630-
struct sighand_struct *sighand;
631715
struct task_struct *p;
632716
unsigned long flags;
633717
int ret = 0;
634718

635-
rcu_read_lock();
636-
p = cpu_timer_task_rcu(timer);
637-
if (!p) {
638-
/*
639-
* If p has just been reaped, we can no
640-
* longer get any information about it at all.
641-
*/
642-
rcu_read_unlock();
719+
p = timer_lock_sighand(timer, &flags);
720+
/*
721+
* If p has just been reaped, we can no longer get any information about
722+
* it at all.
723+
*/
724+
if (!p)
643725
return -ESRCH;
644-
}
645726

646727
/*
647728
* Use the to_ktime conversion because that clamps the maximum
648729
* value to KTIME_MAX and avoid multiplication overflows.
649730
*/
650731
new_expires = ktime_to_ns(timespec64_to_ktime(new->it_value));
651732

652-
/*
653-
* Protect against sighand release/switch in exit/exec and p->cpu_timers
654-
* and p->signal->cpu_timers read/write in arm_timer()
655-
*/
656-
sighand = lock_task_sighand(p, &flags);
657-
/*
658-
* If p has just been reaped, we can no
659-
* longer get any information about it at all.
660-
*/
661-
if (unlikely(sighand == NULL)) {
662-
rcu_read_unlock();
663-
return -ESRCH;
664-
}
665-
666733
/* Retrieve the current expiry time before disarming the timer */
667734
old_expires = cpu_timer_getexpires(ctmr);
668735

@@ -693,7 +760,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
693760
/* Retry if the timer expiry is running concurrently */
694761
if (unlikely(ret)) {
695762
unlock_task_sighand(p, &flags);
696-
goto out;
763+
return ret;
697764
}
698765

699766
/* Convert relative expiry time to absolute */
@@ -728,8 +795,6 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
728795
*/
729796
if (!sigev_none && new_expires && now >= new_expires)
730797
cpu_timer_fire(timer);
731-
out:
732-
rcu_read_unlock();
733798
return ret;
734799
}
735800

@@ -1011,19 +1076,12 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
10111076
{
10121077
clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
10131078
struct task_struct *p;
1014-
struct sighand_struct *sighand;
10151079
unsigned long flags;
10161080
u64 now;
10171081

1018-
rcu_read_lock();
1019-
p = cpu_timer_task_rcu(timer);
1020-
if (!p)
1021-
goto out;
1022-
1023-
/* Protect timer list r/w in arm_timer() */
1024-
sighand = lock_task_sighand(p, &flags);
1025-
if (unlikely(sighand == NULL))
1026-
goto out;
1082+
p = timer_lock_sighand(timer, &flags);
1083+
if (unlikely(!p))
1084+
return;
10271085

10281086
/*
10291087
* Fetch the current sample and update the timer's expiry time.
@@ -1040,8 +1098,6 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
10401098
*/
10411099
arm_timer(timer, p);
10421100
unlock_task_sighand(p, &flags);
1043-
out:
1044-
rcu_read_unlock();
10451101
}
10461102

10471103
/**

0 commit comments

Comments
 (0)