hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/kernel/time/posix-timers.c
....@@ -846,6 +846,10 @@
846846 rcu_read_lock();
847847 unlock_timer(timer, *flags);
848848
849
+ /*
850
+ * kc->timer_wait_running() might drop RCU lock. So @timer
851
+ * cannot be touched anymore after the function returns!
852
+ */
849853 if (!WARN_ON_ONCE(!kc->timer_wait_running))
850854 kc->timer_wait_running(timer);
851855
....@@ -1033,27 +1037,52 @@
10331037 }
10341038
10351039 /*
1036
- * return timer owned by the process, used by exit_itimers
1040
+ * Delete a timer if it is armed, remove it from the hash and schedule it
1041
+ * for RCU freeing.
10371042 */
10381043 static void itimer_delete(struct k_itimer *timer)
10391044 {
1040
-retry_delete:
1041
- spin_lock_irq(&timer->it_lock);
1045
+ unsigned long flags;
10421046
1047
+ /*
1048
+ * irqsave is required to make timer_wait_running() work.
1049
+ */
1050
+ spin_lock_irqsave(&timer->it_lock, flags);
1051
+
1052
+retry_delete:
1053
+ /*
1054
+ * Even if the timer is not longer accessible from other tasks
1055
+ * it still might be armed and queued in the underlying timer
1056
+ * mechanism. Worse, that timer mechanism might run the expiry
1057
+ * function concurrently.
1058
+ */
10431059 if (timer_delete_hook(timer) == TIMER_RETRY) {
1044
- spin_unlock_irq(&timer->it_lock);
1060
+ /*
1061
+ * Timer is expired concurrently, prevent livelocks
1062
+ * and pointless spinning on RT.
1063
+ *
1064
+ * timer_wait_running() drops timer::it_lock, which opens
1065
+ * the possibility for another task to delete the timer.
1066
+ *
1067
+ * That's not possible here because this is invoked from
1068
+ * do_exit() only for the last thread of the thread group.
1069
+ * So no other task can access and delete that timer.
1070
+ */
1071
+ if (WARN_ON_ONCE(timer_wait_running(timer, &flags) != timer))
1072
+ return;
1073
+
10451074 goto retry_delete;
10461075 }
10471076 list_del(&timer->list);
10481077
1049
- spin_unlock_irq(&timer->it_lock);
1078
+ spin_unlock_irqrestore(&timer->it_lock, flags);
10501079 release_posix_timer(timer, IT_ID_SET);
10511080 }
10521081
10531082 /*
1054
- * This is called by do_exit or de_thread, only when nobody else can
1055
- * modify the signal->posix_timers list. Yet we need sighand->siglock
1056
- * to prevent the race with /proc/pid/timers.
1083
+ * Invoked from do_exit() when the last thread of a thread group exits.
1084
+ * At that point no other task can access the timers of the dying
1085
+ * task anymore.
10571086 */
10581087 void exit_itimers(struct task_struct *tsk)
10591088 {
....@@ -1063,10 +1092,12 @@
10631092 if (list_empty(&tsk->signal->posix_timers))
10641093 return;
10651094
1095
+ /* Protect against concurrent read via /proc/$PID/timers */
10661096 spin_lock_irq(&tsk->sighand->siglock);
10671097 list_replace_init(&tsk->signal->posix_timers, &timers);
10681098 spin_unlock_irq(&tsk->sighand->siglock);
10691099
1100
+ /* The timers are not longer accessible via tsk::signal */
10701101 while (!list_empty(&timers)) {
10711102 tmr = list_first_entry(&timers, struct k_itimer, list);
10721103 itimer_delete(tmr);
....@@ -1270,6 +1301,7 @@
12701301 return -EINVAL;
12711302 if (flags & TIMER_ABSTIME)
12721303 rmtp = NULL;
1304
+ current->restart_block.fn = do_no_restart_syscall;
12731305 current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
12741306 current->restart_block.nanosleep.rmtp = rmtp;
12751307
....@@ -1297,6 +1329,7 @@
12971329 return -EINVAL;
12981330 if (flags & TIMER_ABSTIME)
12991331 rmtp = NULL;
1332
+ current->restart_block.fn = do_no_restart_syscall;
13001333 current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE;
13011334 current->restart_block.nanosleep.compat_rmtp = rmtp;
13021335