From 792aa870d56e0eb23e041cecc0d5f5a379b781dc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Apr 2024 13:40:21 +0000 Subject: [PATCH] Revert "posix-timers: Ensure timer ID search-loop limit is valid" This reverts commit ef535e0315afd098c4beb1da364847eca4b56a20 which is commit 8ce8849dd1e78dadcee0ec9acbd259d239b7069f upstream. It breaks the Android kernel abi and can be brought back in the future in an abi-safe way if it is really needed. Bug: 161946584 Change-Id: Icdf91cda9a996fef8c8f5413b1b406a5fa936afb 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 6f0941f01209..093aea9b0d8a 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -126,7 +126,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 2d6cf93ca370..ed3c4a954398 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -140,30 +140,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)