diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2015-03-07 11:49:00 +0100 |
---|---|---|
committer | Karel Zak <kzak@redhat.com> | 2015-03-12 10:20:44 +0100 |
commit | f1a52e176a553b6d17664c794352570363177db0 (patch) | |
tree | 68429f95a359ff1559f6fb2d46893c90b64114a5 | |
parent | 5d627e7fe6872c915e19431a96bb62448328ef33 (diff) | |
download | util-linux-f1a52e176a553b6d17664c794352570363177db0.tar.gz |
logger: bugfix: missing sanity checks with --prio-prefix option
There were no apparent sanity checks other than applying the logmask
when reading PRI values from files. As such, invalid PRIs (tested with
values 192, 210, and 2100) are accepted. This in turn can trigger
problems in various receivers, especially older versions. See here
for details:
http://www.rsyslog.com/remote-syslog-pri-vulnerability-cve-2014-3683/
Note that 2100 was changed to 52 as described in above link.
This patch refactors PRI processing. Invalid PRIs are detected and in
this case the message is sent with the default priority, with the
invalid pri being part of the message to be sent. This is along the
line of what 2.26 did when it detected the PRI was invalid.
The refactoring now also enables pricese tracking of syslog header
length in all cases, so --size is now strictly obeyed.
[kzak@redhat.com: - fix compiler warning [-Wunused-variable]]
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r-- | misc-utils/logger.c | 85 |
1 files changed, 48 insertions, 37 deletions
diff --git a/misc-utils/logger.c b/misc-utils/logger.c index 3a4d58efe..575d111e6 100644 --- a/misc-utils/logger.c +++ b/misc-utils/logger.c @@ -114,25 +114,6 @@ struct logger_ctl { rfc5424_host:1; /* include hostname */ }; -static char *get_prio_prefix(char *msg, int *prio) -{ - int p; - char *end = NULL; - int facility = *prio & LOG_FACMASK; - - errno = 0; - p = strtoul(msg + 1, &end, 10); - - if (errno || !end || end == msg + 1 || end[0] != '>') - return msg; - - if (p & LOG_FACMASK) - facility = p & LOG_FACMASK; - - *prio = facility | (p & LOG_PRIMASK); - return end + 1; -} - static int decode(const char *name, CODE *codetab) { register CODE *c; @@ -548,25 +529,55 @@ static void logger_command_line(const struct logger_ctl *ctl, char **argv) static void logger_stdin(struct logger_ctl *ctl) { - char *msg; int default_priority = ctl->pri; - const size_t max_usrmsg_size = ctl->max_message_size - strlen(ctl->hdr); - char *const buf = xmalloc(max_usrmsg_size + 2); - - while (fgets(buf, max_usrmsg_size+2, stdin) != NULL) { - int len = strlen(buf); - - /* some glibc versions are buggy, they add an additional - * newline which is removed here. */ - if (0 < len && buf[len - 1] == '\n') - buf[len - 1] = '\0'; - msg = buf; - ctl->pri = default_priority; - if (ctl->prio_prefix && msg[0] == '<') - msg = get_prio_prefix(msg, &ctl->pri); - /* this potentially runs long, date may have changed (and also PRI) */ - generate_syslog_header(ctl); - write_output(ctl, msg); + int last_pri = default_priority; + size_t max_usrmsg_size = ctl->max_message_size - strlen(ctl->hdr); + char *const buf = xmalloc(max_usrmsg_size + 2 + 2); + int pri; + int c; + size_t i; + + c = getchar(); + while (c != EOF) { + i = 0; + if (ctl->prio_prefix) { + if (c == '<') { + pri = 0; + buf[i++] = c; + while(isdigit(c = getchar()) && pri <= 191) { + buf[i++] = c; + pri = pri * 10 + c - '0'; + } + if (c != EOF && c != '\n') + buf[i++] = c; + if (c == '>' && 0 <= pri && pri <= 191) { /* valid RFC PRI values */ + i = 0; + if (pri < 8) + pri |= 8; /* kern facility is forbidden */ + ctl->pri = pri; + } else + ctl->pri = default_priority; + + if (ctl->pri != last_pri) { + generate_syslog_header(ctl); + max_usrmsg_size = ctl->max_message_size - strlen(ctl->hdr); + last_pri = ctl->pri; + } + if (c != EOF && c != '\n') + c = getchar(); + } + } + + while (c != EOF && c != '\n' && i < max_usrmsg_size) { + buf[i++] = c; + c = getchar(); + } + buf[i] = '\0'; + + write_output(ctl, buf); + + if (c == '\n') /* discard line terminator */ + c = getchar(); } } |