If a user passes %m in a format string, but we do any intermediate processing that might corrupt errno, then we risk changing the message that the user intended to be printed to instead refer to our changed state of errno. Hoist the saving of errno to occur before any other risky calls, and restore errno before printing a user-supplied format. Signed-off-by: Eric Blake <eblake@redhat.com> --- src/log-stderr.c | 4 ++-- src/log-syslog.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/log-stderr.c b/src/log-stderr.c index 790c2d3..ff0b371 100644 --- a/src/log-stderr.c +++ b/src/log-stderr.c @@ -45,11 +45,10 @@ void log_stderr_verror (const char *fs, va_list args) { - int err; + int err = errno; const char *name = threadlocal_get_name (); size_t instance_num = threadlocal_get_instance_num (); - err = errno; flockfile (stderr); fprintf (stderr, "%s: ", program_name); @@ -62,6 +61,7 @@ log_stderr_verror (const char *fs, va_list args) } fprintf (stderr, "error: "); + errno = err; /* Must restore in case fs contains %m */ vfprintf (stderr, fs, args); fprintf (stderr, "\n"); diff --git a/src/log-syslog.c b/src/log-syslog.c index d533c05..611ed04 100644 --- a/src/log-syslog.c +++ b/src/log-syslog.c @@ -49,18 +49,17 @@ static const int PRIORITY = LOG_DAEMON|LOG_ERR; void log_syslog_verror (const char *fs, va_list args) { - int err; + int err = errno; const char *name = threadlocal_get_name (); size_t instance_num = threadlocal_get_instance_num (); CLEANUP_FREE char *msg = NULL; size_t len = 0; FILE *fp = NULL; - err = errno; - fp = open_memstream (&msg, &len); if (fp == NULL) { /* Fallback to logging using fs, args directly. */ + errno = err; /* Must restore in case fs contains %m */ vsyslog (PRIORITY, fs, args); goto out; } @@ -72,6 +71,7 @@ log_syslog_verror (const char *fs, va_list args) fprintf (fp, ": "); } + errno = err; /* Must restore in case fs contains %m */ vfprintf (fp, fs, args); fclose (fp); -- 2.17.2