]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Cleanup more atexit stuff, and explicitly trigger atexit handlers to avoid ordering...
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 9 Apr 2022 17:36:20 +0000 (12:36 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 9 Apr 2022 17:36:20 +0000 (12:36 -0500)
17 files changed:
src/bin/dhcpclient.c
src/bin/fuzzer.c
src/bin/radclient.c
src/bin/radict.c
src/bin/radiusd.c
src/bin/radsniff.c
src/bin/radsnmp.c
src/bin/radwho.c
src/bin/unit_test_attribute.c
src/bin/unit_test_map.c
src/bin/unit_test_module.c
src/lib/util/atexit.c
src/lib/util/atexit.h
src/listen/control/radmin.c
src/tests/radclient/acct_1.out
src/tests/radclient/auth_1.out
src/tests/radclient/auth_4.out

index 304d5ea892c7e1dae78190ee4e65903a03ee4693..cea0126e28af424b729137ad50e58c7c470255ce 100644 (file)
@@ -750,5 +750,11 @@ int main(int argc, char **argv)
        fr_dhcpv4_global_free();
        fr_dict_autofree(dhcpclient_dict);
 
-       return ret < 0 ? 1 : 0;
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
+
+       return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
index 7829c825d17270c9b1d43bae0f6668305f8bf242..d9b65d57134c246a49b1b4b8fd30ff62663d8774 100644 (file)
@@ -44,7 +44,6 @@ static dl_t                   *dl = NULL;
 static dl_loader_t             *dl_loader;
 
 static fr_dict_t               *dict = NULL;
-static fr_dict_gctx_t const    *dict_gctx = NULL;
 
 int LLVMFuzzerInitialize(int *argc, char ***argv);
 int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len);
@@ -53,13 +52,17 @@ static void exitHandler(void)
 {
        fr_dict_free(&dict, __FILE__);
 
-       if (fr_dict_global_ctx_free(dict_gctx) < 0) fr_perror("fuzzer");
-
        if (dl && dl->handle) {
                dlclose(dl->handle);
                dl->handle = NULL;
        }
        talloc_free(dl_loader);
+
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
 }
 
 int LLVMFuzzerInitialize(int *argc, char ***argv)
@@ -146,8 +149,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv)
                fr_exit_now(EXIT_FAILURE);
        }
 
-       dict_gctx = fr_dict_global_ctx_init(NULL, true, dict_dir);
-       if (!dict_gctx) {
+       if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
                fr_perror("dict_global");
                fr_exit_now(EXIT_FAILURE);
        }
index 6be1f434241c2cc303ac1ee3e76d534b41c8f41c..9919a0daa9edca2e76584a8ecde02fa98609e0cd 100644 (file)
@@ -1642,9 +1642,13 @@ int main(int argc, char **argv)
                );
        }
 
-       if ((stats.lost > 0) || (stats.failed > 0)) {
-               fr_exit_now(EXIT_FAILURE);
-       }
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
 
-       fr_exit_now(EXIT_SUCCESS);
+       if ((stats.lost > 0) || (stats.failed > 0)) return EXIT_FAILURE;
+
+       return EXIT_SUCCESS;
 }
index 2e3a37365d23fc8e662f323ebd8d3f0a4342ceb3..d3079ab8a8b69c45b65acd416f8d853dcdeac591 100644 (file)
@@ -248,7 +248,6 @@ int main(int argc, char *argv[])
        char const              *protocol = NULL;
 
        TALLOC_CTX              *autofree;
