summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2015-03-07 11:49:00 +0100
committerKarel Zak <kzak@redhat.com>2015-03-12 10:20:44 +0100
commitf1a52e176a553b6d17664c794352570363177db0 (patch)
tree68429f95a359ff1559f6fb2d46893c90b64114a5
parent5d627e7fe6872c915e19431a96bb62448328ef33 (diff)
downloadutil-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.c85
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();
}
}