diff options
-rw-r--r-- | include/sudo_iolog.h | 2 | ||||
-rw-r--r-- | lib/iolog/iolog_mkdirs.c | 22 | ||||
-rw-r--r-- | lib/iolog/iolog_mkdtemp.c | 15 | ||||
-rw-r--r-- | lib/util/mkdir_parents.c | 1 | ||||
-rw-r--r-- | logsrvd/logsrvd.c | 11 | ||||
-rw-r--r-- | logsrvd/logsrvd_journal.c | 13 |
6 files changed, 39 insertions, 25 deletions
diff --git a/include/sudo_iolog.h b/include/sudo_iolog.h index 90aa2099b..599424184 100644 --- a/include/sudo_iolog.h +++ b/include/sudo_iolog.h @@ -143,7 +143,7 @@ void iolog_set_maxseq(unsigned int maxval); void iolog_set_mode(mode_t mode); void iolog_set_owner(uid_t uid, uid_t gid); bool iolog_swapids(bool restore); -bool iolog_mkdirs(char *path); +bool iolog_mkdirs(const char *path); /* iolog_filter.c */ void *iolog_pwfilt_alloc(void); diff --git a/lib/iolog/iolog_mkdirs.c b/lib/iolog/iolog_mkdirs.c index baa9eba00..c9ab980c4 100644 --- a/lib/iolog/iolog_mkdirs.c +++ b/lib/iolog/iolog_mkdirs.c @@ -1,7 +1,7 @@ /* * 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 * purpose with or without fee is hereby granted, provided that the above @@ -46,7 +46,7 @@ * Create directory and any parent directories as needed. */ bool -iolog_mkdirs(char *path) +iolog_mkdirs(const char *path) { const mode_t iolog_filemode = iolog_get_file_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. */ omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode)); - ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true); - if (!ok && errno == EACCES) { + ok = false; + 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). */ uid_changed = iolog_swapids(false); 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. */ + const char *base = sudo_basename(path); sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "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 (errno == EACCES && !uid_changed) { /* Try again as the I/O log owner (for NFS). */ uid_changed = iolog_swapids(false); if (uid_changed) - ok = mkdir(path, iolog_dirmode) == 0 || errno == EEXIST; + ok = mkdirat(dfd, base, iolog_dirmode) == 0 || errno == EEXIST; } if (!ok) sudo_warn(U_("unable to mkdir %s"), path); } 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, "%s: unable to chown %d:%d %s", __func__, (int)iolog_uid, (int)iolog_gid, path); diff --git a/lib/iolog/iolog_mkdtemp.c b/lib/iolog/iolog_mkdtemp.c index e7904e312..948fdcd3e 100644 --- a/lib/iolog/iolog_mkdtemp.c +++ b/lib/iolog/iolog_mkdtemp.c @@ -52,28 +52,29 @@ iolog_mkdtemp(char *path) const mode_t iolog_dirmode = iolog_get_dir_mode(); const uid_t iolog_uid = iolog_get_uid(); const gid_t iolog_gid = iolog_get_gid(); - bool ok, uid_changed = false; + bool ok = false, uid_changed = false; mode_t omask; + int dfd; debug_decl(iolog_mkdtemp, SUDO_DEBUG_UTIL); /* umask must not be more restrictive than the file modes. */ omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode)); - ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true); - if (!ok && errno == EACCES) { + 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). */ uid_changed = iolog_swapids(false); 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. */ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO, "mkdtemp %s", path); /* We cannot retry mkdtemp() so always open as iolog user */ if (!uid_changed) uid_changed = iolog_swapids(false); - if (mkdtemp(path) == NULL) { + if (mkdtempat(dfd, path) == NULL) { sudo_warn(U_("unable to mkdir %s"), path); ok = false; } else { @@ -82,6 +83,8 @@ iolog_mkdtemp(char *path) path, (unsigned int)iolog_dirmode); } } + close(dfd); + ok = true; } umask(omask); diff --git a/lib/util/mkdir_parents.c b/lib/util/mkdir_parents.c index 6868cc09a..755ff50d3 100644 --- a/lib/util/mkdir_parents.c +++ b/lib/util/mkdir_parents.c @@ -182,6 +182,7 @@ bad: /* * Create any parent directories needed by path (but not path itself). + * Not currently used. */ bool sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode, diff --git a/logsrvd/logsrvd.c b/logsrvd/logsrvd.c index bd8191bab..7c66defc6 100644 --- a/logsrvd/logsrvd.c +++ b/logsrvd/logsrvd.c @@ -1759,8 +1759,7 @@ static void write_pidfile(void) { FILE *fp; - int fd; - bool success; + int dfd, fd; mode_t oldmask; const char *pid_file = logsrvd_conf_pid_file(); debug_decl(write_pidfile, SUDO_DEBUG_UTIL); @@ -1771,10 +1770,11 @@ write_pidfile(void) /* Default logsrvd umask is more restrictive (077). */ 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); - if (success) { - fd = open(pid_file, O_WRONLY|O_CREAT|O_NOFOLLOW, 0644); + if (dfd != -1) { + 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) { sudo_warn("%s", pid_file); if (fd != -1) @@ -1786,6 +1786,7 @@ write_pidfile(void) sudo_warn("%s", pid_file); fclose(fp); } + close(dfd); } umask(oldmask); diff --git a/logsrvd/logsrvd_journal.c b/logsrvd/logsrvd_journal.c index c9e804fe5..831610cfa 100644 --- a/logsrvd/logsrvd_journal.c +++ b/logsrvd/logsrvd_journal.c @@ -89,8 +89,9 @@ journal_fdopen(int fd, const char *journal_path, static int journal_mkstemp(const char *parent_dir, char *pathbuf, int pathlen) { - int len, fd = -1; + int len, dfd = -1, fd = -1; mode_t dirmode, oldmask; + char *template; debug_decl(journal_mkstemp, SUDO_DEBUG_UTIL); /* 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); goto done; } - if (!sudo_mkdir_parents(pathbuf, logsrvd_conf_iolog_uid(), - logsrvd_conf_iolog_gid(), S_IRWXU|S_IXGRP|S_IXOTH, false)) { + dfd = sudo_open_parent_dir(pathbuf, logsrvd_conf_iolog_uid(), + 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, "unable to create parent dir for %s", pathbuf); 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); goto done; } done: umask(oldmask); + if (dfd != -1) + close(dfd); debug_return_int(fd); } |