-       fr_dict_gctx_t const    *our_dict_gctx = NULL;
 
        /*
         *      Must be called first, so the handler is called last
@@ -312,8 +311,7 @@ int main(int argc, char *argv[])
                goto finish;
        }
 
-       our_dict_gctx = fr_dict_global_ctx_init(NULL, true, dict_dir);
-       if (!our_dict_gctx) {
+       if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
                fr_perror("radict");
                ret = 1;
                goto finish;
@@ -399,7 +397,13 @@ finish:
                        fr_dict_free(dict_p, __FILE__);
                } while (++dict_p < dict_end);
        }
-       if (fr_dict_global_ctx_free(our_dict_gctx) < 0) fr_perror("radict");
        if (talloc_free(autofree) < 0) fr_perror("radict");
+
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
+
        return found ? ret : 64;
 }
index c737a0e43fd3b6f917f391cbee318ba57921e4b3..a9e502a2d57f789d1982be175276b87404a9fe40 100644 (file)
@@ -1125,6 +1125,12 @@ cleanup:
        if (!rad_suid_is_down_permanent() && (fr_get_lsan_state() == 1)) rad_suid_up();
        fr_strerror_clear();    /* clear error buffer */
 
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
+
        return ret;
 }
 
index 66aec78bbe4dc1b7120abfba80faec36354f4cc8..548ef4573f65a898db105b5f049bda441c9ac816 100644 (file)
@@ -2246,7 +2246,6 @@ int main(int argc, char *argv[])
        char const              *raddb_dir = RADDBDIR;
        char const              *dict_dir = DICTDIR;
        TALLOC_CTX              *autofree;
-       fr_dict_gctx_t const    *dict_gctx = NULL;
 
        rs_stats_t              *stats;
 
@@ -2597,8 +2596,7 @@ int main(int argc, char *argv[])
                                                         conf->pcap_filter, conf->pcap_filter);
        }
 
-       dict_gctx = fr_dict_global_ctx_init(NULL, true, dict_dir);
-       if (!dict_gctx) {
+       if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
                fr_perror("radsniff");
                fr_exit_now(EXIT_FAILURE);
        }
@@ -3038,10 +3036,11 @@ finish:
        fr_dict_autofree(radsniff_dict);
        fr_radius_free();
 
-       if (fr_dict_global_ctx_free(dict_gctx) < 0) {
-               fr_perror("radsniff");
-               ret = EXIT_FAILURE;
-       }
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
 
        return ret;
 }
index 7791a30db3b324b8b41d1ce68aeabe4cf27ee257..60118b6bd1297c3e5911b04102aeb0bbf8157f47 100644 (file)
@@ -1154,5 +1154,11 @@ finish:
         */
        fr_dict_autofree(radsnmp_dict);
 
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
+
        return ret;
 }
index e1d57d7a16da9bf21f91c14e46c275fca8db18a3..7d8c6dedd15e0334e969239722c8cbcbd4904b36 100644 (file)
@@ -198,7 +198,6 @@ int main(int argc, char **argv)
        int                     zap = 0;
        fr_dict_t               *dict = NULL;
        TALLOC_CTX              *autofree;
-       fr_dict_gctx_t const    *dict_gctx = NULL;
 
        char const              *p;
        main_config_t           *config;
@@ -307,8 +306,7 @@ int main(int argc, char **argv)
                return 1;
        }
 
-       dict_gctx = fr_dict_global_ctx_init(NULL, true, config->dict_dir);
-       if (!dict_gctx) {
+       if (!fr_dict_global_ctx_init(NULL, true, config->dict_dir)) {
                fr_perror("%s", main_config->name);
                fr_exit_now(EXIT_FAILURE);
        }
@@ -563,11 +561,13 @@ int main(int argc, char **argv)
        }
        fclose(fp);
 
-       if (fr_dict_global_ctx_free(dict_gctx) < 0) {
-               fr_perror("radwho");
-               ret = EXIT_FAILURE;
-       }
        main_config_free(&config);
 
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
+
        return ret;
 }
index 39e810cc0b6386de5d2c590c6b6e241080da54b4..8704fb3e8cb19150d19d4832f8a7891fe41ae369 100644 (file)
@@ -3760,5 +3760,11 @@ cleanup:
                ret = EXIT_FAILURE;
        }
 
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
+
        return ret;
 }
