2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 05:28:00 +00:00

Delay release of root privileges until after configuring controls

On systems where root access is needed to configure privileged
ports, we don't want to fully relinquish root privileges until
after the control channel (which typically runs on port 953) has
been established.

named_os_changeuser() now takes a boolean argument 'permanent'.
This allows us to switch the effective userid temporarily with
named_os_changeuser(false) and restore it with named_os_restoreuser(),
before permanently dropping privileges with named_os_changeuser(true).
This commit is contained in:
Evan Hunt 2024-07-02 23:40:54 -07:00
parent 9afcdc2b18
commit d57fa148af
3 changed files with 52 additions and 14 deletions

View File

@ -39,10 +39,13 @@ void
named_os_inituserinfo(const char *username);
void
named_os_changeuser(void);
named_os_changeuser(bool permanent);
void
named_os_restoreuser(void);
uid_t
ns_os_uid(void);
named_os_uid(void);
void
named_os_adjustnofile(void);

View File

@ -61,6 +61,9 @@ static struct passwd *runas_pw = NULL;
static bool done_setuid = false;
static int dfd[2] = { -1, -1 };
static uid_t saved_uid = (uid_t)-1;
static gid_t saved_gid = (gid_t)-1;
#if HAVE_LIBCAP
static bool non_root = false;
@ -461,12 +464,33 @@ named_os_inituserinfo(const char *username) {
}
void
named_os_changeuser(void) {
named_os_restoreuser(void) {
if (runas_pw == NULL || done_setuid) {
return;
}
REQUIRE(saved_uid != (uid_t)-1);
REQUIRE(saved_gid != (gid_t)-1);
setperms(saved_uid, saved_gid);
}
void
named_os_changeuser(bool permanent) {
char strbuf[ISC_STRERRORSIZE];
if (runas_pw == NULL || done_setuid) {
return;
}
if (!permanent) {
saved_uid = getuid();
saved_gid = getgid();
setperms(runas_pw->pw_uid, runas_pw->pw_gid);
return;
}
done_setuid = true;
if (setgid(runas_pw->pw_gid) == -1) {
@ -495,7 +519,7 @@ named_os_changeuser(void) {
}
uid_t
ns_os_uid(void) {
named_os_uid(void) {
if (runas_pw == NULL) {
return (0);
}
@ -551,7 +575,7 @@ void
named_os_minprivs(void) {
#if HAVE_LIBCAP
linux_keepcaps();
named_os_changeuser();
named_os_changeuser(true);
linux_minprivs();
#endif /* HAVE_LIBCAP */
}
@ -678,19 +702,16 @@ named_os_openfile(const char *filename, mode_t mode, bool switch_user) {
free(f);
if (switch_user && runas_pw != NULL) {
uid_t olduid = getuid();
gid_t oldgid = getgid();
/*
* Set UID/GID to the one we'll be running with
* Temporarily set UID/GID to the one we'll be running with
* eventually.
*/
setperms(runas_pw->pw_uid, runas_pw->pw_gid);
named_os_changeuser(false);
fd = safe_open(filename, mode, false);
/* Restore UID/GID to previous uid/gid */
setperms(olduid, oldgid);
named_os_restoreuser();
if (fd == -1) {
fd = safe_open(filename, mode, false);

View File

@ -9370,10 +9370,12 @@ load_configuration(const char *filename, named_server_t *server,
#endif /* HAVE_LMDB */
/*
* Relinquish root privileges.
* Switch to the effective UID for setting up files.
* Later, after configuring all the listening ports,
* we'll relinquish root privileges permanently.
*/
if (first_time) {
named_os_changeuser();
named_os_changeuser(false);
}
/*
@ -9719,6 +9721,11 @@ load_configuration(const char *filename, named_server_t *server,
isc_loopmgr_resume(named_g_loopmgr);
exclusive = false;
/* Take back root privileges temporarily */
if (first_time) {
named_os_restoreuser();
}
/* Configure the statistics channel(s) */
result = named_statschannels_configure(named_g_server, config,
named_g_aclconfctx);
@ -9744,6 +9751,13 @@ load_configuration(const char *filename, named_server_t *server,
(void)ns_interfacemgr_scan(server->interfacemgr, true, true);
/*
* Permanently drop root privileges now.
*/
if (first_time) {
named_os_changeuser(true);
}
/*
* These cleans up either the old production view list
* or our temporary list depending on whether they
@ -13258,7 +13272,7 @@ nzd_env_close(dns_view_t *view) {
/*
* Database files must be owned by the eventual user, not by root.
*/
ret = chown(dbpath_copy, ns_os_uid(), -1);
ret = chown(dbpath_copy, named_os_uid(), -1);
UNUSED(ret);
/*