struct group *runas_gr;
int lines;
int cols;
+ bool ignore_iolog_errors;
};
+static struct iolog_details iolog_details;
static bool iolog_compress = false;
+static bool warned = false;
static struct timeval last_time;
static unsigned int sessid_max = SESSID_MAX;
if (lseek(fd, 0, SEEK_SET) == -1 || write(fd, buf, 7) != 7) {
#endif
log_warning(SLOG_SEND_MAIL, N_("unable to write to %s"), pathbuf);
+ warned = true;
goto done;
}
rval = true;
}
break;
case 'i':
+ if (strncmp(*cur, "ignore_iolog_errors=", sizeof("ignore_iolog_errors=") - 1) == 0) {
+ if (sudo_strtobool(*cur + sizeof("ignore_iolog_errors=") - 1) == true)
+ details->ignore_iolog_errors = true;
+ continue;
+ }
if (strncmp(*cur, "iolog_path=", sizeof("iolog_path=") - 1) == 0) {
details->iolog_path = *cur + sizeof("iolog_path=") - 1;
continue;
int argc, char * const argv[], char * const user_env[], char * const args[])
{
struct sudo_conf_debug_file_list debug_files = TAILQ_HEAD_INITIALIZER(debug_files);
- struct iolog_details details;
char pathbuf[PATH_MAX], sessid[7];
char *tofree = NULL;
char * const *cur;
if (argc == 0)
debug_return_int(true);
- memset(&details, 0, sizeof(details));
-
bindtextdomain("sudoers", LOCALEDIR);
/* Initialize the debug subsystem. */
/*
* Pull iolog settings out of command_info.
*/
- if (!iolog_deserialize_info(&details, user_info, command_info)) {
+ if (!iolog_deserialize_info(&iolog_details, user_info, command_info)) {
rval = false;
goto done;
}
/* If no I/O log path defined we need to figure it out ourselves. */
- if (details.iolog_path == NULL) {
+ if (iolog_details.iolog_path == NULL) {
/* Get next session ID and convert it into a path. */
tofree = malloc(sizeof(_PATH_SUDO_IO_LOGDIR) + sizeof(sessid) + 2);
if (tofree == NULL) {
snprintf(tofree + sizeof(_PATH_SUDO_IO_LOGDIR), sizeof(sessid) + 2,
"%c%c/%c%c/%c%c", sessid[0], sessid[1], sessid[2], sessid[3],
sessid[4], sessid[5]);
- details.iolog_path = tofree;
+ iolog_details.iolog_path = tofree;
}
/*
* Make local copy of I/O log path and create it, along with any
* intermediate subdirs. Calls mkdtemp() if iolog_path ends in XXXXXX.
*/
- len = mkdir_iopath(details.iolog_path, pathbuf, sizeof(pathbuf));
+ len = mkdir_iopath(iolog_details.iolog_path, pathbuf, sizeof(pathbuf));
if (len >= sizeof(pathbuf))
goto done;
/* Write log file with user and command details. */
if (gettimeofday(&last_time, NULL) == -1)
goto done;
- write_info_log(pathbuf, len, &details, argv, &last_time);
+ write_info_log(pathbuf, len, &iolog_details, argv, &last_time);
/* Create the timing and I/O log files. */
for (i = 0; i < IOFD_MAX; i++) {
done:
free(tofree);
- if (details.runas_pw)
- sudo_pw_delref(details.runas_pw);
- if (details.runas_gr)
- sudo_gr_delref(details.runas_gr);
+ if (iolog_details.runas_pw)
+ sudo_pw_delref(iolog_details.runas_pw);
+ if (iolog_details.runas_gr)
+ sudo_gr_delref(iolog_details.runas_gr);
sudo_freepwcache();
sudo_freegrcache();
+ /* Ignore errors if they occur if the policy says so. */
+ if (rval == -1 && iolog_details.ignore_iolog_errors)
+ rval = 0;
+
debug_return_int(rval);
}
errstr = strerror(errno);
}
- if (errstr != NULL)
- sudo_warnx(U_("unable to write to I/O log file: %s"), errstr);
+ if (errstr != NULL && !warned) {
+ /* Only warn about I/O log file errors once. */
+ log_warning(SLOG_SEND_MAIL,
+ N_("unable to write to I/O log file: %s"), errstr);
+ warned = true;
+ }
sudoers_debug_deregister();
sudoers_io_log(const char *buf, unsigned int len, int idx)
{
struct timeval now, delay;
- static bool warned = false;
const char *errstr = NULL;
int rval = true;
debug_decl(sudoers_io_version, SUDOERS_DEBUG_PLUGIN)
last_time.tv_sec = now.tv_sec;
last_time.tv_usec = now.tv_usec;
- if (errstr != NULL && !warned) {
- /* Only warn about I/O log file errors once. */
- sudo_warnx(U_("unable to write to I/O log file: %s"), errstr);
- warned = true;
+ if (rval == -1) {
+ if (errstr != NULL && !warned) {
+ /* Only warn about I/O log file errors once. */
+ log_warning(SLOG_SEND_MAIL,
+ N_("unable to write to I/O log file: %s"), errstr);
+ warned = true;
+ }
+
+ /* Ignore errors if they occur if the policy says so. */
+ if (iolog_details.ignore_iolog_errors)
+ rval = true;
}
debug_return_int(rval);
static pid_t ppgrp, cmnd_pgrp, mon_pgrp;
static sigset_t ttyblock;
static struct io_buffer_list iobufs;
-static bool ignore_iolog_errors;
static void del_io_events(bool nonblocking);
static int exec_monitor(struct command_details *details, int backchannel);
/* Error: disable plugin's I/O function. */
plugin->u.io->log_ttyin = NULL;
}
- if (!ignore_iolog_errors)
- rval = false;
break;
}
}
/* Error: disable plugin's I/O function. */
plugin->u.io->log_stdin = NULL;
}
- if (!ignore_iolog_errors)
- rval = false;
break;
}
}
/* Error: disable plugin's I/O function. */
plugin->u.io->log_ttyout = NULL;
}
- if (!ignore_iolog_errors)
- rval = false;
break;
}
}
/* Error: disable plugin's I/O function. */
plugin->u.io->log_stdout = NULL;
}
- if (!ignore_iolog_errors)
- rval = false;
break;
}
}
/* Error: disable plugin's I/O function. */
plugin->u.io->log_stderr = NULL;
}
- if (!ignore_iolog_errors)
- rval = false;
break;
}
}
sigaddset(&ttyblock, SIGTTIN);
sigaddset(&ttyblock, SIGTTOU);
- /*
- * The security policy may tell us to ignore errors from the
- * I/O log functions.
- */
- if (!ISSET(details->flags, CD_IGNORE_IOLOG_ERRS))
- ignore_iolog_errors = true;
-
/*
* Setup stdin/stdout/stderr for child, to be duped after forking.
* In background mode there is no stdin.