summaryrefslogtreecommitdiffstats
path: root/logd/LogKlog.cpp
diff options
context:
space:
mode:
authorMark Salyzyn <salyzyn@google.com>2016-08-05 08:16:37 -0700
committerMark Salyzyn <salyzyn@google.com>2016-08-08 09:58:28 -0700
commita146a779e2154c51c87b140e06c456d010af1197 (patch)
tree1c576d5639a315cd13c5e64b5dd9cfe1e8554faa /logd/LogKlog.cpp
parent9cd828b8589a64e79cbd6aa7dc324fcdba75dd73 (diff)
downloadsystem_core-a146a779e2154c51c87b140e06c456d010af1197.tar.gz
system_core-a146a779e2154c51c87b140e06c456d010af1197.tar.bz2
system_core-a146a779e2154c51c87b140e06c456d010af1197.zip
logd: klogd crash
dmesg parser could wrap taglen limit resulting in out of bound accesses. Can lead to crash or data corruption. Fixed an issue with two-word tag parsing. Switched to case insensitive tag content matching. Added a few extra limit checks that could also wrap, simplified the parsing, then added means to stop using hard coded constants. Bug: 30688716 Bug: 30050636 Bug: 30614675 Bug: 25620123 Change-Id: Iae4f664f63ef7b842d82eaa1638b6d7a0d28fd18
Diffstat (limited to 'logd/LogKlog.cpp')
-rw-r--r--logd/LogKlog.cpp196
1 files changed, 97 insertions, 99 deletions
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index ac2b12895..0495463dc 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -605,126 +605,124 @@ int LogKlog::log(const char *buf, size_t len) {
const char *tag = "";
const char *etag = tag;
size_t taglen = len - (p - buf);
- if (!isspace(*p) && *p) {
- const char *bt, *et, *cp;
-
- bt = p;
- if ((taglen >= 6) && !fast<strncmp>(p, "[INFO]", 6)) {
- // <PRI>[<TIME>] "[INFO]"<tag> ":" message
- bt = p + 6;
- taglen -= 6;
- }
- for(et = bt; taglen && *et && (*et != ':') && !isspace(*et); ++et, --taglen) {
- // skip ':' within [ ... ]
- if (*et == '[') {
- while (taglen && *et && *et != ']') {
- ++et;
- --taglen;
- }
- }
- }
- for(cp = et; taglen && isspace(*cp); ++cp, --taglen);
- size_t size;
-
+ const char *bt = p;
+
+ static const char infoBrace[] = "[INFO]";
+ static const size_t infoBraceLen = strlen(infoBrace);
+ if ((taglen >= infoBraceLen) && !fast<strncmp>(p, infoBrace, infoBraceLen)) {
+ // <PRI>[<TIME>] "[INFO]"<tag> ":" message
+ bt = p + infoBraceLen;
+ taglen -= infoBraceLen;
+ }
+
+ const char *et;
+ for (et = bt; taglen && *et && (*et != ':') && !isspace(*et); ++et, --taglen) {
+ // skip ':' within [ ... ]
+ if (*et == '[') {
+ while (taglen && *et && *et != ']') {
+ ++et;
+ --taglen;
+ }
+ if (!taglen) {
+ break;
+ }
+ }
+ }
+ const char *cp;
+ for (cp = et; taglen && isspace(*cp); ++cp, --taglen);
+
+ // Validate tag
+ size_t size = et - bt;
+ if (taglen && size) {
if (*cp == ':') {
+ // ToDo: handle case insensitive colon separated logging stutter:
+ // <tag> : <tag>: ...
+
// One Word
tag = bt;
etag = et;
p = cp + 1;
- } else if (taglen) {
- size = et - bt;
- if ((taglen > size) && // enough space for match plus trailing :
- (*bt == *cp) && // ubber fast<strncmp> pair
- fast<strncmp>(bt + 1, cp + 1, size - 1)) {
- // <PRI>[<TIME>] <tag>_host '<tag>.<num>' : message
- if (!fast<strncmp>(bt + size - 5, "_host", 5)
- && !fast<strncmp>(bt + 1, cp + 1, size - 6)) {
- const char *b = cp;
- cp += size - 5;
- taglen -= size - 5;
- if (*cp == '.') {
- while (--taglen && !isspace(*++cp) && (*cp != ':'));
- const char *e;
- for(e = cp; taglen && isspace(*cp); ++cp, --taglen);
- if (*cp == ':') {
- tag = b;
- etag = e;
- p = cp + 1;
- }
- }
- } else {
- while (--taglen && !isspace(*++cp) && (*cp != ':'));
- const char *e;
- for(e = cp; taglen && isspace(*cp); ++cp, --taglen);
- // Two words
- if (*cp == ':') {
- tag = bt;
- etag = e;
- p = cp + 1;
- }
- }
- } else if (isspace(cp[size])) {
- cp += size;
- taglen -= size;
- while (--taglen && isspace(*++cp));
- // <PRI>[<TIME>] <tag> <tag> : message
- if (*cp == ':') {
- tag = bt;
- etag = et;
- p = cp + 1;
- }
- } else if (cp[size] == ':') {
+ } else if ((taglen > size) && (tolower(*bt) == tolower(*cp))) {
+ // clean up any tag stutter
+ if (!fast<strncasecmp>(bt + 1, cp + 1, size - 1)) { // no match
// <PRI>[<TIME>] <tag> <tag> : message
- tag = bt;
- etag = et;
- p = cp + size + 1;
- } else if ((cp[size] == '.') || isdigit(cp[size])) {
+ // <PRI>[<TIME>] <tag> <tag>: message
// <PRI>[<TIME>] <tag> '<tag>.<num>' : message
// <PRI>[<TIME>] <tag> '<tag><num>' : message
+ // <PRI>[<TIME>] <tag> '<tag><stuff>' : message
const char *b = cp;
cp += size;
taglen -= size;
while (--taglen && !isspace(*++cp) && (*cp != ':'));
- const char *e = cp;
- while (taglen && isspace(*cp)) {
- ++cp;
- --taglen;
- }
- if (*cp == ':') {
+ const char *e;
+ for (e = cp; taglen && isspace(*cp); ++cp, --taglen);
+ if (taglen && (*cp == ':')) {
tag = b;
etag = e;
p = cp + 1;
}
} else {
- while (--taglen && !isspace(*++cp) && (*cp != ':'));
- const char *e = cp;
- while (taglen && isspace(*cp)) {
- ++cp;
- --taglen;
- }
- // Two words
- if (*cp == ':') {
- tag = bt;
- etag = e;
- p = cp + 1;
+ // what about <PRI>[<TIME>] <tag>_host '<tag><stuff>' : message
+ static const char host[] = "_host";
+ static const size_t hostlen = strlen(host);
+ if ((size > hostlen) &&
+ !fast<strncmp>(bt + size - hostlen, host, hostlen) &&
+ !fast<strncmp>(bt + 1, cp + 1, size - hostlen - 1)) {
+ const char *b = cp;
+ cp += size - hostlen;
+ taglen -= size - hostlen;
+ if (*cp == '.') {
+ while (--taglen && !isspace(*++cp) && (*cp != ':'));
+ const char *e;
+ for (e = cp; taglen && isspace(*cp); ++cp, --taglen);
+ if (taglen && (*cp == ':')) {
+ tag = b;
+ etag = e;
+ p = cp + 1;
+ }
+ }
+ } else {
+ goto twoWord;
}
}
- } /* else no tag */
- size = etag - tag;
- if ((size <= 1)
- // register names like x9
- || ((size == 2) && (isdigit(tag[0]) || isdigit(tag[1])))
- // register names like x18 but not driver names like en0
- || ((size == 3) && (isdigit(tag[1]) && isdigit(tag[2])))
- // blacklist
- || ((size == 3) && !fast<strncmp>(tag, "CPU", 3))
- || ((size == 7) && !fast<strncasecmp>(tag, "WARNING", 7))
- || ((size == 5) && !fast<strncasecmp>(tag, "ERROR", 5))
- || ((size == 4) && !fast<strncasecmp>(tag, "INFO", 4))) {
- p = start;
- etag = tag = "";
+ } else {
+ // <PRI>[<TIME>] <tag> <stuff>' : message
+twoWord: while (--taglen && !isspace(*++cp) && (*cp != ':'));
+ const char *e;
+ for (e = cp; taglen && isspace(*cp); ++cp, --taglen);
+ // Two words
+ if (taglen && (*cp == ':')) {
+ tag = bt;
+ etag = e;
+ p = cp + 1;
+ }
}
+ } // else no tag
+
+ static const char cpu[] = "CPU";
+ static const size_t cpuLen = strlen(cpu);
+ static const char warning[] = "WARNING";
+ static const size_t warningLen = strlen(warning);
+ static const char error[] = "ERROR";
+ static const size_t errorLen = strlen(error);
+ static const char info[] = "INFO";
+ static const size_t infoLen = strlen(info);
+
+ size = etag - tag;
+ if ((size <= 1)
+ // register names like x9
+ || ((size == 2) && (isdigit(tag[0]) || isdigit(tag[1])))
+ // register names like x18 but not driver names like en0
+ || ((size == 3) && (isdigit(tag[1]) && isdigit(tag[2])))
+ // blacklist
+ || ((size == cpuLen) && !fast<strncmp>(tag, cpu, cpuLen))
+ || ((size == warningLen) && !fast<strncasecmp>(tag, warning, warningLen))
+ || ((size == errorLen) && !fast<strncasecmp>(tag, error, errorLen))
+ || ((size == infoLen) && !fast<strncasecmp>(tag, info, infoLen))) {
+ p = start;
+ etag = tag = "";
}
+
// Suppress additional stutter in tag:
// eg: [143:healthd]healthd -> [143:healthd]
taglen = etag - tag;