Convert remaining uses of sudo_mkdir_parents() to sudo_open_parent_dir().

This commit is contained in:
Todd C. Miller
2022-09-21 19:08:15 -06:00
parent 376d18b5da
commit 9d654482b2
6 changed files with 39 additions and 25 deletions

View File

@@ -143,7 +143,7 @@ void iolog_set_maxseq(unsigned int maxval);
void iolog_set_mode(mode_t mode); void iolog_set_mode(mode_t mode);
void iolog_set_owner(uid_t uid, uid_t gid); void iolog_set_owner(uid_t uid, uid_t gid);
bool iolog_swapids(bool restore); bool iolog_swapids(bool restore);
bool iolog_mkdirs(char *path); bool iolog_mkdirs(const char *path);
/* iolog_filter.c */ /* iolog_filter.c */
void *iolog_pwfilt_alloc(void); void *iolog_pwfilt_alloc(void);

View File

@@ -1,7 +1,7 @@
/* /*
* SPDX-License-Identifier: ISC * SPDX-License-Identifier: ISC
* *
* Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws> * Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@@ -46,7 +46,7 @@
* Create directory and any parent directories as needed. * Create directory and any parent directories as needed.
*/ */
bool bool
iolog_mkdirs(char *path) iolog_mkdirs(const char *path)
{ {
const mode_t iolog_filemode = iolog_get_file_mode(); const mode_t iolog_filemode = iolog_get_file_mode();
const mode_t iolog_dirmode = iolog_get_dir_mode(); const mode_t iolog_dirmode = iolog_get_dir_mode();
@@ -96,29 +96,33 @@ iolog_mkdirs(char *path)
/* umask must not be more restrictive than the file modes. */ /* umask must not be more restrictive than the file modes. */
omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode)); omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true); ok = false;
if (!ok && errno == EACCES) { if (dfd != -1)
close(dfd);
dfd = sudo_open_parent_dir(path, iolog_uid, iolog_gid, iolog_dirmode, true);
if (dfd == -1 && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */ /* Try again as the I/O log owner (for NFS). */
uid_changed = iolog_swapids(false); uid_changed = iolog_swapids(false);
if (uid_changed) if (uid_changed)
ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false); dfd = sudo_open_parent_dir(path, -1, -1, iolog_dirmode, false);
} }
if (ok) { if (dfd != -1) {
/* Create final path component. */ /* Create final path component. */
const char *base = sudo_basename(path);
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %s, mode 0%o", path, (unsigned int) iolog_dirmode); "mkdir %s, mode 0%o", path, (unsigned int) iolog_dirmode);
ok = mkdir(path, iolog_dirmode) == 0 || errno == EEXIST; ok = mkdirat(dfd, base, iolog_dirmode) == 0 || errno == EEXIST;
if (!ok) { if (!ok) {
if (errno == EACCES && !uid_changed) { if (errno == EACCES && !uid_changed) {
/* Try again as the I/O log owner (for NFS). */ /* Try again as the I/O log owner (for NFS). */
uid_changed = iolog_swapids(false); uid_changed = iolog_swapids(false);
if (uid_changed) if (uid_changed)
ok = mkdir(path, iolog_dirmode) == 0 || errno == EEXIST; ok = mkdirat(dfd, base, iolog_dirmode) == 0 || errno == EEXIST;
} }
if (!ok) if (!ok)
sudo_warn(U_("unable to mkdir %s"), path); sudo_warn(U_("unable to mkdir %s"), path);
} else { } else {
if (chown(path, iolog_uid, iolog_gid) != 0) { if (fchownat(dfd, base, iolog_uid, iolog_gid, AT_SYMLINK_NOFOLLOW) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to chown %d:%d %s", __func__, "%s: unable to chown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, path); (int)iolog_uid, (int)iolog_gid, path);

View File

@@ -52,28 +52,29 @@ iolog_mkdtemp(char *path)
const mode_t iolog_dirmode = iolog_get_dir_mode(); const mode_t iolog_dirmode = iolog_get_dir_mode();
const uid_t iolog_uid = iolog_get_uid(); const uid_t iolog_uid = iolog_get_uid();
const gid_t iolog_gid = iolog_get_gid(); const gid_t iolog_gid = iolog_get_gid();
bool ok, uid_changed = false; bool ok = false, uid_changed = false;
mode_t omask; mode_t omask;
int dfd;
debug_decl(iolog_mkdtemp, SUDO_DEBUG_UTIL); debug_decl(iolog_mkdtemp, SUDO_DEBUG_UTIL);
/* umask must not be more restrictive than the file modes. */ /* umask must not be more restrictive than the file modes. */
omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode)); omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true); dfd = sudo_open_parent_dir(path, iolog_uid, iolog_gid, iolog_dirmode, true);
if (!ok && errno == EACCES) { if (dfd == -1 && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */ /* Try again as the I/O log owner (for NFS). */
uid_changed = iolog_swapids(false); uid_changed = iolog_swapids(false);
if (uid_changed) if (uid_changed)
ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false); dfd = sudo_open_parent_dir(path, -1, -1, iolog_dirmode, false);
} }
if (ok) { if (dfd != -1) {
/* Create final path component. */ /* Create final path component. */
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdtemp %s", path); "mkdtemp %s", path);
/* We cannot retry mkdtemp() so always open as iolog user */ /* We cannot retry mkdtemp() so always open as iolog user */
if (!uid_changed) if (!uid_changed)
uid_changed = iolog_swapids(false); uid_changed = iolog_swapids(false);
if (mkdtemp(path) == NULL) { if (mkdtempat(dfd, path) == NULL) {
sudo_warn(U_("unable to mkdir %s"), path); sudo_warn(U_("unable to mkdir %s"), path);
ok = false; ok = false;
} else { } else {
@@ -82,6 +83,8 @@ iolog_mkdtemp(char *path)
path, (unsigned int)iolog_dirmode); path, (unsigned int)iolog_dirmode);
} }
} }
close(dfd);
ok = true;
} }
umask(omask); umask(omask);

