Add a suspend event type to the I/O log to log suspend/resume of

the command so we can skip that delay during replay.
This commit is contained in:
Todd C. Miller
2018-10-05 14:16:08 -06:00
parent e2570307e6
commit cf07dc0757
13 changed files with 383 additions and 202 deletions

View File

@@ -48,9 +48,9 @@
#include "sudo_fatal.h"
#include "sudo_debug.h"
#include "sudo_util.h"
#include "iolog_util.h"
#include "iolog.h"
static int timing_idx_adj;
static int timing_event_adj;
struct log_info *
parse_logfile(const char *logfile)
@@ -288,8 +288,10 @@ parse_delay(const char *cp, struct timespec *delay, const char *decimal_point)
/*
* Parse a timing line, which is formatted as:
* index sleep_time num_bytes
* Where index is IOFD_*, sleep_time is the number of seconds to sleep
* IO_EVENT_TTYOUT sleep_time num_bytes
* IO_EVENT_WINSIZE sleep_time rows cols
* IO_EVENT_SUSPEND sleep_time signo
* Where type is IO_EVENT_*, sleep_time is the number of seconds to sleep
* before writing the data and num_bytes is the number of bytes to output.
* Returns true on success and false on failure.
*/
@@ -301,17 +303,20 @@ parse_timing(const char *buf, struct timespec *delay,
char *cp, *ep;
debug_decl(parse_timing, SUDO_DEBUG_UTIL)
/* Parse index */
/* Clear fd. */
timing->fd.v = NULL;
/* Parse event type. */
ulval = strtoul(buf, &ep, 10);
if (ep == buf || !isspace((unsigned char) *ep))
goto bad;
if (ulval >= IOFD_MAX) {
if (ulval >= IO_EVENT_COUNT) {
if (ulval != 6)
goto bad;
/* work around a bug in timing files generated by sudo 1.8.7 */
timing_idx_adj = 2;
timing_event_adj = 2;
}
timing->idx = (int)ulval - timing_idx_adj;
timing->event = (int)ulval - timing_event_adj;
for (cp = ep + 1; isspace((unsigned char) *cp); cp++)
continue;
@@ -319,7 +324,17 @@ parse_timing(const char *buf, struct timespec *delay,
if ((cp = parse_delay(cp, delay, timing->decimal)) == NULL)
goto bad;
if (timing->idx == IOFD_TIMING) {
switch (timing->event) {
case IO_EVENT_SUSPEND:
errno = 0;
ulval = strtoul(cp, &ep, 10);
if (ep == cp || *ep != '\0')
goto bad;
if (ulval > INT_MAX)
goto bad;
timing->u.signo = (int)ulval;
break;
case IO_EVENT_WINSIZE:
errno = 0;
ulval = strtoul(cp, &ep, 10);
if (ep == cp || !isspace((unsigned char) *ep))
@@ -337,7 +352,8 @@ parse_timing(const char *buf, struct timespec *delay,
if (ulval > INT_MAX || (errno == ERANGE && ulval == ULONG_MAX))
goto bad;
timing->u.winsize.cols = (int)ulval;
} else {
break;
default:
errno = 0;
ulval = strtoul(cp, &ep, 10);
if (ep == cp || *ep != '\0')
@@ -345,6 +361,7 @@ parse_timing(const char *buf, struct timespec *delay,
if (ulval > SIZE_MAX || (errno == ERANGE && ulval == ULONG_MAX))
goto bad;
timing->u.nbytes = (size_t)ulval;
break;
}
debug_return_bool(true);