From d51d4af7a6150daf9d839a0f54e53ada2833786d Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Fri, 26 Feb 2021 15:02:58 -0700 Subject: [PATCH] Break out I/O log config handling into iolog_conf.c. --- MANIFEST | 1 + include/sudo_iolog.h | 8 +- lib/iolog/Makefile.in | 41 +++++--- lib/iolog/iolog_conf.c | 202 ++++++++++++++++++++++++++++++++++++++ lib/iolog/iolog_fileio.c | 162 +++++------------------------- lib/iolog/iolog_loginfo.c | 10 +- 6 files changed, 266 insertions(+), 158 deletions(-) create mode 100644 lib/iolog/iolog_conf.c diff --git a/MANIFEST b/MANIFEST index 66663d779..36110a735 100644 --- a/MANIFEST +++ b/MANIFEST @@ -115,6 +115,7 @@ lib/fuzzstub/fuzzstub.c lib/iolog/Makefile.in lib/iolog/host_port.c lib/iolog/hostcheck.c +lib/iolog/iolog_conf.c lib/iolog/iolog_fileio.c lib/iolog/iolog_json.c lib/iolog/iolog_json.h diff --git a/include/sudo_iolog.h b/include/sudo_iolog.h index 9e337df43..fbcc6e7a3 100644 --- a/include/sudo_iolog.h +++ b/include/sudo_iolog.h @@ -121,9 +121,15 @@ int iolog_openat(int fdf, const char *path, int flags); off_t iolog_seek(struct iolog_file *iol, off_t offset, int whence); ssize_t iolog_read(struct iolog_file *iol, void *buf, size_t nbytes, const char **errstr); ssize_t iolog_write(struct iolog_file *iol, const void *buf, size_t len, const char **errstr); -int iolog_fchown(int fd); void iolog_clearerr(struct iolog_file *iol); void iolog_rewind(struct iolog_file *iol); +unsigned int iolog_get_maxseq(void); +uid_t iolog_get_uid(void); +gid_t iolog_get_gid(void); +mode_t iolog_get_file_mode(void); +mode_t iolog_get_dir_mode(void); +bool iolog_get_compress(void); +bool iolog_get_flush(void); void iolog_set_compress(bool); void iolog_set_defaults(void); void iolog_set_flush(bool); diff --git a/lib/iolog/Makefile.in b/lib/iolog/Makefile.in index a0b1f8a30..968340a5c 100644 --- a/lib/iolog/Makefile.in +++ b/lib/iolog/Makefile.in @@ -95,14 +95,15 @@ DEVEL = @DEVEL@ SHELL = @SHELL@ -LIBIOLOG_OBJS = iolog_fileio.lo iolog_json.lo iolog_legacy.lo iolog_loginfo.lo \ - iolog_path.lo iolog_timing.lo host_port.lo hostcheck.lo +LIBIOLOG_OBJS = iolog_conf.lo iolog_fileio.lo iolog_json.lo iolog_legacy.lo \ + iolog_loginfo.lo iolog_path.lo iolog_timing.lo host_port.lo \ + hostcheck.lo IOBJS = $(LIBIOLOG_OBJS:.lo=.i) POBJS = $(IOBJS:.i=.plog) -CHECK_IOLOG_MKPATH_OBJS = check_iolog_mkpath.lo iolog_fileio.lo +CHECK_IOLOG_MKPATH_OBJS = check_iolog_mkpath.lo iolog_conf.lo iolog_fileio.lo CHECK_IOLOG_PATH_OBJS = check_iolog_path.lo iolog_path.lo @@ -424,23 +425,33 @@ hostcheck.i: $(srcdir)/hostcheck.c $(incdir)/compat/stdbool.h \ $(CC) -E -o $@ $(CPPFLAGS) $< hostcheck.plog: hostcheck.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/hostcheck.c --i-file $< --output-file $@ +iolog_conf.lo: $(srcdir)/iolog_conf.c $(incdir)/compat/stdbool.h \ + $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ + $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \ + $(incdir)/sudo_util.h $(top_builddir)/config.h \ + $(top_builddir)/pathnames.h + $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_conf.c +iolog_conf.i: $(srcdir)/iolog_conf.c $(incdir)/compat/stdbool.h \ + $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ + $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \ + $(incdir)/sudo_util.h $(top_builddir)/config.h \ + $(top_builddir)/pathnames.h + $(CC) -E -o $@ $(CPPFLAGS) $< +iolog_conf.plog: iolog_conf.i + rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_conf.c --i-file $< --output-file $@ iolog_fileio.lo: $(srcdir)/iolog_fileio.c $(incdir)/compat/stdbool.h \ - $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \ - $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \ + $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \ - $(incdir)/sudo_iolog.h $(incdir)/sudo_json.h \ - $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \ - $(incdir)/sudo_util.h $(top_builddir)/config.h \ - $(top_builddir)/pathnames.h + $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \ + $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \ + $(top_builddir)/config.h $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_fileio.c iolog_fileio.i: $(srcdir)/iolog_fileio.c $(incdir)/compat/stdbool.h \ - $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \ - $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \ + $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \ - $(incdir)/sudo_iolog.h $(incdir)/sudo_json.h \ - $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \ - $(incdir)/sudo_util.h $(top_builddir)/config.h \ - $(top_builddir)/pathnames.h + $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \ + $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \ + $(top_builddir)/config.h $(CC) -E -o $@ $(CPPFLAGS) $< iolog_fileio.plog: iolog_fileio.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_fileio.c --i-file $< --output-file $@ diff --git a/lib/iolog/iolog_conf.c b/lib/iolog/iolog_conf.c new file mode 100644 index 000000000..58e893c15 --- /dev/null +++ b/lib/iolog/iolog_conf.c @@ -0,0 +1,202 @@ +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2009-2021 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This is an open source non-commercial project. Dear PVS-Studio, please check it. + * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + */ + +#include + +#include +#include +#include +#include +#ifdef HAVE_STDBOOL_H +# include +#else +# include "compat/stdbool.h" +#endif + +#include "pathnames.h" +#include "sudo_compat.h" +#include "sudo_debug.h" +#include "sudo_util.h" +#include "sudo_iolog.h" + +static unsigned int sessid_max = SESSID_MAX; +static mode_t iolog_filemode = S_IRUSR|S_IWUSR; +static mode_t iolog_dirmode = S_IRWXU; +static uid_t iolog_uid = ROOT_UID; +static gid_t iolog_gid = ROOT_GID; +static bool iolog_gid_set; +static bool iolog_compress; +static bool iolog_flush; + +/* + * Reset I/O log settings to default values. + */ +void +iolog_set_defaults(void) +{ + sessid_max = SESSID_MAX; + iolog_filemode = S_IRUSR|S_IWUSR; + iolog_dirmode = S_IRWXU; + iolog_uid = ROOT_UID; + iolog_gid = ROOT_GID; + iolog_gid_set = false; + iolog_compress = false; + iolog_flush = false; +} + +/* + * Set max sequence number (aka session ID) + */ +void +iolog_set_maxseq(unsigned int newval) +{ + debug_decl(iolog_set_maxseq, SUDO_DEBUG_UTIL); + + /* Clamp to SESSID_MAX as documented. */ + if (newval > SESSID_MAX) + newval = SESSID_MAX; + sessid_max = newval; + + debug_return; +} + +/* + * Set iolog_uid (and iolog_gid if gid not explicitly set). + */ +void +iolog_set_owner(uid_t uid, gid_t gid) +{ + debug_decl(iolog_set_owner, SUDO_DEBUG_UTIL); + + iolog_uid = uid; + if (!iolog_gid_set) + iolog_gid = gid; + + debug_return; +} + +/* + * Set iolog_gid. + */ +void +iolog_set_gid(gid_t gid) +{ + debug_decl(iolog_set_gid, SUDO_DEBUG_UTIL); + + iolog_gid = gid; + iolog_gid_set = true; + + debug_return; +} + +/* + * Set iolog_filemode and iolog_dirmode. + */ +void +iolog_set_mode(mode_t mode) +{ + debug_decl(iolog_set_mode, SUDO_DEBUG_UTIL); + + /* I/O log files must be readable and writable by owner. */ + iolog_filemode = S_IRUSR|S_IWUSR; + + /* Add in group and other read/write if specified. */ + iolog_filemode |= mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + + /* For directory mode, add execute bits as needed. */ + iolog_dirmode = iolog_filemode | S_IXUSR; + if (iolog_dirmode & (S_IRGRP|S_IWGRP)) + iolog_dirmode |= S_IXGRP; + if (iolog_dirmode & (S_IROTH|S_IWOTH)) + iolog_dirmode |= S_IXOTH; + + debug_return; +} + +/* + * Set iolog_compress + */ +void +iolog_set_compress(bool newval) +{ + debug_decl(iolog_set_compress, SUDO_DEBUG_UTIL); + iolog_compress = newval; + debug_return; +} + +/* + * Set iolog_flush + */ +void +iolog_set_flush(bool newval) +{ + debug_decl(iolog_set_flush, SUDO_DEBUG_UTIL); + iolog_flush = newval; + debug_return; +} + +/* + * Getters. + */ + +unsigned int +iolog_get_maxseq(void) +{ + return sessid_max; +} + +uid_t +iolog_get_uid(void) +{ + return iolog_uid; +} + +gid_t +iolog_get_gid(void) +{ + return iolog_gid; +} + +mode_t +iolog_get_file_mode(void) +{ + return iolog_filemode; +} + +mode_t +iolog_get_dir_mode(void) +{ + return iolog_dirmode; +} + +bool +iolog_get_compress(void) +{ + return iolog_compress; +} + +bool +iolog_get_flush(void) +{ + return iolog_flush; +} diff --git a/lib/iolog/iolog_fileio.c b/lib/iolog/iolog_fileio.c index 4e367136f..0df7ddba0 100644 --- a/lib/iolog/iolog_fileio.c +++ b/lib/iolog/iolog_fileio.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: ISC * - * Copyright (c) 2009-2020 Todd C. Miller + * Copyright (c) 2009-2021 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -37,27 +37,14 @@ #include #include -#include "pathnames.h" #include "sudo_compat.h" -#include "sudo_conf.h" #include "sudo_debug.h" -#include "sudo_eventlog.h" #include "sudo_fatal.h" #include "sudo_gettext.h" #include "sudo_iolog.h" -#include "sudo_json.h" -#include "sudo_queue.h" #include "sudo_util.h" static unsigned char const gzip_magic[2] = {0x1f, 0x8b}; -static unsigned int sessid_max = SESSID_MAX; -static mode_t iolog_filemode = S_IRUSR|S_IWUSR; -static mode_t iolog_dirmode = S_IRWXU; -static uid_t iolog_uid = ROOT_UID; -static gid_t iolog_gid = ROOT_GID; -static bool iolog_gid_set; -static bool iolog_compress; -static bool iolog_flush; /* * Set effective user and group-IDs to iolog_uid and iolog_gid. @@ -69,6 +56,8 @@ io_swapids(bool restore) #ifdef HAVE_SETEUID static uid_t user_euid = (uid_t)-1; static gid_t user_egid = (gid_t)-1; + const uid_t iolog_uid = iolog_get_uid(); + const gid_t iolog_gid = iolog_get_gid(); debug_decl(io_swapids, SUDO_DEBUG_UTIL); if (user_euid == (uid_t)-1) @@ -118,10 +107,14 @@ io_swapids(bool restore) static bool iolog_mkdirs(char *path) { - mode_t omask; - struct stat sb; - int dfd; + const mode_t iolog_filemode = iolog_get_file_mode(); + 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 = true, uid_changed = false; + struct stat sb; + mode_t omask; + int dfd; debug_decl(iolog_mkdirs, SUDO_DEBUG_UTIL); dfd = open(path, O_RDONLY|O_NONBLOCK); @@ -210,6 +203,9 @@ done: bool 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; debug_decl(iolog_mkdtemp, SUDO_DEBUG_UTIL); @@ -268,113 +264,6 @@ iolog_rename(const char *from, const char *to) debug_return_bool(ok); } -/* - * Reset I/O log settings to default values. - */ -void -iolog_set_defaults(void) -{ - sessid_max = SESSID_MAX; - iolog_filemode = S_IRUSR|S_IWUSR; - iolog_dirmode = S_IRWXU; - iolog_uid = ROOT_UID; - iolog_gid = ROOT_GID; - iolog_gid_set = false; - iolog_compress = false; - iolog_flush = false; -} - -/* - * Set max sequence number (aka session ID) - */ -void -iolog_set_maxseq(unsigned int newval) -{ - debug_decl(iolog_set_maxseq, SUDO_DEBUG_UTIL); - - /* Clamp to SESSID_MAX as documented. */ - if (newval > SESSID_MAX) - newval = SESSID_MAX; - sessid_max = newval; - - debug_return; -} - -/* - * Set iolog_uid (and iolog_gid if gid not explicitly set). - */ -void -iolog_set_owner(uid_t uid, gid_t gid) -{ - debug_decl(iolog_set_owner, SUDO_DEBUG_UTIL); - - iolog_uid = uid; - if (!iolog_gid_set) - iolog_gid = gid; - - debug_return; -} - -/* - * Set iolog_gid. - */ -void -iolog_set_gid(gid_t gid) -{ - debug_decl(iolog_set_gid, SUDO_DEBUG_UTIL); - - iolog_gid = gid; - iolog_gid_set = true; - - debug_return; -} - -/* - * Set iolog_filemode and iolog_dirmode. - */ -void -iolog_set_mode(mode_t mode) -{ - debug_decl(iolog_set_mode, SUDO_DEBUG_UTIL); - - /* I/O log files must be readable and writable by owner. */ - iolog_filemode = S_IRUSR|S_IWUSR; - - /* Add in group and other read/write if specified. */ - iolog_filemode |= mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); - - /* For directory mode, add execute bits as needed. */ - iolog_dirmode = iolog_filemode | S_IXUSR; - if (iolog_dirmode & (S_IRGRP|S_IWGRP)) - iolog_dirmode |= S_IXGRP; - if (iolog_dirmode & (S_IROTH|S_IWOTH)) - iolog_dirmode |= S_IXOTH; - - debug_return; -} - -/* - * Set iolog_compress - */ -void -iolog_set_compress(bool newval) -{ - debug_decl(iolog_set_compress, SUDO_DEBUG_UTIL); - iolog_compress = newval; - debug_return; -} - -/* - * Set iolog_flush - */ -void -iolog_set_flush(bool newval) -{ - debug_decl(iolog_set_flush, SUDO_DEBUG_UTIL); - iolog_flush = newval; - debug_return; -} - /* * Wrapper for openat(2) that sets umask and retries as iolog_uid/iolog_gid * if openat(2) returns EACCES. @@ -382,8 +271,10 @@ iolog_set_flush(bool newval) int iolog_openat(int dfd, const char *path, int flags) { - int fd; + const mode_t iolog_filemode = iolog_get_file_mode(); + const mode_t iolog_dirmode = iolog_get_dir_mode(); mode_t omask = S_IRWXG|S_IRWXO; + int fd; debug_decl(iolog_openat, SUDO_DEBUG_UTIL); if (ISSET(flags, O_CREAT)) { @@ -435,6 +326,8 @@ iolog_nextid(char *iolog_dir, char sessid[7]) bool ret = false; char pathbuf[PATH_MAX]; static const char b36char[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const uid_t iolog_uid = iolog_get_uid(); + const gid_t iolog_gid = iolog_get_gid(); debug_decl(iolog_nextid, SUDO_DEBUG_UTIL); /* @@ -480,7 +373,7 @@ iolog_nextid(char *iolog_dir, char sessid[7]) nread--; buf[nread] = '\0'; id = strtoul(buf, &ep, 36); - if (ep == buf || *ep != '\0' || id >= sessid_max) { + if (ep == buf || *ep != '\0' || id >= iolog_get_maxseq()) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, "%s: bad sequence number: %s", pathbuf, buf); id = 0; @@ -559,6 +452,8 @@ iolog_open(struct iolog_file *iol, int dfd, int iofd, const char *mode) int flags; const char *file; unsigned char magic[2]; + const uid_t iolog_uid = iolog_get_uid(); + const gid_t iolog_gid = iolog_get_gid(); debug_decl(iolog_open, SUDO_DEBUG_UTIL); if (mode[0] == 'r') { @@ -588,7 +483,7 @@ iolog_open(struct iolog_file *iol, int dfd, int iofd, const char *mode) "%s: unable to fchown %d:%d %s", __func__, (int)iolog_uid, (int)iolog_gid, file); } - iol->compressed = iolog_compress; + iol->compressed = iolog_get_compress(); } else { /* check for gzip magic number */ if (pread(fd, magic, sizeof(magic), 0) == ssizeof(magic)) { @@ -784,7 +679,7 @@ iolog_write(struct iolog_file *iol, const void *buf, size_t len, *errstr = gzstrerror(iol->fd.g); goto done; } - if (iolog_flush) { + if (iolog_get_flush()) { if (gzflush(iol->fd.g, Z_SYNC_FLUSH) != Z_OK) { ret = -1; if (errstr != NULL) @@ -802,7 +697,7 @@ iolog_write(struct iolog_file *iol, const void *buf, size_t len, *errstr = strerror(errno); goto done; } - if (iolog_flush) { + if (iolog_get_flush()) { if (fflush(iol->fd.f) != 0) { ret = -1; if (errstr != NULL) @@ -882,15 +777,6 @@ iolog_gets(struct iolog_file *iol, char *buf, size_t nbytes, debug_return_str(str); } -/* - * Set owner using iolog_uid and iolog_gid. - */ -int -iolog_fchown(int fd) -{ - return fchown(fd, iolog_uid, iolog_gid); -} - /* * Map IOFD_* -> name. */ diff --git a/lib/iolog/iolog_loginfo.c b/lib/iolog/iolog_loginfo.c index 9d47d59ca..daf2a7105 100644 --- a/lib/iolog/iolog_loginfo.c +++ b/lib/iolog/iolog_loginfo.c @@ -115,9 +115,10 @@ iolog_write_info_file_legacy(int dfd, struct eventlog *evlog) close(fd); debug_return_bool(false); } - if (iolog_fchown(fd) != 0) { + if (fchown(fd, iolog_get_uid(), iolog_get_gid()) != 0) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, - "%s: unable to set owner on %s/log", __func__, evlog->iolog_path); + "%s: unable to fchown %d:%d %s/log", __func__, + (int)iolog_get_uid(), (int)iolog_get_gid(), evlog->iolog_path); } fprintf(fp, "%lld:%s:%s:%s:%s:%d:%d\n%s\n", @@ -187,9 +188,10 @@ iolog_write_info_file_json(int dfd, struct eventlog *evlog) "unable to open %s/log.json", evlog->iolog_path); goto done; } - if (iolog_fchown(fd) != 0) { + if (fchown(fd, iolog_get_uid(), iolog_get_gid()) != 0) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, - "%s: unable to set owner on %s/log", __func__, evlog->iolog_path); + "%s: unable to fchown %d:%d %s/log.json", __func__, + (int)iolog_get_uid(), (int)iolog_get_gid(), evlog->iolog_path); } fd = -1;