mirror of
https://github.com/sudo-project/sudo.git
synced 2025-08-22 09:57:41 +00:00
Split iolog_fileio.c into multiple files.
This commit is contained in:
parent
fc9170d809
commit
851247e58c
16
MANIFEST
16
MANIFEST
@ -115,14 +115,28 @@ lib/fuzzstub/fuzzstub.c
|
|||||||
lib/iolog/Makefile.in
|
lib/iolog/Makefile.in
|
||||||
lib/iolog/host_port.c
|
lib/iolog/host_port.c
|
||||||
lib/iolog/hostcheck.c
|
lib/iolog/hostcheck.c
|
||||||
|
lib/iolog/iolog_clearerr.c
|
||||||
|
lib/iolog/iolog_close.c
|
||||||
lib/iolog/iolog_conf.c
|
lib/iolog/iolog_conf.c
|
||||||
lib/iolog/iolog_fileio.c
|
lib/iolog/iolog_eof.c
|
||||||
|
lib/iolog/iolog_gets.c
|
||||||
lib/iolog/iolog_json.c
|
lib/iolog/iolog_json.c
|
||||||
lib/iolog/iolog_json.h
|
lib/iolog/iolog_json.h
|
||||||
lib/iolog/iolog_legacy.c
|
lib/iolog/iolog_legacy.c
|
||||||
lib/iolog/iolog_loginfo.c
|
lib/iolog/iolog_loginfo.c
|
||||||
|
lib/iolog/iolog_mkdirs.c
|
||||||
|
lib/iolog/iolog_mkdtemp.c
|
||||||
|
lib/iolog/iolog_mkpath.c
|
||||||
|
lib/iolog/iolog_nextid.c
|
||||||
|
lib/iolog/iolog_open.c
|
||||||
|
lib/iolog/iolog_openat.c
|
||||||
lib/iolog/iolog_path.c
|
lib/iolog/iolog_path.c
|
||||||
|
lib/iolog/iolog_read.c
|
||||||
|
lib/iolog/iolog_seek.c
|
||||||
|
lib/iolog/iolog_swapids.c
|
||||||
lib/iolog/iolog_timing.c
|
lib/iolog/iolog_timing.c
|
||||||
|
lib/iolog/iolog_util.c
|
||||||
|
lib/iolog/iolog_write.c
|
||||||
lib/iolog/regress/corpus/log_json/id.json
|
lib/iolog/regress/corpus/log_json/id.json
|
||||||
lib/iolog/regress/corpus/log_json/ls.json
|
lib/iolog/regress/corpus/log_json/ls.json
|
||||||
lib/iolog/regress/corpus/log_json/mailq.json
|
lib/iolog/regress/corpus/log_json/mailq.json
|
||||||
|
@ -113,7 +113,6 @@ bool iolog_mkdtemp(char *path);
|
|||||||
bool iolog_mkpath(char *path);
|
bool iolog_mkpath(char *path);
|
||||||
bool iolog_nextid(char *iolog_dir, char sessid[7]);
|
bool iolog_nextid(char *iolog_dir, char sessid[7]);
|
||||||
bool iolog_open(struct iolog_file *iol, int dfd, int iofd, const char *mode);
|
bool iolog_open(struct iolog_file *iol, int dfd, int iofd, const char *mode);
|
||||||
bool iolog_rename(const char *from, const char *to);
|
|
||||||
bool iolog_write_info_file(int dfd, struct eventlog *evlog);
|
bool iolog_write_info_file(int dfd, struct eventlog *evlog);
|
||||||
char *iolog_gets(struct iolog_file *iol, char *buf, size_t nbytes, const char **errsttr);
|
char *iolog_gets(struct iolog_file *iol, char *buf, size_t nbytes, const char **errsttr);
|
||||||
const char *iolog_fd_to_name(int iofd);
|
const char *iolog_fd_to_name(int iofd);
|
||||||
@ -137,5 +136,7 @@ void iolog_set_gid(gid_t gid);
|
|||||||
void iolog_set_maxseq(unsigned int maxval);
|
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_mkdirs(char *path);
|
||||||
|
|
||||||
#endif /* SUDO_IOLOG_H */
|
#endif /* SUDO_IOLOG_H */
|
||||||
|
@ -95,23 +95,27 @@ DEVEL = @DEVEL@
|
|||||||
|
|
||||||
SHELL = @SHELL@
|
SHELL = @SHELL@
|
||||||
|
|
||||||
LIBIOLOG_OBJS = iolog_conf.lo iolog_fileio.lo iolog_json.lo iolog_legacy.lo \
|
LIBIOLOG_OBJS = host_port.lo hostcheck.lo iolog_clearerr.lo iolog_close.lo \
|
||||||
iolog_loginfo.lo iolog_path.lo iolog_timing.lo host_port.lo \
|
iolog_conf.lo iolog_eof.lo iolog_gets.lo iolog_json.lo \
|
||||||
hostcheck.lo
|
iolog_legacy.lo iolog_loginfo.lo iolog_mkdirs.lo \
|
||||||
|
iolog_mkdtemp.lo iolog_mkpath.lo iolog_nextid.lo \
|
||||||
|
iolog_open.lo iolog_openat.lo iolog_path.lo iolog_read.lo \
|
||||||
|
iolog_seek.lo iolog_swapids.lo iolog_timing.lo iolog_util.lo \
|
||||||
|
iolog_write.lo
|
||||||
|
|
||||||
IOBJS = $(LIBIOLOG_OBJS:.lo=.i)
|
IOBJS = $(LIBIOLOG_OBJS:.lo=.i)
|
||||||
|
|
||||||
POBJS = $(IOBJS:.i=.plog)
|
POBJS = $(IOBJS:.i=.plog)
|
||||||
|
|
||||||
CHECK_IOLOG_MKPATH_OBJS = check_iolog_mkpath.lo iolog_conf.lo iolog_fileio.lo
|
CHECK_IOLOG_MKPATH_OBJS = check_iolog_mkpath.lo
|
||||||
|
|
||||||
CHECK_IOLOG_PATH_OBJS = check_iolog_path.lo iolog_path.lo
|
CHECK_IOLOG_PATH_OBJS = check_iolog_path.lo
|
||||||
|
|
||||||
CHECK_IOLOG_TIMING_OBJS = check_iolog_timing.lo iolog_json.lo iolog_timing.lo
|
CHECK_IOLOG_TIMING_OBJS = check_iolog_timing.lo
|
||||||
|
|
||||||
CHECK_IOLOG_JSON_OBJS = check_iolog_json.lo iolog_json.lo
|
CHECK_IOLOG_JSON_OBJS = check_iolog_json.lo
|
||||||
|
|
||||||
HOST_PORT_TEST_OBJS = host_port_test.lo host_port.lo
|
HOST_PORT_TEST_OBJS = host_port_test.lo
|
||||||
|
|
||||||
FUZZ_IOLOG_JSON_OBJS = fuzz_iolog_json.lo
|
FUZZ_IOLOG_JSON_OBJS = fuzz_iolog_json.lo
|
||||||
|
|
||||||
@ -425,6 +429,30 @@ hostcheck.i: $(srcdir)/hostcheck.c $(incdir)/compat/stdbool.h \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
hostcheck.plog: hostcheck.i
|
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 $@
|
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_clearerr.lo: $(srcdir)/iolog_clearerr.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_clearerr.c
|
||||||
|
iolog_clearerr.i: $(srcdir)/iolog_clearerr.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
iolog_clearerr.plog: iolog_clearerr.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_clearerr.c --i-file $< --output-file $@
|
||||||
|
iolog_close.lo: $(srcdir)/iolog_close.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_close.c
|
||||||
|
iolog_close.i: $(srcdir)/iolog_close.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
iolog_close.plog: iolog_close.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_close.c --i-file $< --output-file $@
|
||||||
iolog_conf.lo: $(srcdir)/iolog_conf.c $(incdir)/compat/stdbool.h \
|
iolog_conf.lo: $(srcdir)/iolog_conf.c $(incdir)/compat/stdbool.h \
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
@ -439,22 +467,30 @@ iolog_conf.i: $(srcdir)/iolog_conf.c $(incdir)/compat/stdbool.h \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
iolog_conf.plog: iolog_conf.i
|
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 $@
|
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 \
|
iolog_eof.lo: $(srcdir)/iolog_eof.c $(incdir)/compat/stdbool.h \
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
$(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
|
$(top_builddir)/config.h
|
||||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_eof.c
|
||||||
$(top_builddir)/config.h
|
iolog_eof.i: $(srcdir)/iolog_eof.c $(incdir)/compat/stdbool.h \
|
||||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_fileio.c
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
iolog_fileio.i: $(srcdir)/iolog_fileio.c $(incdir)/compat/stdbool.h \
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
$(top_builddir)/config.h
|
||||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.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) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
iolog_fileio.plog: iolog_fileio.i
|
iolog_eof.plog: iolog_eof.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 $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_eof.c --i-file $< --output-file $@
|
||||||
|
iolog_gets.lo: $(srcdir)/iolog_gets.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_gets.c
|
||||||
|
iolog_gets.i: $(srcdir)/iolog_gets.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
iolog_gets.plog: iolog_gets.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_gets.c --i-file $< --output-file $@
|
||||||
iolog_json.lo: $(srcdir)/iolog_json.c $(incdir)/compat/stdbool.h \
|
iolog_json.lo: $(srcdir)/iolog_json.c $(incdir)/compat/stdbool.h \
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
$(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
|
$(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
|
||||||
@ -507,6 +543,94 @@ iolog_loginfo.i: $(srcdir)/iolog_loginfo.c $(incdir)/compat/stdbool.h \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
iolog_loginfo.plog: iolog_loginfo.i
|
iolog_loginfo.plog: iolog_loginfo.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_loginfo.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_loginfo.c --i-file $< --output-file $@
|
||||||
|
iolog_mkdirs.lo: $(srcdir)/iolog_mkdirs.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.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_mkdirs.c
|
||||||
|
iolog_mkdirs.i: $(srcdir)/iolog_mkdirs.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.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_mkdirs.plog: iolog_mkdirs.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_mkdirs.c --i-file $< --output-file $@
|
||||||
|
iolog_mkdtemp.lo: $(srcdir)/iolog_mkdtemp.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.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_mkdtemp.c
|
||||||
|
iolog_mkdtemp.i: $(srcdir)/iolog_mkdtemp.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.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_mkdtemp.plog: iolog_mkdtemp.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_mkdtemp.c --i-file $< --output-file $@
|
||||||
|
iolog_mkpath.lo: $(srcdir)/iolog_mkpath.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_mkpath.c
|
||||||
|
iolog_mkpath.i: $(srcdir)/iolog_mkpath.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
iolog_mkpath.plog: iolog_mkpath.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_mkpath.c --i-file $< --output-file $@
|
||||||
|
iolog_nextid.lo: $(srcdir)/iolog_nextid.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.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_nextid.c
|
||||||
|
iolog_nextid.i: $(srcdir)/iolog_nextid.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.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_nextid.plog: iolog_nextid.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_nextid.c --i-file $< --output-file $@
|
||||||
|
iolog_open.lo: $(srcdir)/iolog_open.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
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_open.c
|
||||||
|
iolog_open.i: $(srcdir)/iolog_open.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
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
iolog_open.plog: iolog_open.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_open.c --i-file $< --output-file $@
|
||||||
|
iolog_openat.lo: $(srcdir)/iolog_openat.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.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_openat.c
|
||||||
|
iolog_openat.i: $(srcdir)/iolog_openat.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.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_openat.plog: iolog_openat.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_openat.c --i-file $< --output-file $@
|
||||||
iolog_path.lo: $(srcdir)/iolog_path.c $(incdir)/compat/stdbool.h \
|
iolog_path.lo: $(srcdir)/iolog_path.c $(incdir)/compat/stdbool.h \
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||||
@ -523,6 +647,44 @@ iolog_path.i: $(srcdir)/iolog_path.c $(incdir)/compat/stdbool.h \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
iolog_path.plog: iolog_path.i
|
iolog_path.plog: iolog_path.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_path.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_path.c --i-file $< --output-file $@
|
||||||
|
iolog_read.lo: $(srcdir)/iolog_read.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_read.c
|
||||||
|
iolog_read.i: $(srcdir)/iolog_read.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
iolog_read.plog: iolog_read.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_read.c --i-file $< --output-file $@
|
||||||
|
iolog_seek.lo: $(srcdir)/iolog_seek.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_seek.c
|
||||||
|
iolog_seek.i: $(srcdir)/iolog_seek.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
iolog_seek.plog: iolog_seek.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_seek.c --i-file $< --output-file $@
|
||||||
|
iolog_swapids.lo: $(srcdir)/iolog_swapids.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
|
||||||
|
$(incdir)/sudo_queue.h $(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_swapids.c
|
||||||
|
iolog_swapids.i: $(srcdir)/iolog_swapids.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
|
||||||
|
$(incdir)/sudo_queue.h $(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
iolog_swapids.plog: iolog_swapids.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_swapids.c --i-file $< --output-file $@
|
||||||
iolog_timing.lo: $(srcdir)/iolog_timing.c $(incdir)/compat/stdbool.h \
|
iolog_timing.lo: $(srcdir)/iolog_timing.c $(incdir)/compat/stdbool.h \
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
$(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
|
$(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
|
||||||
@ -539,3 +701,27 @@ iolog_timing.i: $(srcdir)/iolog_timing.c $(incdir)/compat/stdbool.h \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
iolog_timing.plog: iolog_timing.i
|
iolog_timing.plog: iolog_timing.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_timing.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_timing.c --i-file $< --output-file $@
|
||||||
|
iolog_util.lo: $(srcdir)/iolog_util.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_util.c
|
||||||
|
iolog_util.i: $(srcdir)/iolog_util.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
iolog_util.plog: iolog_util.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_util.c --i-file $< --output-file $@
|
||||||
|
iolog_write.lo: $(srcdir)/iolog_write.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_write.c
|
||||||
|
iolog_write.i: $(srcdir)/iolog_write.c $(incdir)/compat/stdbool.h \
|
||||||
|
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||||
|
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
|
||||||
|
$(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
iolog_write.plog: iolog_write.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_write.c --i-file $< --output-file $@
|
||||||
|
45
lib/iolog/iolog_clearerr.c
Normal file
45
lib/iolog/iolog_clearerr.c
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
iolog_clearerr(struct iolog_file *iol)
|
||||||
|
{
|
||||||
|
debug_decl(iolog_eof, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
if (iol->compressed)
|
||||||
|
gzclearerr(iol->fd.g);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
clearerr(iol->fd.f);
|
||||||
|
debug_return;
|
||||||
|
}
|
80
lib/iolog/iolog_close.c
Normal file
80
lib/iolog/iolog_close.c
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Close an I/O log.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
iolog_close(struct iolog_file *iol, const char **errstr)
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
debug_decl(iolog_close, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
if (iol->compressed) {
|
||||||
|
int errnum;
|
||||||
|
|
||||||
|
/* Must check error indicator before closing. */
|
||||||
|
if (iol->writable) {
|
||||||
|
if (gzflush(iol->fd.g, Z_SYNC_FLUSH) != Z_OK) {
|
||||||
|
ret = false;
|
||||||
|
if (errstr != NULL) {
|
||||||
|
*errstr = gzerror(iol->fd.g, &errnum);
|
||||||
|
if (errnum == Z_ERRNO)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errnum = gzclose(iol->fd.g);
|
||||||
|
if (ret && errnum != Z_OK) {
|
||||||
|
ret = false;
|
||||||
|
if (errstr != NULL)
|
||||||
|
*errstr = errnum == Z_ERRNO ? strerror(errno) : "unknown error";
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (fclose(iol->fd.f) != 0) {
|
||||||
|
ret = false;
|
||||||
|
if (errstr != NULL)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_return_bool(ret);
|
||||||
|
}
|
54
lib/iolog/iolog_eof.c
Normal file
54
lib/iolog/iolog_eof.c
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true if at end of I/O log file, else false.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
iolog_eof(struct iolog_file *iol)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
debug_decl(iolog_eof, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
if (iol->compressed)
|
||||||
|
ret = gzeof(iol->fd.g) != 0;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ret = feof(iol->fd.f) != 0;
|
||||||
|
debug_return_int(ret);
|
||||||
|
}
|
@ -1,815 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-License-Identifier: ISC
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2021 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
|
|
||||||
* 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 <config.h>
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#ifdef HAVE_STDBOOL_H
|
|
||||||
# include <stdbool.h>
|
|
||||||
#else
|
|
||||||
# include "compat/stdbool.h"
|
|
||||||
#endif
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#include "sudo_compat.h"
|
|
||||||
#include "sudo_debug.h"
|
|
||||||
#include "sudo_fatal.h"
|
|
||||||
#include "sudo_gettext.h"
|
|
||||||
#include "sudo_iolog.h"
|
|
||||||
#include "sudo_util.h"
|
|
||||||
|
|
||||||
static unsigned char const gzip_magic[2] = {0x1f, 0x8b};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set effective user and group-IDs to iolog_uid and iolog_gid.
|
|
||||||
* If restore flag is set, swap them back.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
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)
|
|
||||||
user_euid = geteuid();
|
|
||||||
if (user_egid == (gid_t)-1)
|
|
||||||
user_egid = getegid();
|
|
||||||
|
|
||||||
if (restore) {
|
|
||||||
if (seteuid(user_euid) == -1) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
|
||||||
"%s: unable to restore effective uid to %d", __func__,
|
|
||||||
(int)user_euid);
|
|
||||||
sudo_warn("seteuid() %d -> %d", (int)iolog_uid, (int)user_euid);
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
if (setegid(user_egid) == -1) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
|
||||||
"%s: unable to restore effective gid to %d", __func__,
|
|
||||||
(int)user_egid);
|
|
||||||
sudo_warn("setegid() %d -> %d", (int)iolog_gid, (int)user_egid);
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Fail silently if the user has insufficient privileges. */
|
|
||||||
if (setegid(iolog_gid) == -1) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
|
||||||
"%s: unable to set effective gid to %d", __func__,
|
|
||||||
(int)iolog_gid);
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
if (seteuid(iolog_uid) == -1) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
|
||||||
"%s: unable to set effective uid to %d", __func__,
|
|
||||||
(int)iolog_uid);
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug_return_bool(true);
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create directory and any parent directories as needed.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
iolog_mkdirs(char *path)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
if (dfd == -1 && errno == EACCES) {
|
|
||||||
/* Try again as the I/O log owner (for NFS). */
|
|
||||||
if (io_swapids(false)) {
|
|
||||||
dfd = open(path, O_RDONLY|O_NONBLOCK);
|
|
||||||
if (!io_swapids(true)) {
|
|
||||||
ok = false;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dfd != -1 && fstat(dfd, &sb) != -1) {
|
|
||||||
if (S_ISDIR(sb.st_mode)) {
|
|
||||||
if (sb.st_uid != iolog_uid || sb.st_gid != iolog_gid) {
|
|
||||||
if (fchown(dfd, iolog_uid, iolog_gid) != 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((sb.st_mode & ALLPERMS) != iolog_dirmode) {
|
|
||||||
if (fchmod(dfd, iolog_dirmode) != 0) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
|
||||||
"%s: unable to chmod 0%o %s", __func__,
|
|
||||||
(int)iolog_dirmode, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sudo_warnx(U_("%s exists but is not a directory (0%o)"),
|
|
||||||
path, (unsigned int) sb.st_mode);
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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) {
|
|
||||||
/* Try again as the I/O log owner (for NFS). */
|
|
||||||
uid_changed = io_swapids(false);
|
|
||||||
if (uid_changed)
|
|
||||||
ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false);
|
|
||||||
}
|
|
||||||
if (ok) {
|
|
||||||
/* Create final path component. */
|
|
||||||
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;
|
|
||||||
if (!ok) {
|
|
||||||
if (errno == EACCES && !uid_changed) {
|
|
||||||
/* Try again as the I/O log owner (for NFS). */
|
|
||||||
uid_changed = io_swapids(false);
|
|
||||||
if (uid_changed)
|
|
||||||
ok = mkdir(path, iolog_dirmode) == 0 || errno == EEXIST;
|
|
||||||
}
|
|
||||||
if (!ok)
|
|
||||||
sudo_warn(U_("unable to mkdir %s"), path);
|
|
||||||
} else {
|
|
||||||
if (chown(path, iolog_uid, iolog_gid) != 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (uid_changed) {
|
|
||||||
if (!io_swapids(true))
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
umask(omask);
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (dfd != -1)
|
|
||||||
close(dfd);
|
|
||||||
debug_return_bool(ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create temporary directory and any parent directories as needed.
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
|
|
||||||
ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true);
|
|
||||||
if (!ok && errno == EACCES) {
|
|
||||||
/* Try again as the I/O log owner (for NFS). */
|
|
||||||
uid_changed = io_swapids(false);
|
|
||||||
if (uid_changed)
|
|
||||||
ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false);
|
|
||||||
}
|
|
||||||
if (ok) {
|
|
||||||
/* 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 = io_swapids(false);
|
|
||||||
if (mkdtemp(path) == NULL) {
|
|
||||||
sudo_warn(U_("unable to mkdir %s"), path);
|
|
||||||
ok = false;
|
|
||||||
} else {
|
|
||||||
if (chmod(path, iolog_dirmode) != 0) {
|
|
||||||
sudo_warn(U_("unable to change mode of %s to 0%o"),
|
|
||||||
path, (unsigned int)iolog_dirmode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uid_changed) {
|
|
||||||
if (!io_swapids(true))
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
debug_return_bool(ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Like rename(2) but changes UID as needed.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
iolog_rename(const char *from, const char *to)
|
|
||||||
{
|
|
||||||
bool ok, uid_changed = false;
|
|
||||||
debug_decl(iolog_rename, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
ok = rename(from, to) == 0;
|
|
||||||
if (!ok && errno == EACCES) {
|
|
||||||
uid_changed = io_swapids(false);
|
|
||||||
if (uid_changed)
|
|
||||||
ok = rename(from, to) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uid_changed) {
|
|
||||||
if (!io_swapids(true))
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
debug_return_bool(ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Wrapper for openat(2) that sets umask and retries as iolog_uid/iolog_gid
|
|
||||||
* if openat(2) returns EACCES.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
iolog_openat(int dfd, const char *path, int flags)
|
|
||||||
{
|
|
||||||
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)) {
|
|
||||||
/* umask must not be more restrictive than the file modes. */
|
|
||||||
omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
|
|
||||||
}
|
|
||||||
fd = openat(dfd, path, flags, iolog_filemode);
|
|
||||||
if (fd == -1 && errno == EACCES) {
|
|
||||||
/* Enable write bit if it is missing. */
|
|
||||||
struct stat sb;
|
|
||||||
if (fstatat(dfd, path, &sb, 0) == 0) {
|
|
||||||
mode_t write_bits = iolog_filemode & (S_IWUSR|S_IWGRP|S_IWOTH);
|
|
||||||
if ((sb.st_mode & write_bits) != write_bits) {
|
|
||||||
if (fchmodat(dfd, path, iolog_filemode, 0) == 0)
|
|
||||||
fd = openat(dfd, path, flags, iolog_filemode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fd == -1 && errno == EACCES) {
|
|
||||||
/* Try again as the I/O log owner (for NFS). */
|
|
||||||
if (io_swapids(false)) {
|
|
||||||
fd = openat(dfd, path, flags, iolog_filemode);
|
|
||||||
if (!io_swapids(true)) {
|
|
||||||
/* io_swapids() warns on error. */
|
|
||||||
if (fd != -1) {
|
|
||||||
close(fd);
|
|
||||||
fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ISSET(flags, O_CREAT))
|
|
||||||
umask(omask);
|
|
||||||
debug_return_int(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the on-disk sequence number, set sessid to the next
|
|
||||||
* number, and update the on-disk copy.
|
|
||||||
* Uses file locking to avoid sequence number collisions.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
iolog_nextid(char *iolog_dir, char sessid[7])
|
|
||||||
{
|
|
||||||
char buf[32], *ep;
|
|
||||||
int i, len, fd = -1;
|
|
||||||
unsigned long id = 0;
|
|
||||||
ssize_t nread;
|
|
||||||
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);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create I/O log directory if it doesn't already exist.
|
|
||||||
*/
|
|
||||||
if (!iolog_mkdirs(iolog_dir))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open sequence file
|
|
||||||
*/
|
|
||||||
len = snprintf(pathbuf, sizeof(pathbuf), "%s/seq", iolog_dir);
|
|
||||||
if (len < 0 || len >= ssizeof(pathbuf)) {
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
|
||||||
"%s: %s/seq", __func__, iolog_dir);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
fd = iolog_openat(AT_FDCWD, pathbuf, O_RDWR|O_CREAT);
|
|
||||||
if (fd == -1) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
|
||||||
"%s: unable to open %s", __func__, pathbuf);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (!sudo_lock_file(fd, SUDO_LOCK)) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
|
||||||
"unable to lock %s", pathbuf);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (fchown(fd, iolog_uid, iolog_gid) != 0) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
|
||||||
"%s: unable to fchown %d:%d %s", __func__,
|
|
||||||
(int)iolog_uid, (int)iolog_gid, pathbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read current seq number (base 36). */
|
|
||||||
nread = read(fd, buf, sizeof(buf) - 1);
|
|
||||||
if (nread != 0) {
|
|
||||||
if (nread == -1) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (buf[nread - 1] == '\n')
|
|
||||||
nread--;
|
|
||||||
buf[nread] = '\0';
|
|
||||||
id = strtoul(buf, &ep, 36);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
id++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert id to a string and stash in sessid.
|
|
||||||
* Note that that least significant digits go at the end of the string.
|
|
||||||
*/
|
|
||||||
for (i = 5; i >= 0; i--) {
|
|
||||||
buf[i] = b36char[id % 36];
|
|
||||||
id /= 36;
|
|
||||||
}
|
|
||||||
buf[6] = '\n';
|
|
||||||
|
|
||||||
/* Stash id for logging purposes. */
|
|
||||||
memcpy(sessid, buf, 6);
|
|
||||||
sessid[6] = '\0';
|
|
||||||
|
|
||||||
/* Rewind and overwrite old seq file, including the NUL byte. */
|
|
||||||
#ifdef HAVE_PWRITE
|
|
||||||
if (pwrite(fd, buf, 7, 0) != 7) {
|
|
||||||
#else
|
|
||||||
if (lseek(fd, 0, SEEK_SET) == -1 || write(fd, buf, 7) != 7) {
|
|
||||||
#endif
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
|
||||||
"%s: unable to write %s", __func__, pathbuf);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
ret = true;
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (fd != -1)
|
|
||||||
close(fd);
|
|
||||||
debug_return_bool(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create path and any intermediate directories.
|
|
||||||
* If path ends in 'XXXXXX', use mkdtemp().
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
iolog_mkpath(char *path)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
bool ret;
|
|
||||||
debug_decl(iolog_mkpath, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create path and intermediate subdirs as needed.
|
|
||||||
* If path ends in at least 6 Xs (ala POSIX mktemp), use mkdtemp().
|
|
||||||
* Sets iolog_gid (if it is not already set) as a side effect.
|
|
||||||
*/
|
|
||||||
len = strlen(path);
|
|
||||||
if (len >= 6 && strcmp(&path[len - 6], "XXXXXX") == 0)
|
|
||||||
ret = iolog_mkdtemp(path);
|
|
||||||
else
|
|
||||||
ret = iolog_mkdirs(path);
|
|
||||||
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "iolog path %s", path);
|
|
||||||
|
|
||||||
debug_return_bool(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Append suffix to pathbuf after len chars and open the resulting file.
|
|
||||||
* Note that the size of pathbuf is assumed to be PATH_MAX.
|
|
||||||
* Stores the open file handle which has the close-on-exec flag set.
|
|
||||||
* XXX - move enabled logic into caller?
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
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') {
|
|
||||||
flags = mode[1] == '+' ? O_RDWR : O_RDONLY;
|
|
||||||
} else if (mode[0] == 'w') {
|
|
||||||
flags = O_CREAT|O_TRUNC;
|
|
||||||
flags |= mode[1] == '+' ? O_RDWR : O_WRONLY;
|
|
||||||
} else {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
|
||||||
"%s: invalid I/O mode %s", __func__, mode);
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
if ((file = iolog_fd_to_name(iofd)) == NULL) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
|
||||||
"%s: invalid iofd %d", __func__, iofd);
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
iol->writable = false;
|
|
||||||
iol->compressed = false;
|
|
||||||
if (iol->enabled) {
|
|
||||||
int fd = iolog_openat(dfd, file, flags);
|
|
||||||
if (fd != -1) {
|
|
||||||
if (*mode == 'w') {
|
|
||||||
if (fchown(fd, iolog_uid, iolog_gid) != 0) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
|
||||||
"%s: unable to fchown %d:%d %s", __func__,
|
|
||||||
(int)iolog_uid, (int)iolog_gid, file);
|
|
||||||
}
|
|
||||||
iol->compressed = iolog_get_compress();
|
|
||||||
} else {
|
|
||||||
/* check for gzip magic number */
|
|
||||||
if (pread(fd, magic, sizeof(magic), 0) == ssizeof(magic)) {
|
|
||||||
if (magic[0] == gzip_magic[0] && magic[1] == gzip_magic[1])
|
|
||||||
iol->compressed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fcntl(fd, F_SETFD, FD_CLOEXEC) != -1) {
|
|
||||||
#ifdef HAVE_ZLIB_H
|
|
||||||
if (iol->compressed)
|
|
||||||
iol->fd.g = gzdopen(fd, mode);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
iol->fd.f = fdopen(fd, mode);
|
|
||||||
}
|
|
||||||
if (iol->fd.v != NULL) {
|
|
||||||
switch ((flags & O_ACCMODE)) {
|
|
||||||
case O_WRONLY:
|
|
||||||
case O_RDWR:
|
|
||||||
iol->writable = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int save_errno = errno;
|
|
||||||
close(fd);
|
|
||||||
errno = save_errno;
|
|
||||||
fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fd == -1) {
|
|
||||||
iol->enabled = false;
|
|
||||||
debug_return_bool(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (*mode == 'w') {
|
|
||||||
/* Remove old log file in case we recycled sequence numbers. */
|
|
||||||
(void)unlinkat(dfd, file, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug_return_bool(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_H
|
|
||||||
static const char *
|
|
||||||
gzstrerror(gzFile file)
|
|
||||||
{
|
|
||||||
const char *errstr;
|
|
||||||
int errnum;
|
|
||||||
|
|
||||||
errstr = gzerror(file, &errnum);
|
|
||||||
if (errnum == Z_ERRNO)
|
|
||||||
errstr = strerror(errno);
|
|
||||||
|
|
||||||
return errstr;
|
|
||||||
}
|
|
||||||
#endif /* HAVE_ZLIB_H */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close an I/O log.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
iolog_close(struct iolog_file *iol, const char **errstr)
|
|
||||||
{
|
|
||||||
bool ret = true;
|
|
||||||
debug_decl(iolog_close, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_H
|
|
||||||
if (iol->compressed) {
|
|
||||||
int errnum;
|
|
||||||
|
|
||||||
/* Must check error indicator before closing. */
|
|
||||||
if (iol->writable) {
|
|
||||||
if (gzflush(iol->fd.g, Z_SYNC_FLUSH) != Z_OK) {
|
|
||||||
ret = false;
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = gzstrerror(iol->fd.g);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errnum = gzclose(iol->fd.g);
|
|
||||||
if (ret && errnum != Z_OK) {
|
|
||||||
ret = false;
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = errnum == Z_ERRNO ? strerror(errno) : "unknown error";
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (fclose(iol->fd.f) != 0) {
|
|
||||||
ret = false;
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = strerror(errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_return_bool(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* I/O log wrapper for fseek/gzseek.
|
|
||||||
*/
|
|
||||||
off_t
|
|
||||||
iolog_seek(struct iolog_file *iol, off_t offset, int whence)
|
|
||||||
{
|
|
||||||
off_t ret;
|
|
||||||
//debug_decl(iolog_seek, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_H
|
|
||||||
if (iol->compressed)
|
|
||||||
ret = gzseek(iol->fd.g, offset, whence);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
ret = fseeko(iol->fd.f, offset, whence);
|
|
||||||
|
|
||||||
//debug_return_off_t(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* I/O log wrapper for rewind/gzrewind.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
iolog_rewind(struct iolog_file *iol)
|
|
||||||
{
|
|
||||||
debug_decl(iolog_rewind, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_H
|
|
||||||
if (iol->compressed)
|
|
||||||
(void)gzrewind(iol->fd.g);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
rewind(iol->fd.f);
|
|
||||||
|
|
||||||
debug_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read from a (possibly compressed) I/O log file.
|
|
||||||
*/
|
|
||||||
ssize_t
|
|
||||||
iolog_read(struct iolog_file *iol, void *buf, size_t nbytes,
|
|
||||||
const char **errstr)
|
|
||||||
{
|
|
||||||
ssize_t nread;
|
|
||||||
debug_decl(iolog_read, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
if (nbytes > UINT_MAX) {
|
|
||||||
errno = EINVAL;
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = strerror(errno);
|
|
||||||
debug_return_ssize_t(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_H
|
|
||||||
if (iol->compressed) {
|
|
||||||
if ((nread = gzread(iol->fd.g, buf, nbytes)) == -1) {
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = gzstrerror(iol->fd.g);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
nread = (ssize_t)fread(buf, 1, nbytes, iol->fd.f);
|
|
||||||
if (nread == 0 && ferror(iol->fd.f)) {
|
|
||||||
nread = -1;
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = strerror(errno);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug_return_ssize_t(nread);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write to an I/O log, optionally compressing.
|
|
||||||
*/
|
|
||||||
ssize_t
|
|
||||||
iolog_write(struct iolog_file *iol, const void *buf, size_t len,
|
|
||||||
const char **errstr)
|
|
||||||
{
|
|
||||||
ssize_t ret;
|
|
||||||
debug_decl(iolog_write, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
if (len > UINT_MAX) {
|
|
||||||
errno = EINVAL;
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = strerror(errno);
|
|
||||||
debug_return_ssize_t(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_H
|
|
||||||
if (iol->compressed) {
|
|
||||||
ret = gzwrite(iol->fd.g, (const voidp)buf, len);
|
|
||||||
if (ret == 0) {
|
|
||||||
ret = -1;
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = gzstrerror(iol->fd.g);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (iolog_get_flush()) {
|
|
||||||
if (gzflush(iol->fd.g, Z_SYNC_FLUSH) != Z_OK) {
|
|
||||||
ret = -1;
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = gzstrerror(iol->fd.g);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
ret = fwrite(buf, 1, len, iol->fd.f);
|
|
||||||
if (ret == 0) {
|
|
||||||
ret = -1;
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = strerror(errno);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (iolog_get_flush()) {
|
|
||||||
if (fflush(iol->fd.f) != 0) {
|
|
||||||
ret = -1;
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = strerror(errno);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
debug_return_ssize_t(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns true if at end of I/O log file, else false.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
iolog_eof(struct iolog_file *iol)
|
|
||||||
{
|
|
||||||
bool ret;
|
|
||||||
debug_decl(iolog_eof, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_H
|
|
||||||
if (iol->compressed)
|
|
||||||
ret = gzeof(iol->fd.g) != 0;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
ret = feof(iol->fd.f) != 0;
|
|
||||||
debug_return_int(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
iolog_clearerr(struct iolog_file *iol)
|
|
||||||
{
|
|
||||||
debug_decl(iolog_eof, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_H
|
|
||||||
if (iol->compressed)
|
|
||||||
gzclearerr(iol->fd.g);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
clearerr(iol->fd.f);
|
|
||||||
debug_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Like gets() but for struct iolog_file.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
iolog_gets(struct iolog_file *iol, char *buf, size_t nbytes,
|
|
||||||
const char **errstr)
|
|
||||||
{
|
|
||||||
char *str;
|
|
||||||
debug_decl(iolog_gets, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
if (nbytes > UINT_MAX) {
|
|
||||||
errno = EINVAL;
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = strerror(errno);
|
|
||||||
debug_return_str(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_H
|
|
||||||
if (iol->compressed) {
|
|
||||||
if ((str = gzgets(iol->fd.g, buf, nbytes)) == NULL) {
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = gzstrerror(iol->fd.g);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if ((str = fgets(buf, nbytes, iol->fd.f)) == NULL) {
|
|
||||||
if (errstr != NULL)
|
|
||||||
*errstr = strerror(errno);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug_return_str(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Map IOFD_* -> name.
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
iolog_fd_to_name(int iofd)
|
|
||||||
{
|
|
||||||
const char *ret;
|
|
||||||
debug_decl(iolog_fd_to_name, SUDO_DEBUG_UTIL);
|
|
||||||
|
|
||||||
switch (iofd) {
|
|
||||||
case IOFD_STDIN:
|
|
||||||
ret = "stdin";
|
|
||||||
break;
|
|
||||||
case IOFD_STDOUT:
|
|
||||||
ret = "stdout";
|
|
||||||
break;
|
|
||||||
case IOFD_STDERR:
|
|
||||||
ret = "stderr";
|
|
||||||
break;
|
|
||||||
case IOFD_TTYIN:
|
|
||||||
ret = "ttyin";
|
|
||||||
break;
|
|
||||||
case IOFD_TTYOUT:
|
|
||||||
ret = "ttyout";
|
|
||||||
break;
|
|
||||||
case IOFD_TIMING:
|
|
||||||
ret = "timing";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = "unknown";
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: unexpected iofd %d",
|
|
||||||
__func__, iofd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
debug_return_const_str(ret);
|
|
||||||
}
|
|
78
lib/iolog/iolog_gets.c
Normal file
78
lib/iolog/iolog_gets.c
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like gets() but for struct iolog_file.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
iolog_gets(struct iolog_file *iol, char *buf, size_t nbytes,
|
||||||
|
const char **errstr)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
debug_decl(iolog_gets, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
if (nbytes > UINT_MAX) {
|
||||||
|
errno = EINVAL;
|
||||||
|
if (errstr != NULL)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
debug_return_str(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
if (iol->compressed) {
|
||||||
|
if ((str = gzgets(iol->fd.g, buf, nbytes)) == NULL) {
|
||||||
|
if (errstr != NULL) {
|
||||||
|
int errnum;
|
||||||
|
*errstr = gzerror(iol->fd.g, &errnum);
|
||||||
|
if (errnum == Z_ERRNO)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if ((str = fgets(buf, nbytes, iol->fd.f)) == NULL) {
|
||||||
|
if (errstr != NULL)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_return_str(str);
|
||||||
|
}
|
139
lib/iolog/iolog_mkdirs.c
Normal file
139
lib/iolog/iolog_mkdirs.c
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_fatal.h"
|
||||||
|
#include "sudo_gettext.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create directory and any parent directories as needed.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
iolog_mkdirs(char *path)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
if (dfd == -1 && errno == EACCES) {
|
||||||
|
/* Try again as the I/O log owner (for NFS). */
|
||||||
|
if (iolog_swapids(false)) {
|
||||||
|
dfd = open(path, O_RDONLY|O_NONBLOCK);
|
||||||
|
if (!iolog_swapids(true)) {
|
||||||
|
ok = false;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dfd != -1 && fstat(dfd, &sb) != -1) {
|
||||||
|
if (S_ISDIR(sb.st_mode)) {
|
||||||
|
if (sb.st_uid != iolog_uid || sb.st_gid != iolog_gid) {
|
||||||
|
if (fchown(dfd, iolog_uid, iolog_gid) != 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((sb.st_mode & ALLPERMS) != iolog_dirmode) {
|
||||||
|
if (fchmod(dfd, iolog_dirmode) != 0) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to chmod 0%o %s", __func__,
|
||||||
|
(int)iolog_dirmode, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sudo_warnx(U_("%s exists but is not a directory (0%o)"),
|
||||||
|
path, (unsigned int) sb.st_mode);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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) {
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
/* Create final path component. */
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (!ok)
|
||||||
|
sudo_warn(U_("unable to mkdir %s"), path);
|
||||||
|
} else {
|
||||||
|
if (chown(path, iolog_uid, iolog_gid) != 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (uid_changed) {
|
||||||
|
if (!iolog_swapids(true))
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
umask(omask);
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (dfd != -1)
|
||||||
|
close(dfd);
|
||||||
|
debug_return_bool(ok);
|
||||||
|
}
|
87
lib/iolog/iolog_mkdtemp.c
Normal file
87
lib/iolog/iolog_mkdtemp.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_fatal.h"
|
||||||
|
#include "sudo_gettext.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create temporary directory and any parent directories as needed.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true);
|
||||||
|
if (!ok && 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);
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
/* 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) {
|
||||||
|
sudo_warn(U_("unable to mkdir %s"), path);
|
||||||
|
ok = false;
|
||||||
|
} else {
|
||||||
|
if (chmod(path, iolog_dirmode) != 0) {
|
||||||
|
sudo_warn(U_("unable to change mode of %s to 0%o"),
|
||||||
|
path, (unsigned int)iolog_dirmode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uid_changed) {
|
||||||
|
if (!iolog_swapids(true))
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
debug_return_bool(ok);
|
||||||
|
}
|
65
lib/iolog/iolog_mkpath.c
Normal file
65
lib/iolog/iolog_mkpath.c
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create path and any intermediate directories.
|
||||||
|
* If path ends in 'XXXXXX', use mkdtemp().
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
iolog_mkpath(char *path)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
bool ret;
|
||||||
|
debug_decl(iolog_mkpath, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create path and intermediate subdirs as needed.
|
||||||
|
* If path ends in at least 6 Xs (ala POSIX mktemp), use mkdtemp().
|
||||||
|
* Sets iolog_gid (if it is not already set) as a side effect.
|
||||||
|
*/
|
||||||
|
len = strlen(path);
|
||||||
|
if (len >= 6 && strcmp(&path[len - 6], "XXXXXX") == 0)
|
||||||
|
ret = iolog_mkdtemp(path);
|
||||||
|
else
|
||||||
|
ret = iolog_mkdirs(path);
|
||||||
|
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "iolog path %s", path);
|
||||||
|
|
||||||
|
debug_return_bool(ret);
|
||||||
|
}
|
143
lib/iolog/iolog_nextid.c
Normal file
143
lib/iolog/iolog_nextid.c
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_fatal.h"
|
||||||
|
#include "sudo_gettext.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the on-disk sequence number, set sessid to the next
|
||||||
|
* number, and update the on-disk copy.
|
||||||
|
* Uses file locking to avoid sequence number collisions.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
iolog_nextid(char *iolog_dir, char sessid[7])
|
||||||
|
{
|
||||||
|
char buf[32], *ep;
|
||||||
|
int i, len, fd = -1;
|
||||||
|
unsigned long id = 0;
|
||||||
|
ssize_t nread;
|
||||||
|
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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create I/O log directory if it doesn't already exist.
|
||||||
|
*/
|
||||||
|
if (!iolog_mkdirs(iolog_dir))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open sequence file
|
||||||
|
*/
|
||||||
|
len = snprintf(pathbuf, sizeof(pathbuf), "%s/seq", iolog_dir);
|
||||||
|
if (len < 0 || len >= ssizeof(pathbuf)) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: %s/seq", __func__, iolog_dir);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
fd = iolog_openat(AT_FDCWD, pathbuf, O_RDWR|O_CREAT);
|
||||||
|
if (fd == -1) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to open %s", __func__, pathbuf);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (!sudo_lock_file(fd, SUDO_LOCK)) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
|
"unable to lock %s", pathbuf);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (fchown(fd, iolog_uid, iolog_gid) != 0) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to fchown %d:%d %s", __func__,
|
||||||
|
(int)iolog_uid, (int)iolog_gid, pathbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read current seq number (base 36). */
|
||||||
|
nread = read(fd, buf, sizeof(buf) - 1);
|
||||||
|
if (nread != 0) {
|
||||||
|
if (nread == -1) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (buf[nread - 1] == '\n')
|
||||||
|
nread--;
|
||||||
|
buf[nread] = '\0';
|
||||||
|
id = strtoul(buf, &ep, 36);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
id++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert id to a string and stash in sessid.
|
||||||
|
* Note that that least significant digits go at the end of the string.
|
||||||
|
*/
|
||||||
|
for (i = 5; i >= 0; i--) {
|
||||||
|
buf[i] = b36char[id % 36];
|
||||||
|
id /= 36;
|
||||||
|
}
|
||||||
|
buf[6] = '\n';
|
||||||
|
|
||||||
|
/* Stash id for logging purposes. */
|
||||||
|
memcpy(sessid, buf, 6);
|
||||||
|
sessid[6] = '\0';
|
||||||
|
|
||||||
|
/* Rewind and overwrite old seq file, including the NUL byte. */
|
||||||
|
if (pwrite(fd, buf, 7, 0) != 7) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to write %s", __func__, pathbuf);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (fd != -1)
|
||||||
|
close(fd);
|
||||||
|
debug_return_bool(ret);
|
||||||
|
}
|
127
lib/iolog/iolog_open.c
Normal file
127
lib/iolog/iolog_open.c
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
|
||||||
|
static unsigned char const gzip_magic[2] = {0x1f, 0x8b};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open the specified I/O log file and store in iol.
|
||||||
|
* Stores the open file handle which has the close-on-exec flag set.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
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') {
|
||||||
|
flags = mode[1] == '+' ? O_RDWR : O_RDONLY;
|
||||||
|
} else if (mode[0] == 'w') {
|
||||||
|
flags = O_CREAT|O_TRUNC;
|
||||||
|
flags |= mode[1] == '+' ? O_RDWR : O_WRONLY;
|
||||||
|
} else {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||||
|
"%s: invalid I/O mode %s", __func__, mode);
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
if ((file = iolog_fd_to_name(iofd)) == NULL) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||||
|
"%s: invalid iofd %d", __func__, iofd);
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
iol->writable = false;
|
||||||
|
iol->compressed = false;
|
||||||
|
if (iol->enabled) {
|
||||||
|
int fd = iolog_openat(dfd, file, flags);
|
||||||
|
if (fd != -1) {
|
||||||
|
if (*mode == 'w') {
|
||||||
|
if (fchown(fd, iolog_uid, iolog_gid) != 0) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to fchown %d:%d %s", __func__,
|
||||||
|
(int)iolog_uid, (int)iolog_gid, file);
|
||||||
|
}
|
||||||
|
iol->compressed = iolog_get_compress();
|
||||||
|
} else {
|
||||||
|
/* check for gzip magic number */
|
||||||
|
if (pread(fd, magic, sizeof(magic), 0) == ssizeof(magic)) {
|
||||||
|
if (magic[0] == gzip_magic[0] && magic[1] == gzip_magic[1])
|
||||||
|
iol->compressed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fcntl(fd, F_SETFD, FD_CLOEXEC) != -1) {
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
if (iol->compressed)
|
||||||
|
iol->fd.g = gzdopen(fd, mode);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
iol->fd.f = fdopen(fd, mode);
|
||||||
|
}
|
||||||
|
if (iol->fd.v != NULL) {
|
||||||
|
switch ((flags & O_ACCMODE)) {
|
||||||
|
case O_WRONLY:
|
||||||
|
case O_RDWR:
|
||||||
|
iol->writable = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int save_errno = errno;
|
||||||
|
close(fd);
|
||||||
|
errno = save_errno;
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fd == -1) {
|
||||||
|
iol->enabled = false;
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (*mode == 'w') {
|
||||||
|
/* Remove old log file in case we recycled sequence numbers. */
|
||||||
|
(void)unlinkat(dfd, file, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_return_bool(true);
|
||||||
|
}
|
90
lib/iolog/iolog_openat.c
Normal file
90
lib/iolog/iolog_openat.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_fatal.h"
|
||||||
|
#include "sudo_gettext.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper for openat(2) that sets umask and retries as iolog_uid/iolog_gid
|
||||||
|
* if openat(2) returns EACCES.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
iolog_openat(int dfd, const char *path, int flags)
|
||||||
|
{
|
||||||
|
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)) {
|
||||||
|
/* umask must not be more restrictive than the file modes. */
|
||||||
|
omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
|
||||||
|
}
|
||||||
|
fd = openat(dfd, path, flags, iolog_filemode);
|
||||||
|
if (fd == -1 && errno == EACCES) {
|
||||||
|
/* Enable write bit if it is missing. */
|
||||||
|
struct stat sb;
|
||||||
|
if (fstatat(dfd, path, &sb, 0) == 0) {
|
||||||
|
mode_t write_bits = iolog_filemode & (S_IWUSR|S_IWGRP|S_IWOTH);
|
||||||
|
if ((sb.st_mode & write_bits) != write_bits) {
|
||||||
|
if (fchmodat(dfd, path, iolog_filemode, 0) == 0)
|
||||||
|
fd = openat(dfd, path, flags, iolog_filemode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fd == -1 && errno == EACCES) {
|
||||||
|
/* Try again as the I/O log owner (for NFS). */
|
||||||
|
if (iolog_swapids(false)) {
|
||||||
|
fd = openat(dfd, path, flags, iolog_filemode);
|
||||||
|
if (!iolog_swapids(true)) {
|
||||||
|
/* iolog_swapids() warns on error. */
|
||||||
|
if (fd != -1) {
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ISSET(flags, O_CREAT))
|
||||||
|
umask(omask);
|
||||||
|
debug_return_int(fd);
|
||||||
|
}
|
79
lib/iolog/iolog_read.c
Normal file
79
lib/iolog/iolog_read.c
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read from a (possibly compressed) I/O log file.
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
iolog_read(struct iolog_file *iol, void *buf, size_t nbytes,
|
||||||
|
const char **errstr)
|
||||||
|
{
|
||||||
|
ssize_t nread;
|
||||||
|
debug_decl(iolog_read, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
if (nbytes > UINT_MAX) {
|
||||||
|
errno = EINVAL;
|
||||||
|
if (errstr != NULL)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
debug_return_ssize_t(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
if (iol->compressed) {
|
||||||
|
if ((nread = gzread(iol->fd.g, buf, nbytes)) == -1) {
|
||||||
|
if (errstr != NULL) {
|
||||||
|
int errnum;
|
||||||
|
*errstr = gzerror(iol->fd.g, &errnum);
|
||||||
|
if (errnum == Z_ERRNO)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
nread = (ssize_t)fread(buf, 1, nbytes, iol->fd.f);
|
||||||
|
if (nread == 0 && ferror(iol->fd.f)) {
|
||||||
|
nread = -1;
|
||||||
|
if (errstr != NULL)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_return_ssize_t(nread);
|
||||||
|
}
|
69
lib/iolog/iolog_seek.c
Normal file
69
lib/iolog/iolog_seek.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I/O log wrapper for fseek/gzseek.
|
||||||
|
*/
|
||||||
|
off_t
|
||||||
|
iolog_seek(struct iolog_file *iol, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
off_t ret;
|
||||||
|
//debug_decl(iolog_seek, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
if (iol->compressed)
|
||||||
|
ret = gzseek(iol->fd.g, offset, whence);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ret = fseeko(iol->fd.f, offset, whence);
|
||||||
|
|
||||||
|
//debug_return_off_t(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I/O log wrapper for rewind/gzrewind.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
iolog_rewind(struct iolog_file *iol)
|
||||||
|
{
|
||||||
|
debug_decl(iolog_rewind, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
if (iol->compressed)
|
||||||
|
(void)gzrewind(iol->fd.g);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
rewind(iol->fd.f);
|
||||||
|
|
||||||
|
debug_return;
|
||||||
|
}
|
95
lib/iolog/iolog_swapids.c
Normal file
95
lib/iolog/iolog_swapids.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_fatal.h"
|
||||||
|
#include "sudo_gettext.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set effective user and group-IDs to iolog_uid and iolog_gid.
|
||||||
|
* If restore flag is set, swap them back.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
iolog_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)
|
||||||
|
user_euid = geteuid();
|
||||||
|
if (user_egid == (gid_t)-1)
|
||||||
|
user_egid = getegid();
|
||||||
|
|
||||||
|
if (restore) {
|
||||||
|
if (seteuid(user_euid) == -1) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to restore effective uid to %d", __func__,
|
||||||
|
(int)user_euid);
|
||||||
|
sudo_warn("seteuid() %d -> %d", (int)iolog_uid, (int)user_euid);
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
if (setegid(user_egid) == -1) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to restore effective gid to %d", __func__,
|
||||||
|
(int)user_egid);
|
||||||
|
sudo_warn("setegid() %d -> %d", (int)iolog_gid, (int)user_egid);
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Fail silently if the user has insufficient privileges. */
|
||||||
|
if (setegid(iolog_gid) == -1) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to set effective gid to %d", __func__,
|
||||||
|
(int)iolog_gid);
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
if (seteuid(iolog_uid) == -1) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to set effective uid to %d", __func__,
|
||||||
|
(int)iolog_uid);
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_return_bool(true);
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
74
lib/iolog/iolog_util.c
Normal file
74
lib/iolog/iolog_util.c
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map IOFD_* -> name.
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
iolog_fd_to_name(int iofd)
|
||||||
|
{
|
||||||
|
const char *ret;
|
||||||
|
debug_decl(iolog_fd_to_name, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
switch (iofd) {
|
||||||
|
case IOFD_STDIN:
|
||||||
|
ret = "stdin";
|
||||||
|
break;
|
||||||
|
case IOFD_STDOUT:
|
||||||
|
ret = "stdout";
|
||||||
|
break;
|
||||||
|
case IOFD_STDERR:
|
||||||
|
ret = "stderr";
|
||||||
|
break;
|
||||||
|
case IOFD_TTYIN:
|
||||||
|
ret = "ttyin";
|
||||||
|
break;
|
||||||
|
case IOFD_TTYOUT:
|
||||||
|
ret = "ttyout";
|
||||||
|
break;
|
||||||
|
case IOFD_TIMING:
|
||||||
|
ret = "timing";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = "unknown";
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: unexpected iofd %d",
|
||||||
|
__func__, iofd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug_return_const_str(ret);
|
||||||
|
}
|
105
lib/iolog/iolog_write.c
Normal file
105
lib/iolog/iolog_write.c
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: ISC
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2021 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
|
||||||
|
* 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 <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_STDBOOL_H
|
||||||
|
# include <stdbool.h>
|
||||||
|
#else
|
||||||
|
# include "compat/stdbool.h"
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "sudo_compat.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_iolog.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write to an I/O log, optionally compressing.
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
iolog_write(struct iolog_file *iol, const void *buf, size_t len,
|
||||||
|
const char **errstr)
|
||||||
|
{
|
||||||
|
ssize_t ret;
|
||||||
|
debug_decl(iolog_write, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
if (len > UINT_MAX) {
|
||||||
|
errno = EINVAL;
|
||||||
|
if (errstr != NULL)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
debug_return_ssize_t(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
if (iol->compressed) {
|
||||||
|
int errnum;
|
||||||
|
|
||||||
|
ret = gzwrite(iol->fd.g, (const voidp)buf, len);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = -1;
|
||||||
|
if (errstr != NULL) {
|
||||||
|
*errstr = gzerror(iol->fd.g, &errnum);
|
||||||
|
if (errnum == Z_ERRNO)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (iolog_get_flush()) {
|
||||||
|
if (gzflush(iol->fd.g, Z_SYNC_FLUSH) != Z_OK) {
|
||||||
|
ret = -1;
|
||||||
|
if (errstr != NULL) {
|
||||||
|
*errstr = gzerror(iol->fd.g, &errnum);
|
||||||
|
if (errnum == Z_ERRNO)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
ret = fwrite(buf, 1, len, iol->fd.f);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = -1;
|
||||||
|
if (errstr != NULL)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (iolog_get_flush()) {
|
||||||
|
if (fflush(iol->fd.f) != 0) {
|
||||||
|
ret = -1;
|
||||||
|
if (errstr != NULL)
|
||||||
|
*errstr = strerror(errno);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
debug_return_ssize_t(ret);
|
||||||
|
}
|
@ -91,3 +91,10 @@ cleanup:
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* STUB */
|
||||||
|
bool
|
||||||
|
iolog_swapids(bool restore)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -727,6 +727,29 @@ iolog_copy(struct iolog_file *src, struct iolog_file *dst, off_t remainder,
|
|||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like rename(2) but changes UID as needed.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
iolog_rename(const char *from, const char *to)
|
||||||
|
{
|
||||||
|
bool ok, uid_changed = false;
|
||||||
|
debug_decl(iolog_rename, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
ok = rename(from, to) == 0;
|
||||||
|
if (!ok && errno == EACCES) {
|
||||||
|
uid_changed = iolog_swapids(false);
|
||||||
|
if (uid_changed)
|
||||||
|
ok = rename(from, to) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uid_changed) {
|
||||||
|
if (!iolog_swapids(true))
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
debug_return_bool(ok);
|
||||||
|
}
|
||||||
|
|
||||||
/* Compressed logs don't support random access, need to rewrite them. */
|
/* Compressed logs don't support random access, need to rewrite them. */
|
||||||
static bool
|
static bool
|
||||||
iolog_rewrite(const struct timespec *target, struct connection_closure *closure)
|
iolog_rewrite(const struct timespec *target, struct connection_closure *closure)
|
||||||
|
@ -74,45 +74,3 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
iolog_set_defaults(void)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
iolog_set_maxseq(unsigned int newval)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
iolog_set_owner(uid_t uid, gid_t gid)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
iolog_set_gid(gid_t gid)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
iolog_set_mode(mode_t mode)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
iolog_set_compress(bool newval)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
iolog_set_flush(bool newval)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user