Add iolog_flush option.

This commit is contained in:
Todd C. Miller
2017-03-20 10:25:58 -06:00
parent 8c8d078f66
commit c4e703696a
7 changed files with 144 additions and 49 deletions

View File

@@ -1615,6 +1615,16 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS
will be truncated and overwritten unless _i_o_l_o_g___f_i_l_e
ends in six or more Xs.
iolog_flush If set, ssuuddoo will flush I/O log data to disk after each
write instead of buffering it. This makes it possible
to view the logs in real-time as the program is
executing but may significantly reduce the
effectiveness of I/O log compression. This flag is _o_f_f
by default.
This setting is only supported by version 1.8.20 or
higher.
iolog_group The group name to look up when setting the group ID on
new I/O log files and directories. By default, I/O log
files and directories inherit the group ID of the
@@ -2241,12 +2251,14 @@ II//OO LLOOGG FFIILLEESS
_s_t_d_e_r_r standard error to a pipe or redirected to a file
All files other than _l_o_g are compressed in gzip format unless the
_c_o_m_p_r_e_s_s___i_o option has been disabled. Due to buffering, it is not
possible to display the I/O logs in real-time as the program is
executing. The I/O log data will not be complete until the program run
by ssuuddoo has exited or has been terminated by a signal. The output
portion of an I/O log file can be viewed with the sudoreplay(1m) utility,
which can also be used to list or search the available logs.
_c_o_m_p_r_e_s_s___i_o flag has been disabled. Due to buffering, it is not normally
possible to display the I/O logs in real-time as the program is executing
The I/O log data will not be complete until the program run by ssuuddoo has
exited or has been terminated by a signal. The _i_o_l_o_g___f_l_u_s_h flag can be
used to disable buffering, in which case I/O log data is written to disk
as soon as it is available. The output portion of an I/O log file can be
viewed with the sudoreplay(1m) utility, which can also be used to list or
search the available logs.
Note that user input may contain sensitive information such as passwords
(even if they are not echoed to the screen), which will be stored in the
@@ -2748,4 +2760,4 @@ DDIISSCCLLAAIIMMEERR
file distributed with ssuuddoo or https://www.sudo.ws/license.html for
complete details.
Sudo 1.8.20 March 17, 2017 Sudo 1.8.20
Sudo 1.8.20 March 20, 2017 Sudo 1.8.20

View File

@@ -21,7 +21,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
.TH "SUDOERS" "5" "March 17, 2017" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.TH "SUDOERS" "5" "March 20, 2017" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -3315,6 +3315,19 @@ ends in six or
more
\fRX\fRs.
.TP 18n
iolog_flush
If set,
\fBsudo\fR
will flush I/O log data to disk after each write instead of buffering it.
This makes it possible to view the logs in real-time as the program
is executing but may significantly reduce the effectiveness of I/O
log compression.
This flag is
\fIoff\fR
by default.
.sp
This setting is only supported by version 1.8.20 or higher.
.TP 18n
iolog_group
The group name to look up when setting the group ID on new I/O log
files and directories.
@@ -4467,12 +4480,16 @@ All files other than
\fIlog\fR
are compressed in gzip format unless the
\fIcompress_io\fR
option has been disabled.
Due to buffering, it is not possible to display the I/O logs in
real-time as the program is executing.
flag has been disabled.
Due to buffering, it is not normally possible to display the I/O logs in
real-time as the program is executing
The I/O log data will not be complete until the program run by
\fBsudo\fR
has exited or has been terminated by a signal.
The
\fIiolog_flush\fR
flag can be used to disable buffering, in which case I/O log data
is written to disk as soon as it is available.
The output portion of an I/O log file can be viewed with the
sudoreplay(@mansectsu@)
utility, which can also be used to list or search the available logs.

View File

@@ -19,7 +19,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
.Dd March 17, 2017
.Dd March 20, 2017
.Dt SUDOERS @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@@ -3109,6 +3109,18 @@ overwritten unless
ends in six or
more
.Li X Ns s .
.It iolog_flush
If set,
.Nm sudo
will flush I/O log data to disk after each write instead of buffering it.
This makes it possible to view the logs in real-time as the program
is executing but may significantly reduce the effectiveness of I/O
log compression.
This flag is
.Em off
by default.
.Pp
This setting is only supported by version 1.8.20 or higher.
.It iolog_group
The group name to look up when setting the group ID on new I/O log
files and directories.
@@ -4148,12 +4160,16 @@ All files other than
.Pa log
are compressed in gzip format unless the
.Em compress_io
option has been disabled.
Due to buffering, it is not possible to display the I/O logs in
real-time as the program is executing.
flag has been disabled.
Due to buffering, it is not normally possible to display the I/O logs in
real-time as the program is executing
The I/O log data will not be complete until the program run by
.Nm sudo
has exited or has been terminated by a signal.
The
.Em iolog_flush
flag can be used to disable buffering, in which case I/O log data
is written to disk as soon as it is available.
The output portion of an I/O log file can be viewed with the
.Xr sudoreplay @mansectsu@
utility, which can also be used to list or search the available logs.

View File

@@ -457,6 +457,10 @@ struct sudo_defs_types sudo_defs_table[] = {
"user_command_timeouts", T_FLAG,
N_("Allow the user to specify a timeout on the command line"),
NULL,
}, {
"iolog_flush", T_FLAG,
N_("Flush I/O log data to disk immediately instead of buffering it"),
NULL,
}, {
NULL, 0, NULL
}

View File

