diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 71a07699a36b..9641958ddb3e 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -377,27 +377,32 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
  */
 static int posix_cpu_timer_del(struct k_itimer *timer)
 {
-	struct task_struct *p = timer->it.cpu.task;
 	int ret = 0;
+	unsigned long flags;
+	struct sighand_struct *sighand;
+	struct task_struct *p = timer->it.cpu.task;
 
 	WARN_ON_ONCE(p == NULL);
 
-	read_lock(&tasklist_lock);
-	if (unlikely(p->sighand == NULL)) {
+	/*
+	 * Protect against sighand release/switch in exit/exec and process/
+	 * thread timer list entry concurrent read/writes.
+	 */
+	sighand = lock_task_sighand(p, &flags);
+	if (unlikely(sighand == NULL)) {
 		/*
 		 * We raced with the reaping of the task.
 		 * The deletion should have cleared us off the list.
 		 */
 		BUG_ON(!list_empty(&timer->it.cpu.entry));
 	} else {
-		spin_lock(&p->sighand->siglock);
 		if (timer->it.cpu.firing)
 			ret = TIMER_RETRY;
 		else
 			list_del(&timer->it.cpu.entry);
-		spin_unlock(&p->sighand->siglock);
+
+		unlock_task_sighand(p, &flags);
 	}
-	read_unlock(&tasklist_lock);
 
 	if (!ret)
 		put_task_struct(p);