From 72618ba82af966bbde6fda49905f6b2b6fa25fd0 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Wed, 6 Oct 2021 17:35:07 +0300 Subject: [PATCH] lib: fix incorrect thread management The current code passes an address of a local variable to `thread_add_read` which stores it into `thread->ref` by the lib. The next time the thread callback is executed, the lib stores NULL into the `thread->ref` which means it writes into some random memory on the stack. To fix this, we should pass a pointer to the vector entry to the lib. Signed-off-by: Igor Ryzhov --- lib/resolver.c | 28 +++++++++++++++------------- lib/vector.c | 11 +++++++++++ lib/vector.h | 1 + 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/lib/resolver.c b/lib/resolver.c index c2153e0a5e..4aba909f25 100644 --- a/lib/resolver.c +++ b/lib/resolver.c @@ -53,14 +53,14 @@ static int resolver_cb_socket_readable(struct thread *t) { struct resolver_state *r = THREAD_ARG(t); int fd = THREAD_FD(t); + struct thread **t_ptr; vector_set_index(r->read_threads, fd, THREAD_RUNNING); ares_process_fd(r->channel, fd, ARES_SOCKET_BAD); if (vector_lookup(r->read_threads, fd) == THREAD_RUNNING) { - t = NULL; + t_ptr = (struct thread **)vector_get_index(r->read_threads, fd); thread_add_read(r->master, resolver_cb_socket_readable, r, fd, - &t); - vector_set_index(r->read_threads, fd, t); + t_ptr); } resolver_update_timeouts(r); @@ -71,14 +71,14 @@ static int resolver_cb_socket_writable(struct thread *t) { struct resolver_state *r = THREAD_ARG(t); int fd = THREAD_FD(t); + struct thread **t_ptr; vector_set_index(r->write_threads, fd, THREAD_RUNNING); ares_process_fd(r->channel, ARES_SOCKET_BAD, fd); if (vector_lookup(r->write_threads, fd) == THREAD_RUNNING) { - t = NULL; + t_ptr = (struct thread **)vector_get_index(r->write_threads, fd); thread_add_write(r->master, resolver_cb_socket_writable, r, fd, - &t); - vector_set_index(r->write_threads, fd, t); + t_ptr); } resolver_update_timeouts(r); @@ -105,14 +105,15 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable, int writable) { struct resolver_state *r = (struct resolver_state *)data; - struct thread *t; + struct thread *t, **t_ptr; if (readable) { - t = vector_lookup_ensure(r->read_threads, fd); + t = vector_lookup(r->read_threads, fd); if (!t) { + t_ptr = (struct thread **)vector_get_index( + r->read_threads, fd); thread_add_read(r->master, resolver_cb_socket_readable, - r, fd, &t); - vector_set_index(r->read_threads, fd, t); + r, fd, t_ptr); } } else { t = vector_lookup(r->read_threads, fd); @@ -125,11 +126,12 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable, } if (writable) { - t = vector_lookup_ensure(r->write_threads, fd); + t = vector_lookup(r->write_threads, fd); if (!t) { + t_ptr = (struct thread **)vector_get_index( + r->write_threads, fd); thread_add_read(r->master, resolver_cb_socket_writable, - r, fd, &t); - vector_set_index(r->write_threads, fd, t); + r, fd, t_ptr); } } else { t = vector_lookup(r->write_threads, fd); diff --git a/lib/vector.c b/lib/vector.c index 565c49fd59..4af564a82f 100644 --- a/lib/vector.c +++ b/lib/vector.c @@ -123,6 +123,17 @@ int vector_set_index(vector v, unsigned int i, void *val) return i; } +/* Make a specified index slot active and return its address. */ +void **vector_get_index(vector v, unsigned int i) +{ + vector_ensure(v, i); + + if (v->active <= i) + v->active = i + 1; + + return &v->index[i]; +} + /* Look up vector. */ void *vector_lookup(vector v, unsigned int i) { diff --git a/lib/vector.h b/lib/vector.h index d5857eb599..845c8d8b04 100644 --- a/lib/vector.h +++ b/lib/vector.h @@ -54,6 +54,7 @@ extern void vector_ensure(vector v, unsigned int num); extern int vector_empty_slot(vector v); extern int vector_set(vector v, void *val); extern int vector_set_index(vector v, unsigned int i, void *val); +extern void **vector_get_index(vector v, unsigned int i); extern void vector_unset(vector v, unsigned int i); extern void vector_unset_value(vector v, void *val); extern void vector_remove(vector v, unsigned int ix); -- 2.39.5