Blame SOURCES/sudo-1.8.19p2-iologflush.patch

0e1944
diff -up ./doc/sudoers.cat.orig ./doc/sudoers.cat
0e1944
--- ./doc/sudoers.cat.orig	2017-03-21 13:31:00.953951199 +0100
0e1944
+++ ./doc/sudoers.cat	2017-03-21 14:14:18.679116865 +0100
0e1944
@@ -1549,6 +1549,16 @@ S?SU?UD?DO?OE?ER?RS?S O?OP?PT?TI?IO?ON?N
0e1944
                        will be truncated and overwritten unless _?i_?o_?l_?o_?g_?__?f_?i_?l_?e
0e1944
                        ends in six or more Xs.
0e1944
 
0e1944
+     iolog_flush       If set, s?su?ud?do?o will flush I/O log data to disk after each
0e1944
+                       write instead of buffering it.  This makes it possible
0e1944
+                       to view the logs in real-time as the program is
0e1944
+                       executing but may significantly reduce the
0e1944
+                       effectiveness of I/O log compression.  This flag is _?o_?f_?f
0e1944
+                       by default.
0e1944
+
0e1944
+                       This setting is only supported by version 1.8.20 or
0e1944
+                       higher.
0e1944
+
0e1944
      iolog_group       The group name to look up when setting the group ID on
0e1944
                        new I/O log files and directories.  By default, I/O log
0e1944
                        files and directories inherit the group ID of the
0e1944
@@ -2141,10 +2151,14 @@ I?I/?/O?O L?LO?OG?G F?FI?IL?LE?ES?S
0e1944
      _?s_?t_?d_?e_?r_?r    standard error to a pipe or redirected to a file
0e1944
 
0e1944
      All files other than _?l_?o_?g are compressed in gzip format unless the
0e1944
-     _?c_?o_?m_?p_?r_?e_?s_?s_?__?i_?o option has been disabled.  Due to buffering, the I/O log data
0e1944
-     will not be complete until the s?su?ud?do?o command has completed.  The output
0e1944
-     portion of an I/O log file can be viewed with the sudoreplay(1m) utility,
0e1944
-     which can also be used to list or search the available logs.
0e1944
+     _?c_?o_?m_?p_?r_?e_?s_?s_?__?i_?o flag has been disabled.  Due to buffering, it is not normally
0e1944
+     possible to display the I/O logs in real-time as the program is executing
0e1944
+     The I/O log data will not be complete until the program run by s?su?ud?do?o has
0e1944
+     exited or has been terminated by a signal.  The _?i_?o_?l_?o_?g_?__?f_?l_?u_?s_?h flag can be
0e1944
+     used to disable buffering, in which case I/O log data is written to disk
0e1944
+     as soon as it is available.  The output portion of an I/O log file can be
0e1944
+     viewed with the sudoreplay(1m) utility, which can also be used to list or
0e1944
+     search the available logs.
0e1944
 
0e1944
      Note that user input may contain sensitive information such as passwords
0e1944
      (even if they are not echoed to the screen), which will be stored in the
0e1944
diff -up ./doc/sudoers.man.in.orig ./doc/sudoers.man.in
0e1944
--- ./doc/sudoers.man.in.orig	2017-03-21 14:22:33.804283190 +0100
0e1944
+++ ./doc/sudoers.man.in	2017-03-21 14:22:21.136664667 +0100
0e1944
@@ -3199,6 +3199,19 @@ ends in six or
0e1944
 more
0e1944
 \fRX\fRs.
0e1944
 .TP 18n
0e1944
+iolog_flush
0e1944
+If set,
0e1944
+\fBsudo\fR
0e1944
+will flush I/O log data to disk after each write instead of buffering it.
0e1944
+This makes it possible to view the logs in real-time as the program
0e1944
+is executing but may significantly reduce the effectiveness of I/O
0e1944
+log compression.
0e1944
+This flag is
0e1944
+\fIoff\fR
0e1944
+by default.
0e1944
+.sp
0e1944
+This setting is only supported by version 1.8.20 or higher.
0e1944
+.TP 18n
0e1944
 iolog_group
0e1944
 The group name to look up when setting the group ID on new I/O log
0e1944
 files and directories.
0e1944
@@ -4298,10 +4311,16 @@ All files other than
0e1944
 \fIlog\fR
0e1944
 are compressed in gzip format unless the
0e1944
 \fIcompress_io\fR
