mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-02 15:45:25 +00:00
[master] prevent reload failure due to LMDB database perms
4638. [bug] Reloading or reconfiguring named could fail on some platforms when LMDB was in use. [RT #45203]
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -1,3 +1,6 @@
|
|||||||
|
4638. [bug] Reloading or reconfiguring named could fail on
|
||||||
|
some platforms when LMDB was in use. [RT #45203]
|
||||||
|
|
||||||
4637. [func] "nsec3hash -r" option ("rdata order") takes arguments
|
4637. [func] "nsec3hash -r" option ("rdata order") takes arguments
|
||||||
in the same order as they appear in NSEC3 or
|
in the same order as they appear in NSEC3 or
|
||||||
NSEC3PARAM records, so that NSEC3 parameters can
|
NSEC3PARAM records, so that NSEC3 parameters can
|
||||||
|
@@ -484,6 +484,12 @@ nzd_writable(dns_view_t *view);
|
|||||||
static isc_result_t
|
static isc_result_t
|
||||||
nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi);
|
nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi);
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
nzd_env_reopen(dns_view_t *view);
|
||||||
|
|
||||||
|
static void
|
||||||
|
nzd_env_close(dns_view_t *view);
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
nzd_close(MDB_txn **txnp, isc_boolean_t commit);
|
nzd_close(MDB_txn **txnp, isc_boolean_t commit);
|
||||||
|
|
||||||
@@ -6727,12 +6733,21 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
|
|||||||
return (ISC_R_NOMEMORY);
|
return (ISC_R_NOMEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We attach the parser that was used for config as well
|
||||||
|
* as the one that will be used for added zones, to avoid
|
||||||
|
* a shutdown race later.
|
||||||
|
*/
|
||||||
memset(nzcfg, 0, sizeof(*nzcfg));
|
memset(nzcfg, 0, sizeof(*nzcfg));
|
||||||
|
cfg_parser_attach(conf_parser, &nzcfg->conf_parser);
|
||||||
|
cfg_parser_attach(ns_g_addparser, &nzcfg->add_parser);
|
||||||
|
isc_mem_attach(view->mctx, &nzcfg->mctx);
|
||||||
|
cfg_aclconfctx_attach(actx, &nzcfg->actx);
|
||||||
|
|
||||||
result = dns_view_setnewzones(view, ISC_TRUE, nzcfg,
|
result = dns_view_setnewzones(view, ISC_TRUE, nzcfg,
|
||||||
newzone_cfgctx_destroy, mapsize);
|
newzone_cfgctx_destroy, mapsize);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
isc_mem_put(view->mctx, nzcfg, sizeof(*nzcfg));
|
dns_view_setnewzones(view, ISC_FALSE, NULL, NULL, 0ULL);
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6740,16 +6755,6 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
|
|||||||
if (vconfig != NULL)
|
if (vconfig != NULL)
|
||||||
cfg_obj_attach(vconfig, &nzcfg->vconfig);
|
cfg_obj_attach(vconfig, &nzcfg->vconfig);
|
||||||
|
|
||||||
/*
|
|
||||||
* We attach the parser that was used for config as well
|
|
||||||
* as the one that will be used for added zones, to avoid
|
|
||||||
* a shutdown race later.
|
|
||||||
*/
|
|
||||||
cfg_parser_attach(conf_parser, &nzcfg->conf_parser);
|
|
||||||
cfg_parser_attach(ns_g_addparser, &nzcfg->add_parser);
|
|
||||||
isc_mem_attach(view->mctx, &nzcfg->mctx);
|
|
||||||
cfg_aclconfctx_attach(actx, &nzcfg->actx);
|
|
||||||
|
|
||||||
result = count_newzones(view, nzcfg, num_zones);
|
result = count_newzones(view, nzcfg, num_zones);
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@@ -7936,6 +7941,21 @@ load_configuration(const char *filename, ns_server_t *server,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're using LMDB, we may have created newzones databases
|
||||||
|
* as root, making it impossible to reopen them later after
|
||||||
|
* switching to a new userid. We close them now, and reopen
|
||||||
|
* after relinquishing privileges them.
|
||||||
|
*/
|
||||||
|
if (first_time) {
|
||||||
|
for (view = ISC_LIST_HEAD(server->viewlist);
|
||||||
|
view != NULL;
|
||||||
|
view = ISC_LIST_NEXT(view, link))
|
||||||
|
{
|
||||||
|
nzd_env_close(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Relinquish root privileges.
|
* Relinquish root privileges.
|
||||||
*/
|
*/
|
||||||
@@ -7951,6 +7971,20 @@ load_configuration(const char *filename, ns_server_t *server,
|
|||||||
"the working directory is not writable");
|
"the working directory is not writable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LMDB
|
||||||
|
/*
|
||||||
|
* Reopen NZD databases.
|
||||||
|
*/
|
||||||
|
if (first_time) {
|
||||||
|
for (view = ISC_LIST_HEAD(server->viewlist);
|
||||||
|
view != NULL;
|
||||||
|
view = ISC_LIST_NEXT(view, link))
|
||||||
|
{
|
||||||
|
nzd_env_reopen(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LMDB */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure the logging system.
|
* Configure the logging system.
|
||||||
*
|
*
|
||||||
@@ -11317,6 +11351,93 @@ nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) {
|
|||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nzd_env_close() and nzd_env_reopen are a kluge to address the
|
||||||
|
* problem of an NZD file possibly being created before we drop
|
||||||
|
* root privileges.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
nzd_env_close(dns_view_t *view) {
|
||||||
|
if (view->new_zone_dbenv != NULL) {
|
||||||
|
const char *dbpath = NULL;
|
||||||
|
char lockpath[PATH_MAX];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (mdb_env_get_path(view->new_zone_dbenv, &dbpath) == 0) {
|
||||||
|
snprintf(lockpath, sizeof(lockpath), "%s-lock",
|
||||||
|
dbpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
mdb_env_close((MDB_env *) view->new_zone_dbenv);
|
||||||
|
view->new_zone_dbenv = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Database files must be owned by the eventual user, not
|
||||||
|
* by root.
|
||||||
|
*/
|
||||||
|
ret = chown(dbpath, ns_os_uid(), -1);
|
||||||
|
UNUSED(ret);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some platforms need the lockfile not to exist when we
|
||||||
|
* reopen the environment.
|
||||||
|
*/
|
||||||
|
(void) isc_file_remove(lockpath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
nzd_env_reopen(dns_view_t *view) {
|
||||||
|
isc_result_t result;
|
||||||
|
MDB_env *env = NULL;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if (view->new_zone_db == NULL) {
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
nzd_env_close(view);
|
||||||
|
|
||||||
|
status = mdb_env_create(&env);
|
||||||
|
if (status != 0) {
|
||||||
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||||
|
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
|
||||||
|
"mdb_env_create failed: %s",
|
||||||
|
mdb_strerror(status));
|
||||||
|
CHECK(ISC_R_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (view->new_zone_mapsize != 0ULL) {
|
||||||
|
status = mdb_env_set_mapsize(env, view->new_zone_mapsize);
|
||||||
|
if (status != 0) {
|
||||||
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||||
|
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
|
||||||
|
"mdb_env_set_mapsize failed: %s",
|
||||||
|
mdb_strerror(status));
|
||||||
|
CHECK(ISC_R_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status = mdb_env_open(env, view->new_zone_db,
|
||||||
|
MDB_NOSUBDIR|MDB_CREATE, 0600);
|
||||||
|
if (status != 0) {
|
||||||
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||||
|
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
|
||||||
|
"mdb_env_open of '%s' failed: %s",
|
||||||
|
view->new_zone_db, mdb_strerror(status));
|
||||||
|
CHECK(ISC_R_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
view->new_zone_dbenv = env;
|
||||||
|
env = NULL;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (env != NULL) {
|
||||||
|
mdb_env_close(env);
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
nzd_close(MDB_txn **txnp, isc_boolean_t commit) {
|
nzd_close(MDB_txn **txnp, isc_boolean_t commit) {
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
@@ -12659,7 +12780,6 @@ ns_server_showzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) {
|
|||||||
static void
|
static void
|
||||||
newzone_cfgctx_destroy(void **cfgp) {
|
newzone_cfgctx_destroy(void **cfgp) {
|
||||||
ns_cfgctx_t *cfg;
|
ns_cfgctx_t *cfg;
|
||||||
isc_mem_t *mctx;
|
|
||||||
|
|
||||||
REQUIRE(cfgp != NULL && *cfgp != NULL);
|
REQUIRE(cfgp != NULL && *cfgp != NULL);
|
||||||
|
|
||||||
@@ -12681,8 +12801,7 @@ newzone_cfgctx_destroy(void **cfgp) {
|
|||||||
if (cfg->actx != NULL)
|
if (cfg->actx != NULL)
|
||||||
cfg_aclconfctx_detach(&cfg->actx);
|
cfg_aclconfctx_detach(&cfg->actx);
|
||||||
|
|
||||||
mctx = cfg->mctx;
|
isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg));
|
||||||
isc_mem_putanddetach(&mctx, cfg, sizeof(*cfg));
|
|
||||||
*cfgp = NULL;
|
*cfgp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
/*! \file */
|
/*! \file */
|
||||||
|
|
||||||
|
#include <pwd.h>
|
||||||
|
|
||||||
#include <isc/types.h>
|
#include <isc/types.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -34,6 +36,9 @@ ns_os_inituserinfo(const char *username);
|
|||||||
void
|
void
|
||||||
ns_os_changeuser(void);
|
ns_os_changeuser(void);
|
||||||
|
|
||||||
|
uid_t
|
||||||
|
ns_os_uid(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
ns_os_adjustnofile(void);
|
ns_os_adjustnofile(void);
|
||||||
|
|
||||||
|
@@ -601,6 +601,13 @@ ns_os_changeuser(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uid_t
|
||||||
|
ns_os_uid(void) {
|
||||||
|
if (runas_pw == NULL)
|
||||||
|
return (0);
|
||||||
|
return (runas_pw->pw_uid);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ns_os_adjustnofile(void) {
|
ns_os_adjustnofile(void) {
|
||||||
#ifdef HAVE_LINUXTHREADS
|
#ifdef HAVE_LINUXTHREADS
|
||||||
|
@@ -32,6 +32,9 @@ ns_os_inituserinfo(const char *username);
|
|||||||
void
|
void
|
||||||
ns_os_changeuser(void);
|
ns_os_changeuser(void);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
ns_os_uid(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
ns_os_adjustnofile(void);
|
ns_os_adjustnofile(void);
|
||||||
|
|
||||||
|
@@ -163,6 +163,11 @@ void
|
|||||||
ns_os_changeuser(void) {
|
ns_os_changeuser(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
ns_os_uid(void) {
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ns_os_adjustnofile(void) {
|
ns_os_adjustnofile(void) {
|
||||||
}
|
}
|
||||||
|
@@ -412,6 +412,12 @@
|
|||||||
|
|
||||||
<section xml:id="relnotes_bugs"><info><title>Bug Fixes</title></info>
|
<section xml:id="relnotes_bugs"><info><title>Bug Fixes</title></info>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Reloading or reconfiguring <command>named</command> could
|
||||||
|
fail on some platforms when LMDB was in use. [RT #45203]
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Due to some incorrectly deleted code, when BIND was
|
Due to some incorrectly deleted code, when BIND was
|
||||||
@@ -422,7 +428,6 @@
|
|||||||
server restart. This has been corrected. [RT #45185]
|
server restart. This has been corrected. [RT #45185]
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Semicolons are no longer escaped when printing CAA and
|
Semicolons are no longer escaped when printing CAA and
|
||||||
|
@@ -212,6 +212,7 @@ struct dns_view {
|
|||||||
char * new_zone_file;
|
char * new_zone_file;
|
||||||
char * new_zone_db;
|
char * new_zone_db;
|
||||||
void * new_zone_dbenv;
|
void * new_zone_dbenv;
|
||||||
|
isc_uint64_t new_zone_mapsize;
|
||||||
void * new_zone_config;
|
void * new_zone_config;
|
||||||
void (*cfg_destroy)(void **);
|
void (*cfg_destroy)(void **);
|
||||||
isc_mutex_t new_zone_lock;
|
isc_mutex_t new_zone_lock;
|
||||||
|
@@ -236,6 +236,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
|||||||
view->new_zone_file = NULL;
|
view->new_zone_file = NULL;
|
||||||
view->new_zone_db = NULL;
|
view->new_zone_db = NULL;
|
||||||
view->new_zone_dbenv = NULL;
|
view->new_zone_dbenv = NULL;
|
||||||
|
view->new_zone_mapsize = 0ULL;
|
||||||
view->new_zone_config = NULL;
|
view->new_zone_config = NULL;
|
||||||
view->cfg_destroy = NULL;
|
view->cfg_destroy = NULL;
|
||||||
view->fail_ttl = 0;
|
view->fail_ttl = 0;
|
||||||
@@ -2038,7 +2039,7 @@ isc_result_t
|
|||||||
dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
|
dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
|
||||||
void (*cfg_destroy)(void **), isc_uint64_t mapsize)
|
void (*cfg_destroy)(void **), isc_uint64_t mapsize)
|
||||||
{
|
{
|
||||||
isc_result_t result;
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
#ifdef HAVE_LMDB
|
#ifdef HAVE_LMDB
|
||||||
MDB_env *env = NULL;
|
MDB_env *env = NULL;
|
||||||
@@ -2078,27 +2079,21 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
|
|||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = nz_legacy(view->new_zone_dir, view->name, "nzf",
|
CHECK(nz_legacy(view->new_zone_dir, view->name, "nzf",
|
||||||
buffer, sizeof(buffer));
|
buffer, sizeof(buffer)));
|
||||||
if (result != ISC_R_SUCCESS)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
view->new_zone_file = isc_mem_strdup(view->mctx, buffer);
|
view->new_zone_file = isc_mem_strdup(view->mctx, buffer);
|
||||||
if (view->new_zone_file == NULL) {
|
if (view->new_zone_file == NULL) {
|
||||||
result = ISC_R_NOMEMORY;
|
CHECK(ISC_R_NOMEMORY);
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LMDB
|
#ifdef HAVE_LMDB
|
||||||
result = nz_legacy(view->new_zone_dir, view->name, "nzd",
|
CHECK(nz_legacy(view->new_zone_dir, view->name, "nzd",
|
||||||
buffer, sizeof(buffer));
|
buffer, sizeof(buffer)));
|
||||||
if (result != ISC_R_SUCCESS)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
view->new_zone_db = isc_mem_strdup(view->mctx, buffer);
|
view->new_zone_db = isc_mem_strdup(view->mctx, buffer);
|
||||||
if (view->new_zone_db == NULL) {
|
if (view->new_zone_db == NULL) {
|
||||||
result = ISC_R_NOMEMORY;
|
CHECK(ISC_R_NOMEMORY);
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status = mdb_env_create(&env);
|
status = mdb_env_create(&env);
|
||||||
@@ -2107,19 +2102,18 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
|
|||||||
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
|
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
|
||||||
"mdb_env_create failed: %s",
|
"mdb_env_create failed: %s",
|
||||||
mdb_strerror(status));
|
mdb_strerror(status));
|
||||||
result = ISC_R_FAILURE;
|
CHECK(ISC_R_FAILURE);
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapsize != 0ULL) {
|
if (mapsize != 0ULL) {
|
||||||
status = mdb_env_set_mapsize(env, mapsize);
|
status = mdb_env_set_mapsize(env, mapsize);
|
||||||
|
view->new_zone_mapsize = mapsize;
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||||
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
|
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
|
||||||
"mdb_env_set_mapsize failed: %s",
|
"mdb_env_set_mapsize failed: %s",
|
||||||
mdb_strerror(status));
|
mdb_strerror(status));
|
||||||
result = ISC_R_FAILURE;
|
CHECK(ISC_R_FAILURE);
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2130,8 +2124,7 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
|
|||||||
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
|
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
|
||||||
"mdb_env_open of '%s' failed: %s",
|
"mdb_env_open of '%s' failed: %s",
|
||||||
view->new_zone_db, mdb_strerror(status));
|
view->new_zone_db, mdb_strerror(status));
|
||||||
result = ISC_R_FAILURE;
|
CHECK(ISC_R_FAILURE);
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
view->new_zone_dbenv = env;
|
view->new_zone_dbenv = env;
|
||||||
@@ -2141,7 +2134,7 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
|
|||||||
view->new_zone_config = cfgctx;
|
view->new_zone_config = cfgctx;
|
||||||
view->cfg_destroy = cfg_destroy;
|
view->cfg_destroy = cfg_destroy;
|
||||||
|
|
||||||
out:
|
cleanup:
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
if (view->new_zone_file != NULL) {
|
if (view->new_zone_file != NULL) {
|
||||||
isc_mem_free(view->mctx, view->new_zone_file);
|
isc_mem_free(view->mctx, view->new_zone_file);
|
||||||
|
Reference in New Issue
Block a user