index 13300e7ba9c8619637f08adae1991542cced5111..b35569d6c420c48e9d31d078d7b22c279f72b4fa 100644 (file)
@@ -89,10 +89,6 @@ static int process_file(char const *filename)
        };
 
        map_list_init(&list);
-       /*
-        *      Must be called first, so the handler is called last
-        */
-       fr_atexit_global_setup();
 
        config = main_config_alloc(NULL);
        if (!config) {
@@ -168,7 +164,6 @@ int main(int argc, char *argv[])
        char const              *receipt_file = NULL;
 
        TALLOC_CTX              *autofree;
-       fr_dict_gctx_t const    *dict_gctx = NULL;
 
        /*
         *      Must be called first, so the handler is called last
@@ -237,8 +232,7 @@ int main(int argc, char *argv[])
                EXIT_WITH_FAILURE;
        }
 
-       dict_gctx = fr_dict_global_ctx_init(NULL, true, dict_dir);
-       if (!dict_gctx) {
+       if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
                fr_perror("unit_test_map");
                EXIT_WITH_FAILURE;
        }
@@ -299,15 +293,16 @@ cleanup:
                ret = EXIT_FAILURE;
        }
 
-       if (fr_dict_global_ctx_free(dict_gctx) < 0) {
-               fr_perror("unit_test_map");
-               ret = EXIT_FAILURE;
-       }
-
        if (receipt_file && (ret == EXIT_SUCCESS) && (fr_touch(NULL, receipt_file, 0644, true, 0755) <= 0)) {
                fr_perror("unit_test_map");
                ret = EXIT_FAILURE;
        }
 
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
+
        return ret;
 }
index e0131bf6f04376774a16c36b88cd772e78472a99..3d59bcce197b3d272f2b4d29004b81128b3d360e 100644 (file)
@@ -548,7 +548,6 @@ int main(int argc, char *argv[])
        char const              *receipt_file = NULL;
 
        TALLOC_CTX              *autofree;
-       fr_dict_gctx_t const    *dict_gctx = NULL;
        TALLOC_CTX              *thread_ctx;
 
        char                    *p;
@@ -723,8 +722,7 @@ int main(int argc, char *argv[])
         */
        modules_init(config->lib_dir);
 
-       dict_gctx = fr_dict_global_ctx_init(NULL, true, config->dict_dir);
-       if (!dict_gctx) {
+       if (!fr_dict_global_ctx_init(NULL, true, config->dict_dir)) {
                fr_perror("%s", config->name);
                EXIT_WITH_FAILURE;
        }
@@ -1079,6 +1077,12 @@ cleanup:
                ret = EXIT_FAILURE;
        }
 
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
+
        return ret;
 }
 
index 273c4ae447959d0fdbf316b04437ff5eb2f3ba87..8e419e82f2b645f82820a42e3d35a3ee21b6e6c5 100644 (file)
@@ -348,6 +348,45 @@ void fr_atexit_thread_local_disarm_all(void)
        }
 }
 
