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(a)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