From: Ondřej Surý Date: Wed, 29 Apr 2026 15:49:46 +0000 (+0200) Subject: Stop nzd_env_close from chowning through symlinks X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=63d30566bb8be8a49dd5320c3be6bc037ec9d399;p=thirdparty%2Fbind9.git Stop nzd_env_close from chowning through symlinks When named is running as root, nzd_env_close() chowns the per-view NZD database file to the unprivileged user that named will drop to. The call used chown(), which follows symlinks, so a symlink at the NZD path would silently transfer ownership of whatever the link pointed at instead of the database file itself. Switch to lstat() + S_ISREG() + lchown() so the chown only fires when the path is a regular file and never traverses a symlink even if one is planted between the lstat and the lchown. Assisted-by: Claude:claude-opus-4-7 --- diff --git a/bin/named/nzd.c b/bin/named/nzd.c index fe8e4d24c58..af1820d86ad 100644 --- a/bin/named/nzd.c +++ b/bin/named/nzd.c @@ -12,6 +12,8 @@ */ #include +#include +#include #include @@ -235,6 +237,7 @@ nzd_env_close(dns_view_t *view) { const char *dbpath = NULL; char dbpath_copy[PATH_MAX]; char lockpath[PATH_MAX]; + struct stat sb; int status, ret; if (view->newzone.dbenv == NULL) { @@ -249,9 +252,13 @@ nzd_env_close(dns_view_t *view) { /* * Database files must be owned by the eventual user, not by root. + * Use lstat()/S_ISREG/lchown() so a symlink at the path cannot + * redirect the chown to an unrelated file. */ - ret = chown(dbpath_copy, named_os_uid(), -1); - UNUSED(ret); + if (lstat(dbpath_copy, &sb) == 0 && S_ISREG(sb.st_mode)) { + ret = lchown(dbpath_copy, named_os_uid(), -1); + UNUSED(ret); + } /* * Some platforms need the lockfile not to exist when we reopen the