+/** Cause all thread local free triggers to fire
+ *
+ * This is necessary when we're running in single threaded mode
+ * to ensure all "thread-local" memory (which isn't actually thread local)
+ * is cleaned up.
+ *
+ * One example is the OpenSSL log BIOs which must be cleaned up
+ * before fr_openssl_free is called.
+ */
+unsigned int fr_atexit_thread_trigger_all(void)
+{
+       fr_atexit_entry_t               *e = NULL, *ee;
+       fr_atexit_list_t                *list;
+       unsigned int                    count = 0;
+
+       /*
+        *      Iterate over the list of thread local
+        *      destructor lists running the
+        *      destructors.
+        */
+       while ((e = fr_dlist_next(&fr_atexit_threads->head, e))) {
+               if (!e->func) continue; /* thread already joined */
+
+               list = talloc_get_type_abort(e->uctx, fr_atexit_list_t);
+               ee = NULL;
+               while ((ee = fr_dlist_next(&list->head, ee))) {
+                       ATEXIT_DEBUG("%s - Thread %u triggering %p/%p func=%p, uctx=%p (alloced %s:%u)",
+                                    __FUNCTION__,
+                                    (unsigned int)pthread_self(),
+                                    list, ee, ee->func, ee->uctx, ee->file, ee->line);
+
+                       count++;
+                       ee = fr_dlist_talloc_free_item(&list->head, ee);
+               }
+       }
+
+       return count;
+}
+
 /** Remove a specific global destructor (without executing it)
  *
  * @note This function's primary purpose is to help diagnose issues with destructors
@@ -406,6 +445,35 @@ void fr_atexit_global_disarm_all(void)
        }
 }
 
+/** Cause all global free triggers to fire
+ *
+ * This is necessary when libraries (perl) register their own
+ * atexit handlers using the normal POSIX mechanism, and we need
+ * to ensure all our atexit handlers fire before so any global
+ * deinit is done explicitly by us.
+ */
+unsigned int fr_atexit_global_trigger_all(void)
+{
+       fr_atexit_entry_t               *e = NULL;
+       unsigned int                    count = 0;
+
+       /*
+        *      Iterate over the list of thread local
+        *      destructor lists running the
+        *      destructors.
+        */
+       while ((e = fr_dlist_next(&fr_atexit_global->head, e))) {
+               ATEXIT_DEBUG("%s - Triggering %p/%p func=%p, uctx=%p (alloced %s:%u)",
+                            __FUNCTION__,
+                            fr_atexit_global, e, e->func, e->uctx, e->file, e->line);
+
+               count++;
+               e = fr_dlist_talloc_free_item(&fr_atexit_global->head, e);
+       }
+
+       return count;
+}
+
 /** Iterates through all thread local destructor lists, causing destructor to be triggered
  *
  * This should only be called by the main process not by threads.
@@ -470,44 +538,6 @@ do_threads:
        return count;
 }
 
-/** Cause all thread local free triggers to fire
- *
- * This is necessary when we're running in single threaded mode
- * to ensure all "thread-local" memory (which isn't actually thread local)
- * is cleaned up.
- *
- * One example is the OpenSSL log BIOs which must be cleaned up
- * before fr_openssl_free is called.
- */
-unsigned int fr_atexit_thread_trigger_all(void)
-{
-       fr_atexit_entry_t               *e = NULL, *ee;
-       fr_atexit_list_t                *list;
-       unsigned int                    count = 0;
-
-       /*
-        *      Iterate over the list of thread local
-        *      destructor lists running the
-        *      destructors.
-        */
-       while ((e = fr_dlist_next(&fr_atexit_threads->head, e))) {
-               if (!e->func) continue; /* thread already joined */
-
-               list = talloc_get_type_abort(e->uctx, fr_atexit_list_t);
-               ee = NULL;
-               while ((ee = fr_dlist_next(&list->head, ee))) {
-                       ATEXIT_DEBUG("%s - Thread %u triggering %p/%p func=%p, uctx=%p (alloced %s:%u)",
-                                    __FUNCTION__,
-                                    (unsigned int)pthread_self(),
-                                    list, ee, ee->func, ee->uctx, ee->file, ee->line);
-
-                       count++;
-                       ee = fr_dlist_talloc_free_item(&list->head, ee);
-               }
-       }
-
-       return count;
-}
 
 /** Return whether we're currently in the teardown phase
  *
index 9d1dc0911bb19c0956400dfb03510b43f1cde018..e8b42a11b7eb040e5efdcf5732c09fb5b4761b42 100644 (file)
@@ -117,13 +117,15 @@ unsigned int      fr_atexit_thread_local_disarm(bool uctx_scope, fr_atexit_t func, vo
 
 void           fr_atexit_thread_local_disarm_all(void);
 
+unsigned int   fr_atexit_thread_trigger_all(void);
+
 unsigned int   fr_atexit_global_disarm(bool uctx_scope, fr_atexit_t func, void const *uctx);
 
 void           fr_atexit_global_disarm_all(void);
 
-unsigned int   fr_atexit_trigger(bool uctx_scope, fr_atexit_t func, void const *uctx);
+unsigned int   fr_atexit_global_trigger_all(void);
 
-unsigned int   fr_atexit_thread_trigger_all(void);
+unsigned int   fr_atexit_trigger(bool uctx_scope, fr_atexit_t func, void const *uctx);
 
 bool           fr_atexit_is_exiting(void);
 
index aaebe9039699a2f6c2a77466d1664903f0f7abf4..fcb349cc1759477147c50eb858e9186a45133893 100644 (file)
@@ -843,7 +843,6 @@ int main(int argc, char **argv)
 #endif
 
        TALLOC_CTX              *autofree;
-       fr_dict_gctx_t const    *dict_gctx = NULL;
 
        char *commands[MAX_COMMANDS];
        int num_commands = -1;
@@ -975,8 +974,7 @@ int main(int argc, char **argv)
                 *      Need to read in the dictionaries, else we may get
                 *      validation errors when we try and parse the config.
                 */