0e1944
-option has been disabled.
0e1944
-Due to buffering, the I/O log data will not be complete until the
0e1944
+flag has been disabled.
0e1944
+Due to buffering, it is not normally possible to display the I/O logs in
0e1944
+real-time as the program is executing
0e1944
+The I/O log data will not be complete until the program run by
0e1944
 \fBsudo\fR
0e1944
-command has completed.
0e1944
+has exited or has been terminated by a signal.
0e1944
+The
0e1944
+\fIiolog_flush\fR
0e1944
+flag can be used to disable buffering, in which case I/O log data
0e1944
+is written to disk as soon as it is available.
0e1944
 The output portion of an I/O log file can be viewed with the
0e1944
 sudoreplay(@mansectsu@)
0e1944
 utility, which can also be used to list or search the available logs.
0e1944
diff -up ./doc/sudoers.mdoc.in.orig ./doc/sudoers.mdoc.in
0e1944
--- ./doc/sudoers.mdoc.in.orig	2017-03-21 14:23:46.652089432 +0100
0e1944
+++ ./doc/sudoers.mdoc.in	2017-03-21 14:26:43.686758162 +0100
0e1944
@@ -2998,6 +2998,18 @@ overwritten unless
0e1944
 ends in six or
0e1944
 more
0e1944
 .Li X Ns s .
0e1944
+.It iolog_flush
0e1944
+If set,
0e1944
+.Nm sudo
0e1944
+will flush I/O log data to disk after each write instead of buffering it.
0e1944
+This makes it possible to view the logs in real-time as the program
0e1944
+is executing but may significantly reduce the effectiveness of I/O
0e1944
+log compression.
0e1944
+This flag is
0e1944
+.Em off
0e1944
+by default.
0e1944
+.Pp
0e1944
+This setting is only supported by version 1.8.20 or higher.
0e1944
 .It iolog_group
0e1944
 The group name to look up when setting the group ID on new I/O log
0e1944
 files and directories.
0e1944
@@ -3991,10 +4003,16 @@ All files other than
0e1944
 .Pa log
0e1944
 are compressed in gzip format unless the
0e1944
 .Em compress_io
0e1944
-option has been disabled.
0e1944
-Due to buffering, the I/O log data will not be complete until the
0e1944
-.Nm sudo
0e1944
-command has completed.
0e1944
+flag has been disabled.
0e1944
+Due to buffering, it is not normally possible to display the I/O logs in
0e1944
+real-time as the program is executing
0e1944
+The I/O log data will not be complete until the program run by
0e1944
+.Nm sudo
0e1944
+has exited or has been terminated by a signal.
0e1944
+The
0e1944
+.Em iolog_flush
0e1944
+flag can be used to disable buffering, in which case I/O log data
0e1944
+is written to disk as soon as it is available.
0e1944
 The output portion of an I/O log file can be viewed with the
0e1944
 .Xr sudoreplay @mansectsu@
0e1944
 utility, which can also be used to list or search the available logs.
0e1944
diff -up ./plugins/sudoers/def_data.c.orig ./plugins/sudoers/def_data.c
0e1944
--- ./plugins/sudoers/def_data.c.orig	2017-03-21 13:24:10.682064806 +0100
0e1944
+++ ./plugins/sudoers/def_data.c	2017-03-21 13:25:09.805322057 +0100
0e1944
@@ -447,6 +447,10 @@ struct sudo_defs_types sudo_defs_table[]
0e1944
        N_("Ignore unknown Defaults entries in sudoers instead of producing a warning"),
0e1944
        NULL,
0e1944
     }, {
0e1944
+	"iolog_flush", T_FLAG,
0e1944
+	N_("Flush I/O log data to disk immediately instead of buffering it"),
0e1944
+	NULL,
0e1944
+    }, {
0e1944
 	NULL, 0, NULL
0e1944
     }
0e1944
 };
0e1944
diff -up ./plugins/sudoers/def_data.h.orig ./plugins/sudoers/def_data.h
0e1944
--- ./plugins/sudoers/def_data.h.orig	2017-03-21 13:25:20.489006524 +0100
0e1944
+++ ./plugins/sudoers/def_data.h	2017-03-21 13:28:09.251022290 +0100
0e1944
@@ -210,6 +210,8 @@
0e1944
 #define def_legacy_group_processing (sudo_defs_table[I_LEGACY_GROUP_PROCESSING].sd_un.flag)
0e1944
 #define I_IGNORE_UNKNOWN_DEFAULTS 105
