]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Only lock view->newzone.lock if not already locked
authorMatthijs Mekking <matthijs@isc.org>
Fri, 13 Mar 2026 10:52:47 +0000 (11:52 +0100)
committerMatthijs Mekking <matthijs@isc.org>
Tue, 17 Mar 2026 09:51:18 +0000 (09:51 +0000)
Some code paths try to lock an already locked view->newzone.lock.

For example, do_modzone() aqcuires the lock and then calls
delete_zoneconf(), that wants to acquire the same lock.

Add a parameter to delete_zoneconf() that informs the function if the
lock has already been acquired.

(cherry picked from commit 71587b0816a9458895aaa14a85539acd91afda38)

bin/named/server.c

index 796b4cc97ee6b08710e302e3bf8cac169fbe405c..d2ac553ffc6fa9f87bc1ceec8c06dc16e59eaa69 100644 (file)
@@ -13863,7 +13863,7 @@ cleanup:
 
 static isc_result_t
 delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config,
-               const dns_name_t *zname, nzfwriter_t nzfwriter) {
+               const dns_name_t *zname, nzfwriter_t nzfwriter, bool locked) {
        isc_result_t result = ISC_R_NOTFOUND;
        const cfg_listelt_t *elt = NULL;
        const cfg_obj_t *zl = NULL;
@@ -13876,7 +13876,9 @@ delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config,
        REQUIRE(config != NULL);
        REQUIRE(zname != NULL);
 
-       LOCK(&view->new_zone_lock);
+       if (!locked) {
+               LOCK(&view->new_zone_lock);
+       }
 
        cfg_map_get(config, "zone", &zl);
 
@@ -13917,7 +13919,9 @@ delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config,
        }
 
 cleanup:
-       UNLOCK(&view->new_zone_lock);
+       if (!locked) {
+               UNLOCK(&view->new_zone_lock);
+       }
        return result;
 }
 
@@ -13927,13 +13931,13 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
           bool redirect, isc_buffer_t **text) {
        isc_result_t result, tresult;
        dns_zone_t *zone = NULL;
+       bool locked = false;
 #ifndef HAVE_LMDB
        FILE *fp = NULL;
        bool cleanup_config = false;
 #else /* HAVE_LMDB */
        MDB_txn *txn = NULL;
        MDB_dbi dbi;
-       bool locked = false;
 
        UNUSED(zoneconf);
 #endif
@@ -14080,7 +14084,7 @@ cleanup:
        }
        if (result != ISC_R_SUCCESS && cleanup_config) {
                tresult = delete_zoneconf(view, cfg->add_parser,
-                                         cfg->nzf_config, name, NULL);
+                                         cfg->nzf_config, name, NULL, locked);
                RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
        }
 #else  /* HAVE_LMDB */
@@ -14106,13 +14110,13 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
        isc_result_t result, tresult;
        dns_zone_t *zone = NULL;
        bool added;
+       bool locked = false;
 #ifndef HAVE_LMDB
        FILE *fp = NULL;
        cfg_obj_t *z;
 #else  /* HAVE_LMDB */
        MDB_txn *txn = NULL;
        MDB_dbi dbi;
-       bool locked = false;
 #endif /* HAVE_LMDB */
 
        /* Zone must already exist */
@@ -14202,7 +14206,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
        if (added) {
                result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config,
                                         dns_zone_getorigin(zone),
-                                        nzf_writeconf);
+                                        nzf_writeconf, locked);
                if (result != ISC_R_SUCCESS) {
                        TCHECK(putstr(text, "former zone configuration "
                                            "not deleted: "));
@@ -14216,13 +14220,13 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
                if (cfg->vconfig == NULL) {
                        result = delete_zoneconf(
                                view, cfg->conf_parser, cfg->config,
-                               dns_zone_getorigin(zone), NULL);
+                               dns_zone_getorigin(zone), NULL, locked);
                } else {
                        const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig,
                                                                  "options");
                        result = delete_zoneconf(
                                view, cfg->conf_parser, voptions,
-                               dns_zone_getorigin(zone), NULL);
+                               dns_zone_getorigin(zone), NULL, locked);
                }
 
                if (result != ISC_R_SUCCESS) {
@@ -14504,7 +14508,7 @@ rmzone(void *arg) {
 #else  /* ifdef HAVE_LMDB */
                result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config,
                                         dns_zone_getorigin(zone),
-                                        nzf_writeconf);
+                                        nzf_writeconf, false);
                if (result != ISC_R_SUCCESS) {
                        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
@@ -14520,11 +14524,11 @@ rmzone(void *arg) {
                                                                  "options");
                        result = delete_zoneconf(
                                view, cfg->conf_parser, voptions,
-                               dns_zone_getorigin(zone), NULL);
+                               dns_zone_getorigin(zone), NULL, false);
                } else {
                        result = delete_zoneconf(
                                view, cfg->conf_parser, cfg->config,
-                               dns_zone_getorigin(zone), NULL);
+                               dns_zone_getorigin(zone), NULL, false);
                }
                if (result != ISC_R_SUCCESS) {
                        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,