-               dict_gctx = fr_dict_global_ctx_init(NULL, true, dict_dir);
-               if (!dict_gctx) {
+               if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
                        fr_perror("radmin");
                        fr_exit_now(64);
                }
@@ -1322,8 +1320,6 @@ int main(int argc, char **argv)
 exit:
        fr_dict_free(&dict, __FILE__);
 
-       if (fr_dict_global_ctx_free(dict_gctx) < 0) fr_perror("radmin");
-
        if (inputfp != stdin) fclose(inputfp);
 
        if (radmin_log.dst == L_DST_FILES) close(radmin_log.fd);
@@ -1332,5 +1328,11 @@ exit:
 
        if (!quiet) fprintf(stdout, "\n");
 
+       /*
+        *      Ensure our atexit handlers run before any other
+        *      atexit handlers registered by third party libraries.
+        */
+       fr_atexit_global_trigger_all();
+
        return exit_status;
 }
index 4183666c4f063b3b56673ddc8f28681ce46a1291..853836238afc02a90da66381e4bf021182ef7baf 100644 (file)
@@ -3,3 +3,4 @@ Sent Accounting-Request Id 123 from 0.0.0.0:1234 to 127.0.0.1:12340 length 43
         User-Password = "hello"
         Password.Cleartext = "hello"
 Received Accounting-Response Id 123 from 127.0.0.1:12340 to 0.0.0.0:1234 via lo length 20 
+(0) src/tests/radclient/acct_1.txt response code 5
index f59a3e815429bbdf7e3d210cc64373e9ab495773..970ed35712ca002aec4001cb609ad4362737d8a3 100644 (file)
@@ -3,3 +3,4 @@ Sent Access-Request Id 123 from 0.0.0.0:1234 to 127.0.0.1:12340 length 43
         User-Password = "hello"
         Password.Cleartext = "hello"
 Received Access-Accept Id 123 from 127.0.0.1:12340 to 0.0.0.0:1234 via lo length 20 
+(0) src/tests/radclient/auth_1.txt response code 2
index 5e80983bbae95905b6bce2b3fc4445782b9de977..d27113023501ded37aba4b12d6a4303636b2970f 100644 (file)
@@ -7,3 +7,4 @@ Received Access-Accept Id 123 from 127.0.0.1:12340 to 0.0.0.0:1234 via lo length
         Class = 0x483d342c493d34
         raw.Vendor-Specific = 0x483d342c493d34
         raw.Vendor-Specific = 0x483d342c493d43
+(0) src/tests/radclient/auth_4.txt response code 2