From b57aba114b045be6eb3d98f1f61a76ad498e46c4 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 12 Feb 2020 10:01:29 +0100 Subject: [PATCH] BUG/MEDIUM: listener: only consider running threads when resuming listeners In bug #495 we found that it is possible to resume a listener on an inexistent thread. This happens when a bind's thread_mask contains bits out of the active threads mask, such as when using "1/odd" or "1/even". The thread_mask was used as-is to pick a thread number to re-enable the listener, and given that the highest number is used, 1/odd or 1/even can produce quite high thread numbers and crash the process by queuing some entries into non-existent lists. This bug is an incomplete fix of commit 413e926ba ("BUG/MAJOR: listener: fix thread safety in resume_listener()") though it will only trigger if some bind lines are explicitly bound to thread numbers higher than the thread count. The fix must be backported to all branches having the fix above (as far as 1.8, though the code is different there, see the commit message in 1.8 for changes). There are a few other places where bind_thread is used without enforcing all_thread_mask, namely when doing fd_insert() while creating listeners. It seems harmless but would probably deserve another fix. (cherry picked from commit 50b659476ceb8e5ee3a060df1da0d32d336a58a8) Signed-off-by: Willy Tarreau --- src/listener.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/listener.c b/src/listener.c index 09460b5..81af0b7 100644 --- a/src/listener.c +++ b/src/listener.c @@ -386,7 +386,7 @@ int resume_listener(struct listener *l) /* we're not allowed to touch this listener's FD, let's requeue * the listener into one of its owning thread's queue instead. */ - int first_thread = my_flsl(thread_mask(l->bind_conf->bind_thread)) - 1; + int first_thread = my_flsl(thread_mask(l->bind_conf->bind_thread) & all_threads_mask) - 1; work_list_add(&local_listener_queue[first_thread], &l->wait_queue); goto end; } -- 1.7.10.4