summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sudo_iolog.h2
-rw-r--r--lib/iolog/iolog_mkdirs.c22
-rw-r--r--lib/iolog/iolog_mkdtemp.c15
-rw-r--r--lib/util/mkdir_parents.c1
-rw-r--r--logsrvd/logsrvd.c11
-rw-r--r--logsrvd/logsrvd_journal.c13
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);
}