From 7233414aeb009dd527446e4e2f68c74ddcd58d91 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 4 Aug 2023 07:11:13 +0000 Subject: [PATCH] Revert "posix-timers: Ensure timer ID search-loop limit is valid" This reverts commit 8ad6679a5bb97cdb3e14942729292b4bfcc0e223 which is commit 8ce8849dd1e78dadcee0ec9acbd259d239b7069f upstream. It breaks the Android abi. If it is required in the future, it can come back in an abi-safe way. Bug: 161946584 Change-Id: I44be0f7b4df730e599bf80939b6d40d4f8d04a57 Signed-off-by: Greg Kroah-Hartman --- include/linux/sched/signal.h | 2 +- kernel/time/posix-timers.c | 31 +++++++++++++------------------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 9c1b634e1361f..8caadcb24829f 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -124,7 +124,7 @@ struct signal_struct { #ifdef CONFIG_POSIX_TIMERS /* POSIX.1b Interval Timers */ - unsigned int next_posix_timer_id; + int posix_timer_id; struct list_head posix_timers; /* ITIMER_REAL timer for the process */ diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index f3b8313475acd..efe3873021a37 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -138,30 +138,25 @@ static struct k_itimer *posix_timer_by_id(timer_t id) static int posix_timer_add(struct k_itimer *timer) { struct signal_struct *sig = current->signal; + int first_free_id = sig->posix_timer_id; struct hlist_head *head; - unsigned int cnt, id; + int ret = -ENOENT; - /* - * FIXME: Replace this by a per signal struct xarray once there is - * a plan to handle the resulting CRIU regression gracefully. - */ - for (cnt = 0; cnt <= INT_MAX; cnt++) { + do { spin_lock(&hash_lock); - id = sig->next_posix_timer_id; - - /* Write the next ID back. Clamp it to the positive space */ - sig->next_posix_timer_id = (id + 1) & INT_MAX; - - head = &posix_timers_hashtable[hash(sig, id)]; - if (!__posix_timers_find(head, sig, id)) { + head = &posix_timers_hashtable[hash(sig, sig->posix_timer_id)]; + if (!__posix_timers_find(head, sig, sig->posix_timer_id)) { hlist_add_head_rcu(&timer->t_hash, head); - spin_unlock(&hash_lock); - return id; + ret = sig->posix_timer_id; } + if (++sig->posix_timer_id < 0) + sig->posix_timer_id = 0; + if ((sig->posix_timer_id == first_free_id) && (ret == -ENOENT)) + /* Loop over all possible ids completed */ + ret = -EAGAIN; spin_unlock(&hash_lock); - } - /* POSIX return code when no timer ID could be allocated */ - return -EAGAIN; + } while (ret == -ENOENT); + return ret; } static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)