will be truncated and overwritten unless _\bi_\bo_\bl_\bo_\bg_\b__\bf_\bi_\bl_\be
ends in six or more Xs.
+ iolog_flush If set, s\bsu\bud\bdo\bo 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 _\bo_\bf_\bf
+ 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
_\bs_\bt_\bd_\be_\br_\br standard error to a pipe or redirected to a file
All files other than _\bl_\bo_\bg are compressed in gzip format unless the
- _\bc_\bo_\bm_\bp_\br_\be_\bs_\bs_\b__\bi_\bo 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 s\bsu\bud\bdo\bo 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.
+ _\bc_\bo_\bm_\bp_\br_\be_\bs_\bs_\b__\bi_\bo 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 s\bsu\bud\bdo\bo has
+ exited or has been terminated by a signal. The _\bi_\bo_\bl_\bo_\bg_\b__\bf_\bl_\bu_\bs_\bh 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
file distributed with s\bsu\bud\bdo\bo 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
.\" 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"
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.
\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.
.\" 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
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.
.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.
"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
}
#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,
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"
/*
* 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,
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[],
/*
* 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) {
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;
/* Ignore errors if they occur if the policy says so. */
if (iolog_details.ignore_iolog_errors)
- ret = true;
+ ret = 1;
}
debug_return_int(ret);