View File

@@ -182,6 +182,7 @@ bad:
/* /*
* Create any parent directories needed by path (but not path itself). * Create any parent directories needed by path (but not path itself).
* Not currently used.
*/ */
bool bool
sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode, sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode,

View File

@@ -1759,8 +1759,7 @@ static void
write_pidfile(void) write_pidfile(void)
{ {
FILE *fp; FILE *fp;
int fd; int dfd, fd;
bool success;
mode_t oldmask; mode_t oldmask;
const char *pid_file = logsrvd_conf_pid_file(); const char *pid_file = logsrvd_conf_pid_file();
debug_decl(write_pidfile, SUDO_DEBUG_UTIL); debug_decl(write_pidfile, SUDO_DEBUG_UTIL);
@@ -1771,10 +1770,11 @@ write_pidfile(void)
/* Default logsrvd umask is more restrictive (077). */ /* Default logsrvd umask is more restrictive (077). */
oldmask = umask(S_IWGRP|S_IWOTH); oldmask = umask(S_IWGRP|S_IWOTH);
success = sudo_mkdir_parents(pid_file, ROOT_UID, ROOT_GID, dfd = sudo_open_parent_dir(pid_file, ROOT_UID, ROOT_GID,
S_IRWXU|S_IXGRP|S_IXOTH, false); S_IRWXU|S_IXGRP|S_IXOTH, false);
if (success) { if (dfd != -1) {
fd = open(pid_file, O_WRONLY|O_CREAT|O_NOFOLLOW, 0644); const char *base = sudo_basename(pid_file);
fd = openat(dfd, base, O_WRONLY|O_CREAT|O_NOFOLLOW, 0644);
if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) { if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {
sudo_warn("%s", pid_file); sudo_warn("%s", pid_file);
if (fd != -1) if (fd != -1)
@@ -1786,6 +1786,7 @@ write_pidfile(void)
sudo_warn("%s", pid_file); sudo_warn("%s", pid_file);
fclose(fp); fclose(fp);
} }
close(dfd);
} }
umask(oldmask); umask(oldmask);

View File

@@ -89,8 +89,9 @@ journal_fdopen(int fd, const char *journal_path,
static int static int
journal_mkstemp(const char *parent_dir, char *pathbuf, int pathlen) journal_mkstemp(const char *parent_dir, char *pathbuf, int pathlen)
{ {
int len, fd = -1; int len, dfd = -1, fd = -1;
mode_t dirmode, oldmask; mode_t dirmode, oldmask;
char *template;
debug_decl(journal_mkstemp, SUDO_DEBUG_UTIL); debug_decl(journal_mkstemp, SUDO_DEBUG_UTIL);
/* umask must not be more restrictive than the file modes. */ /* umask must not be more restrictive than the file modes. */
@@ -109,19 +110,23 @@ journal_mkstemp(const char *parent_dir, char *pathbuf, int pathlen)
RELAY_TEMPLATE); RELAY_TEMPLATE);
goto done; goto done;
} }
if (!sudo_mkdir_parents(pathbuf, logsrvd_conf_iolog_uid(), dfd = sudo_open_parent_dir(pathbuf, logsrvd_conf_iolog_uid(),
logsrvd_conf_iolog_gid(), S_IRWXU|S_IXGRP|S_IXOTH, false)) { logsrvd_conf_iolog_gid(), S_IRWXU|S_IXGRP|S_IXOTH, false);
if (dfd == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to create parent dir for %s", pathbuf); "unable to create parent dir for %s", pathbuf);
goto done; goto done;
} }
if ((fd = mkstemp(pathbuf)) == -1) { template = pathbuf + (len - strlen(RELAY_TEMPLATE));
if ((fd = mkostempsat(dfd, template, 0, 0)) == -1) {
sudo_warn(U_("%s: %s"), "mkstemp", pathbuf); sudo_warn(U_("%s: %s"), "mkstemp", pathbuf);
goto done; goto done;
} }
done: done:
umask(oldmask); umask(oldmask);
if (dfd != -1)
close(dfd);
debug_return_int(fd); debug_return_int(fd);
} }