aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2015-03-07 11:49:00 +0100
committerKarel Zak <kzak@redhat.com>2015-03-10 11:19:33 +0100
commitb9ef27f59bffbeaf5397538ea16065d4eb6364c8 (patch)
treeff77e1490459d417c852d166dd92388ce175e31d
parent2b3f40c5978569f15e30836cf99f34f31c163d1c (diff)
downloadutil-linux-playground-b9ef27f59bffbeaf5397538ea16065d4eb6364c8.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 3a4d58efee..575d111e68 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();
}
}