]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 2831] Segmentation Fault in DNS lookup during startup.
authorJuergen Perlinger <perlinger@ntp.org>
Mon, 18 Apr 2016 04:07:25 +0000 (06:07 +0200)
committerJuergen Perlinger <perlinger@ntp.org>
Mon, 18 Apr 2016 04:07:25 +0000 (06:07 +0200)
 - fixed yet another race condition in the threaded resolver code.

bk: 57145d7dZelIoPAI7f2C_7HLVzESCg

ChangeLog
include/ntp_worker.h
libntp/ntp_intres.c
libntp/work_fork.c
libntp/work_thread.c

index c70fe8fc563cf0a16def01a652b989e8bc667f06..6b2918084b4b9108fdf4384f2b50b4dd44e4ec81 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 ---
 
+* [Bug 2831]  Segmentation Fault in DNS lookup during startup. perlinger@ntp.org
+  - fixed yet another race condition in the threaded resolver code.
 * [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger@ntp.org
 * [Bug 2995] Fixes to compile on Windows
 
index bc833795b5efab2b0d967aa1209377b3cd1324a2..49ffef4cf64bdd9aaed90bc9209c751c88faa310 100644 (file)
@@ -171,6 +171,8 @@ extern      void    close_all_except(int);
 extern void    kill_asyncio    (int);
 #endif
 
+extern void worker_global_lock(int inOrOut);
+
 # ifdef WORK_PIPE
 typedef        void    (*addremove_io_fd_func)(int, int, int);
 extern addremove_io_fd_func            addremove_io_fd;
index b0f562036a0084e86b1ab2638bae1f144a498d58..0b5bb753425691a1d039f1930ff9033a769a6908 100644 (file)
@@ -201,8 +201,6 @@ static      time_t          next_res_init;
 /* === forward declarations === */
 static u_int           reserve_dnschild_ctx(void);
 static u_int           get_dnschild_ctx(void);
-static void            alloc_dnsworker_context(u_int);
-/* static      void            free_dnsworker_context(u_int); */
 static dnsworker_ctx * get_worker_context(blocking_child *, u_int);
 static void            scheduled_sleep(time_t, time_t,
                                        dnsworker_ctx *);
@@ -949,47 +947,41 @@ get_dnschild_ctx(void)
 }
 
 
-static void
-alloc_dnsworker_context(
-       u_int idx
-       )
-{
-       const size_t worker_context_sz = sizeof(*dnsworker_contexts[0]);
-
-       REQUIRE(NULL == dnsworker_contexts[idx]);
-       dnsworker_contexts[idx] = emalloc_zero(worker_context_sz);
-}
-
-
 static dnsworker_ctx *
 get_worker_context(
        blocking_child *        c,
        u_int                   idx
        )
 {
-       static size_t   ps = sizeof(dnsworker_contexts[0]);
-       u_int   min_new_alloc;
-       u_int   new_alloc;
-       size_t  octets;
-       size_t  new_octets;
+       u_int           min_new_alloc;
+       u_int           new_alloc;
+       size_t          octets;
+       size_t          new_octets;
+       dnsworker_ctx * retv;
 
+       worker_global_lock(TRUE);
+       
        if (dnsworker_contexts_alloc <= idx) {
                min_new_alloc = 1 + idx;
                /* round new_alloc up to nearest multiple of 4 */
                new_alloc = (min_new_alloc + 4) & ~(4 - 1);
-               new_octets = new_alloc * ps;
-               octets = dnsworker_contexts_alloc * ps;
+               new_octets = new_alloc * sizeof(dnsworker_ctx*);
+               octets = dnsworker_contexts_alloc * sizeof(dnsworker_ctx*);
                dnsworker_contexts = erealloc_zero(dnsworker_contexts,
                                                   new_octets, octets);
                dnsworker_contexts_alloc = new_alloc;
+               retv = emalloc_zero(sizeof(dnsworker_ctx));
+               dnsworker_contexts[idx] = retv;
+       } else if (NULL == (retv = dnsworker_contexts[idx])) {
+               retv = emalloc_zero(sizeof(dnsworker_ctx));
+               dnsworker_contexts[idx] = retv;
        }
-
-       if (NULL == dnsworker_contexts[idx])
-               alloc_dnsworker_context(idx);
-       ZERO(*dnsworker_contexts[idx]);
-       dnsworker_contexts[idx]->c = c;
-
-       return dnsworker_contexts[idx];
+       
+       worker_global_lock(FALSE);
+       
+       ZERO(*retv);
+       retv->c = c;
+       return retv;
 }
 
 
index 96c550e98594369a022ec26f359699e592d93af4..5d72d8ced1c8a6d5faf6cd7b649ab35d9e2f327e 100644 (file)
@@ -540,6 +540,11 @@ fork_blocking_child(
 }
 
 
+void worker_global_lock(int inOrOut)
+{
+       (void)inOrOut;
+}
+
 #else  /* !WORK_FORK follows */
 char work_fork_nonempty_compilation_unit;
 #endif
index 11e3267d4a8bcbb5bfdaeebd2e3ede9581de1a33..82f6064fb35966b86bb71aae8b4ba574b5015cc2 100644 (file)
@@ -88,7 +88,27 @@ static       int     ensure_workresp_empty_slot(blocking_child *);
 static int     queue_req_pointer(blocking_child *, blocking_pipe_header *);
 static void    cleanup_after_child(blocking_child *);
 
+static sema_type worker_mmutex;
+static sem_ref   worker_memlock;
 
+/* --------------------------------------------------------------------
+ * locking the global worker state table (and other global stuff)
+ */
+void
+worker_global_lock(
+       int inOrOut)
+{
+       if (worker_memlock) {
+               if (inOrOut)
+                       wait_for_sem(worker_memlock, NULL);
+               else
+                       tickle_sem(worker_memlock);
+       }
+}
+
+/* --------------------------------------------------------------------
+ * implementation isolation wrapper
+ */
 void
 exit_worker(
        int     exitcode
@@ -724,6 +744,9 @@ prepare_child_sems(
        blocking_child *c
        )
 {
+       if (NULL == worker_memlock)
+               worker_memlock = create_sema(&worker_mmutex, 1, 1);
+       
        c->accesslock           = create_sema(&c->sem_table[0], 1, 1);
        c->workitems_pending    = create_sema(&c->sem_table[1], 0, 0);
        c->wake_scheduled_sleep = create_sema(&c->sem_table[2], 0, 1);