0e1944
 #define def_ignore_unknown_defaults (sudo_defs_table[I_IGNORE_UNKNOWN_DEFAULTS].sd_un.flag)
0e1944
+#define I_IOLOG_FLUSH           106
0e1944
+#define def_iolog_flush         (sudo_defs_table[I_IOLOG_FLUSH].sd_un.flag)
0e1944
 
0e1944
 enum def_tuple {
0e1944
 	never,
0e1944
diff -up ./plugins/sudoers/def_data.in.orig ./plugins/sudoers/def_data.in
0e1944
--- ./plugins/sudoers/def_data.in.orig	2017-03-21 13:28:35.115258413 +0100
0e1944
+++ ./plugins/sudoers/def_data.in	2017-03-21 13:30:03.239655739 +0100
0e1944
@@ -331,3 +331,6 @@ legacy_group_processing
0e1944
 ignore_unknown_defaults
0e1944
         T_FLAG
0e1944
         "Ignore unknown Defaults entries in sudoers instead of producing a warning"
0e1944
+iolog_flush
0e1944
+	T_FLAG
0e1944
+	"Flush I/O log data to disk immediately instead of buffering it"
0e1944
diff -up ./plugins/sudoers/iolog.c.orig ./plugins/sudoers/iolog.c
0e1944
--- ./plugins/sudoers/iolog.c.orig	2017-03-21 13:12:39.471464160 +0100
0e1944
+++ ./plugins/sudoers/iolog.c	2017-03-21 13:21:49.279230759 +0100
0e1944
@@ -709,6 +709,7 @@ iolog_deserialize_info(struct iolog_deta
0e1944
 
0e1944
 /*
0e1944
  * Write the "/log" file that contains the user and command info.
0e1944
+ * This file is not compressed.
0e1944
  */
0e1944
 static bool
0e1944
 write_info_log(char *pathbuf, size_t len, struct iolog_details *details,
0e1944
@@ -747,6 +748,57 @@ write_info_log(char *pathbuf, size_t len
0e1944
     debug_return_bool(ret);
0e1944
 }
0e1944
 
0e1944
+#ifdef HAVE_ZLIB_H
0e1944
+static const char *
0e1944
+gzstrerror(gzFile file)
0e1944
+{
0e1944
+    int errnum;
0e1944
+
0e1944
+    return gzerror(file, &errnum);
0e1944
+}
0e1944
+#endif /* HAVE_ZLIB_H */
0e1944
+
0e1944
+/*
0e1944
+ * Write to an I/O log, compressing if iolog_compress is enabled.
0e1944
+ * If def_iolog_flush is true, flush the buffer immediately.
0e1944
+ */
0e1944
+static const char *
0e1944
+iolog_write(const void *buf, unsigned int len, int idx)
0e1944
+{
0e1944
+    const char *errstr = NULL;
0e1944
+    debug_decl(iolog_write, SUDOERS_DEBUG_PLUGIN)
0e1944
+
0e1944
+#ifdef HAVE_ZLIB_H
0e1944
+    if (iolog_compress) {
0e1944
+	if (gzwrite(io_log_files[idx].fd.g, buf, len) != (int)len) {
0e1944
+	    errstr = gzstrerror(io_log_files[idx].fd.g);
0e1944
+	    goto done;
0e1944
+	}
0e1944
+	if (def_iolog_flush) {
0e1944
+	    if (gzflush(io_log_files[idx].fd.g, Z_SYNC_FLUSH) != Z_OK) {
0e1944
+		errstr = gzstrerror(io_log_files[idx].fd.g);
0e1944
+		goto done;
0e1944
+	    }
0e1944
+	}
0e1944
+    } else
0e1944
+#endif
0e1944
+    {
0e1944
+	if (fwrite(buf, 1, len, io_log_files[idx].fd.f) != len) {
0e1944
+	    errstr = strerror(errno);
0e1944
+	    goto done;
0e1944
+	}
0e1944
+	if (def_iolog_flush) {
0e1944
+	    if (fflush(io_log_files[idx].fd.f) != 0) {
0e1944
+		errstr = strerror(errno);
0e1944
+		goto done;
0e1944
+	    }
0e1944
+	}
0e1944
+    }
0e1944
+
0e1944
+done:
0e1944
+    debug_return_const_str(errstr);
0e1944
+}
0e1944
+
0e1944
 static int
0e1944
 sudoers_io_open(unsigned int version, sudo_conv_t conversation,
0e1944
     sudo_printf_t plugin_printf, char * const settings[],
0e1944
@@ -914,13 +966,15 @@ sudoers_io_version(int verbose)
0e1944
 
0e1944
 /*
0e1944
  * Generic I/O logging function.  Called by the I/O logging entry points.
0e1944
+ * Returns 1 on success and -1 on error.
0e1944
  */
0e1944
 static int
0e1944
 sudoers_io_log(const char *buf, unsigned int len, int idx)
0e1944
 {
0e1944
     struct timeval now, delay;
0e1944
+    char tbuf[1024];
0e1944
     const char *errstr = NULL;
0e1944
-    int ret = true;
0e1944
+    int ret = -1;
0e1944
     debug_decl(sudoers_io_version, SUDOERS_DEBUG_PLUGIN)
0e1944
 
0e1944
     if (io_log_files[idx].fd.v == NULL) {
0e1944
@@ -931,41 +985,28 @@ sudoers_io_log(const char *buf, unsigned
0e1944
 
0e1944
     gettimeofday(&now, NULL);
0e1944
 
0e1944
-#ifdef HAVE_ZLIB_H
0e1944
-    if (iolog_compress) {
0e1944
-	if (gzwrite(io_log_files[idx].fd.g, (const voidp)buf, len) != (int)len) {
0e1944
-	    int errnum;
0e1944
+    /* Write I/O log file entry. */
0e1944
+    errstr = iolog_write(buf, len, idx);
0e1944
+    if (errstr != NULL)
0e1944
+	goto done;
0e1944
 
0e1944
-	    errstr = gzerror(io_log_files[idx].fd.g, &errnum);
0e1944
-	    ret = -1;
0e1944
-	}
0e1944
-    } else
0e1944
-#endif
0e1944
-    {
0e1944
-	if (fwrite(buf, 1, len, io_log_files[idx].fd.f) != len) {
0e1944
-	    errstr = strerror(errno);
0e1944
-	    ret = -1;
0e1944
-	}
0e1944
-    }
0e1944
+    /* Write timing file entry. */
0e1944
     sudo_timevalsub(&now, &last_time, &delay);
0e1944
-#ifdef HAVE_ZLIB_H
0e1944
-    if (iolog_compress) {
0e1944
-	if (gzprintf(io_log_files[IOFD_TIMING].fd.g, "%d %f %u\n", idx,
0e1944
-	    delay.tv_sec + ((double)delay.tv_usec / 1000000), len) == 0) {
0e1944
-	    int errnum;
0e1944
-
0e1944
-	    errstr = gzerror(io_log_files[IOFD_TIMING].fd.g, &errnum);
0e1944
-	    ret = -1;
0e1944
-	}
0e1944
-    } else
0e1944
-#endif
0e1944
-    {
0e1944
-	if (fprintf(io_log_files[IOFD_TIMING].fd.f, "%d %f %u\n", idx,
0e1944
-	    delay.tv_sec + ((double)delay.tv_usec / 1000000), len) < 0) {
0e1944
-	    errstr = strerror(errno);
0e1944
-	    ret = -1;
0e1944
-	}
0e1944
+    len = (unsigned int)snprintf(tbuf, sizeof(tbuf), "%d %f %u\n", idx,
0e1944
+	delay.tv_sec + ((double)delay.tv_usec / 1000000), len);
0e1944
+    if (len >= sizeof(tbuf)) {
0e1944
+	/* Not actually possible due to the size of tbuf[]. */
0e1944
+	errstr = strerror(EOVERFLOW);
0e1944
+	goto done;
0e1944
     }
0e1944
+    errstr = iolog_write(tbuf, len, IOFD_TIMING);
0e1944
+    if (errstr != NULL)
0e1944
+	goto done;
0e1944
+
0e1944
+    /* Success. */
0e1944
+    ret = 1;
0e1944
+
0e1944
+done:
0e1944
     last_time.tv_sec = now.tv_sec;
0e1944
     last_time.tv_usec = now.tv_usec;
0e1944
 
0e1944
@@ -979,7 +1020,7 @@ sudoers_io_log(const char *buf, unsigned
0e1944
 
0e1944
 	/* Ignore errors if they occur if the policy says so. */
0e1944
 	if (iolog_details.ignore_iolog_errors)
0e1944
-	    ret = true;
0e1944
+	    ret = 1;
0e1944
     }
0e1944
 
0e1944
     debug_return_int(ret);