@@ -212,6 +212,8 @@
#define def_command_timeout (sudo_defs_table[I_COMMAND_TIMEOUT].sd_un.ival)
#define I_USER_COMMAND_TIMEOUTS 106
#define def_user_command_timeouts (sudo_defs_table[I_USER_COMMAND_TIMEOUTS].sd_un.flag)
#define I_IOLOG_FLUSH 107
#define def_iolog_flush (sudo_defs_table[I_IOLOG_FLUSH].sd_un.flag)
enum def_tuple {
never,

View File

@@ -335,3 +335,6 @@ command_timeout
user_command_timeouts
T_FLAG
"Allow the user to specify a timeout on the command line"
iolog_flush
T_FLAG
"Flush I/O log data to disk immediately instead of buffering it"

View File

@@ -710,6 +710,7 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
/*
* Write the "/log" file that contains the user and command info.
* This file is not compressed.
*/
static bool
write_info_log(char *pathbuf, size_t len, struct iolog_details *details,
@@ -748,6 +749,57 @@ write_info_log(char *pathbuf, size_t len, struct iolog_details *details,
debug_return_bool(ret);
}
#ifdef HAVE_ZLIB_H
static const char *
gzstrerror(gzFile file)
{
int errnum;
return gzerror(file, &errnum);
}
#endif /* HAVE_ZLIB_H */
/*
* Write to an I/O log, compressing if iolog_compress is enabled.
* If def_iolog_flush is true, flush the buffer immediately.
*/
static const char *
iolog_write(const void *buf, unsigned int len, int idx)
{
const char *errstr = NULL;
debug_decl(iolog_write, SUDOERS_DEBUG_PLUGIN)
#ifdef HAVE_ZLIB_H
if (iolog_compress) {
if (gzwrite(io_log_files[idx].fd.g, buf, len) != (int)len) {
errstr = gzstrerror(io_log_files[idx].fd.g);
goto done;
}
if (def_iolog_flush) {
if (gzflush(io_log_files[idx].fd.g, Z_SYNC_FLUSH) != Z_OK) {
errstr = gzstrerror(io_log_files[idx].fd.g);
goto done;
}
}
} else
#endif
{
if (fwrite(buf, 1, len, io_log_files[idx].fd.f) != len) {
errstr = strerror(errno);
goto done;
}
if (def_iolog_flush) {
if (fflush(io_log_files[idx].fd.f) != 0) {
errstr = strerror(errno);
goto done;
}
}
}
done:
debug_return_const_str(errstr);
}
static int
sudoers_io_open(unsigned int version, sudo_conv_t conversation,
sudo_printf_t plugin_printf, char * const settings[],
@@ -915,13 +967,15 @@ sudoers_io_version(int verbose)
/*
* Generic I/O logging function. Called by the I/O logging entry points.
* Returns 1 on success and -1 on error.
*/
static int
sudoers_io_log(const char *buf, unsigned int len, int idx)
{
struct timeval now, delay;
char tbuf[1024];
const char *errstr = NULL;
int ret = true;
int ret = -1;
debug_decl(sudoers_io_version, SUDOERS_DEBUG_PLUGIN)
if (io_log_files[idx].fd.v == NULL) {
@@ -932,41 +986,28 @@ sudoers_io_log(const char *buf, unsigned int len, int idx)
gettimeofday(&now, NULL);
#ifdef HAVE_ZLIB_H
if (iolog_compress) {
if (gzwrite(io_log_files[idx].fd.g, (const voidp)buf, len) != (int)len) {
int errnum;
/* Write I/O log file entry. */
errstr = iolog_write(buf, len, idx);
if (errstr != NULL)
goto done;
errstr = gzerror(io_log_files[idx].fd.g, &errnum);
ret = -1;
}
} else
#endif
{
if (fwrite(buf, 1, len, io_log_files[idx].fd.f) != len) {
errstr = strerror(errno);
ret = -1;
}
}
/* Write timing file entry. */
sudo_timevalsub(&now, &last_time, &delay);
#ifdef HAVE_ZLIB_H
if (iolog_compress) {
if (gzprintf(io_log_files[IOFD_TIMING].fd.g, "%d %f %u\n", idx,
delay.tv_sec + ((double)delay.tv_usec / 1000000), len) == 0) {
int errnum;
errstr = gzerror(io_log_files[IOFD_TIMING].fd.g, &errnum);
ret = -1;
}
} else
#endif
{
if (fprintf(io_log_files[IOFD_TIMING].fd.f, "%d %f %u\n", idx,
delay.tv_sec + ((double)delay.tv_usec / 1000000), len) < 0) {
errstr = strerror(errno);
ret = -1;
}
len = (unsigned int)snprintf(tbuf, sizeof(tbuf), "%d %f %u\n", idx,
delay.tv_sec + ((double)delay.tv_usec / 1000000), len);
if (len >= sizeof(tbuf)) {
/* Not actually possible due to the size of tbuf[]. */
errstr = strerror(EOVERFLOW);
goto done;
}
errstr = iolog_write(tbuf, len, IOFD_TIMING);
if (errstr != NULL)
goto done;
/* Success. */
ret = 1;
done:
last_time.tv_sec = now.tv_sec;
last_time.tv_usec = now.tv_usec;
@@ -980,7 +1021,7 @@ sudoers_io_log(const char *buf, unsigned int len, int idx)
/* Ignore errors if they occur if the policy says so. */
if (iolog_details.ignore_iolog_errors)
ret = true;
ret = 1;
}
debug_return_int(ret);