I found an integer overflow in syslogd which can be triggered by compiling and running:
#include <err.h> #include <string.h> #include <sys/types.h> int main( int argc, char ** argv ) { const char * msg = "<999999999999> hello"; return sendsyslog( msg, strlen( msg ) ); } The problematic code is a hand-rolled int parser in printline/printsys: pri = 0; while (isdigit((unsigned char)*++p)) pri = 10 * pri + (*p - '0'); if (*p == '>') ++p; I've attached a patch which converts the loop to strtonum, but doesn't exactly mirror the behaviour of the old code in funny cases, like sendsyslog("<1no closing angle bracket"). Mike
Index: syslogd.c =================================================================== RCS file: /cvs/src/usr.sbin/syslogd/syslogd.c,v retrieving revision 1.177 diff -u -p -r1.177 syslogd.c --- syslogd.c 20 Jul 2015 19:49:33 -0000 1.177 +++ syslogd.c 11 Feb 2016 20:31:55 -0000 @@ -1331,18 +1331,23 @@ usage(void) void printline(char *hname, char *msg) { - int pri; - char *p, *q, line[MAXLINE + 4 + 1]; /* message, encoding, NUL */ + int pri, possiblepri; + char *p, *q, line[MAXLINE + 4 + 1], *gt; /* message, encoding, NUL */ + const char *errstr; /* test for special codes */ pri = DEFUPRI; p = msg; if (*p == '<') { - pri = 0; - while (isdigit((unsigned char)*++p)) - pri = 10 * pri + (*p - '0'); - if (*p == '>') - ++p; + gt = strchr(p, '>'); + if (gt) { + *gt = '\0'; + possiblepri = strtonum(p + 1, 0, INT_MAX, &errstr); + if (!errstr) + pri = possiblepri; + *gt = '>'; + p = gt + 1; + } } if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) pri = DEFUPRI; @@ -1372,8 +1377,9 @@ printline(char *hname, char *msg) void printsys(char *msg) { - int c, pri, flags; - char *lp, *p, *q, line[MAXLINE + 1]; + int c, pri, flags, possiblepri; + char *lp, *p, *q, line[MAXLINE + 1], *gt; + const char *errstr; (void)snprintf(line, sizeof line, "%s: ", _PATH_UNIX); lp = line + strlen(line); @@ -1381,11 +1387,15 @@ printsys(char *msg) flags = SYNC_FILE | ADDDATE; /* fsync file after write */ pri = DEFSPRI; if (*p == '<') { - pri = 0; - while (isdigit((unsigned char)*++p)) - pri = 10 * pri + (*p - '0'); - if (*p == '>') - ++p; + gt = strchr(p, '>'); + if (gt) { + *gt = '\0'; + possiblepri = strtonum(p + 1, 0, INT_MAX, &errstr); + if (!errstr) + pri = possiblepri; + *gt = '>'; + p = gt + 1; + } } else { /* kernel printf's come out on console */ flags |= IGN_CONS;