@@ -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)
414518static 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
724790static 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