From f25bc50e689071ed30778e71c3c2c83512f54e28 Mon Sep 17 00:00:00 2001 From: "Liu, Xinwu" Date: Wed, 26 Sep 2018 15:23:41 +0800 Subject: [PATCH] tools: acrn-crashlog: update string operation in acrnprobe Remove unsafe api strlen except the parameter is a static string. Tracked-On: #1254 Signed-off-by: Liu, Xinwu Reviewed-by: Yonghua Huang Acked-by: Chen Gang --- tools/acrn-crashlog/acrnprobe/channels.c | 33 ++-- .../acrnprobe/crash_reclassify.c | 72 +++++---- tools/acrn-crashlog/acrnprobe/history.c | 7 +- .../acrn-crashlog/acrnprobe/include/history.h | 2 +- .../acrnprobe/include/load_conf.h | 3 +- .../acrnprobe/include/probeutils.h | 12 +- tools/acrn-crashlog/acrnprobe/probeutils.c | 135 +++++++++-------- tools/acrn-crashlog/acrnprobe/sender.c | 143 ++++++++++-------- tools/acrn-crashlog/acrnprobe/startupreason.c | 24 +-- 9 files changed, 238 insertions(+), 193 deletions(-) diff --git a/tools/acrn-crashlog/acrnprobe/channels.c b/tools/acrn-crashlog/acrnprobe/channels.c index be64c7b31..ad795c575 100644 --- a/tools/acrn-crashlog/acrnprobe/channels.c +++ b/tools/acrn-crashlog/acrnprobe/channels.c @@ -55,19 +55,20 @@ static struct channel_t channels[] = { * @param private The corresponding configuration info to the event. * @param watchfd For watch channel, so far, only used by inotify. * @param path File which trigger this event. + * @param plen The length of path. * * @return a pointer to the filled event if successful, * or NULL on error. */ static struct event_t *create_event(enum event_type_t event_type, const char *channel, void *private, - int watchfd, const char *path) + int watchfd, const char *path, size_t plen) { struct event_t *e; - int path_len = 0; + size_t path_len = 0; if (path) { - path_len = strlen(path); + path_len = plen; if (path_len > PATH_MAX) { LOGE("invalid path, drop event.\n"); return NULL; @@ -83,7 +84,7 @@ static struct event_t *create_event(enum event_type_t event_type, e->event_type = event_type; if (path_len > 0) { e->len = path_len; - memcpy(e->path, path, path_len + 1); + *(char *)(mempcpy(e->path, path, path_len)) = '\0'; } } else { LOGE("malloc failed, error (%s)\n", strerror(errno)); @@ -110,7 +111,7 @@ static void channel_oneshot(struct channel_t *cnl) if (!is_boot_id_changed()) return; - e = create_event(REBOOT, cname, NULL, 0, NULL); + e = create_event(REBOOT, cname, NULL, 0, NULL, 0); if (e) event_enqueue(e); @@ -127,7 +128,8 @@ static void channel_oneshot(struct channel_t *cnl) if (!strcmp("file", crash->trigger->type)) { if (file_exists(crash->trigger->path)) { e = create_event(CRASH, cname, (void *)crash, - 0, crash->trigger->path); + 0, crash->trigger->path, + crash->trigger->path_len); if (e) event_enqueue(e); } @@ -137,7 +139,8 @@ static void channel_oneshot(struct channel_t *cnl) read_startupreason(rreason, sizeof(rreason)); if (!strcmp(rreason, crash->content[0])) { e = create_event(CRASH, cname, (void *)crash, - 0, crash->trigger->path); + 0, crash->trigger->path, + crash->trigger->path_len); if (e) event_enqueue(e); } @@ -155,7 +158,7 @@ static void channel_oneshot(struct channel_t *cnl) !strcmp("file", info->trigger->type) && file_exists(info->trigger->path)) { e = create_event(INFO, cname, (void *)info, - 0, NULL); + 0, NULL, 0); if (e) event_enqueue(e); } @@ -177,7 +180,7 @@ static struct polling_job_t { static void polling_vm(union sigval v __attribute__((unused))) { - struct event_t *e = create_event(VM, "polling", NULL, 0, NULL); + struct event_t *e = create_event(VM, "polling", NULL, 0, NULL, 0); if (e) event_enqueue(e); @@ -238,7 +241,7 @@ static void channel_polling(struct channel_t *cnl) if (!vm) continue; - if (strncmp(vm->channel, "polling", strlen(vm->channel))) + if (strcmp(vm->channel, "polling")) continue; vm_job.timer_val = atoi(vm->interval); @@ -340,7 +343,6 @@ static int receive_inotify_events(struct channel_t *channel) int read_left; char buf[256]; char *p; - char *name; struct event_t *e; struct inotify_event *ievent; enum event_type_t event_type; @@ -382,14 +384,9 @@ static int receive_inotify_events(struct channel_t *channel) if (event_type == UNKNOWN) { LOGE("get a unknown event\n"); } else { - if (!ievent->len) - name = NULL; - else - name = ievent->name; - e = create_event(event_type, channel->name, private, channel->fd, - name); + ievent->name, ievent->len); if (e) event_enqueue(e); } @@ -411,7 +408,7 @@ static int receive_inotify_events(struct channel_t *channel) */ static void heart_beat(void) { - struct event_t *e = create_event(HEART_BEAT, NULL, NULL, 0, NULL); + struct event_t *e = create_event(HEART_BEAT, NULL, NULL, 0, NULL, 0); if (e) event_enqueue(e); diff --git a/tools/acrn-crashlog/acrnprobe/crash_reclassify.c b/tools/acrn-crashlog/acrnprobe/crash_reclassify.c index c66d0a702..8f78c274b 100644 --- a/tools/acrn-crashlog/acrnprobe/crash_reclassify.c +++ b/tools/acrn-crashlog/acrnprobe/crash_reclassify.c @@ -125,19 +125,14 @@ static int crash_match_content(const struct crash_t *crash, const char *file) crash_has_mightcontents(crash, file); } -static int _get_data(const char *file, const struct crash_t *crash, +static ssize_t _get_data(const char *file, const struct crash_t *crash, char **data, const int index) { const char *search_key; char *value; char *end; - int size; - int max_size = 255; - - if (!data) - return 0; - - *data = NULL; + ssize_t size; + const size_t max_size = 255; search_key = crash->data[index]; if (!search_key) @@ -151,8 +146,11 @@ static int _get_data(const char *file, const struct crash_t *crash, if (!end) return 0; - size = MIN(max_size, end - value); - *data = malloc(size + 1); + size = MIN(max_size, (size_t)(end - value)); + if (!size) + return 0; + + *data = malloc(size + 1); if (*data == NULL) return -ENOMEM; @@ -171,35 +169,45 @@ static int _get_data(const char *file, const struct crash_t *crash, * @param[out] data1 Searched result, according to 'data1' configuread in crash. * @param[out] data2 Searched result, according to 'data2' configuread in crash. * - * @return 0 if successful, or errno if not. + * @return 0 if successful, or -1 if not. */ static int get_data(const char *file, const struct crash_t *crash, - char **data0, char **data1, char **data2) + char **data0, size_t *d0len, char **data1, + size_t *d1len, char **data2, size_t *d2len) { - int res; + ssize_t res; /* to find strings which match conf words */ res = _get_data(file, crash, data0, 0); if (res < 0) goto fail; + *d0len = (size_t)res; res = _get_data(file, crash, data1, 1); if (res < 0) goto free_data0; + *d1len = (size_t)res; res = _get_data(file, crash, data2, 2); if (res < 0) goto free_data1; + *d2len = (size_t)res; return 0; free_data1: - if (data1 && *data1) + if (*data1) free(*data1); free_data0: - if (data0 && *data0) + if (*data0) free(*data0); fail: - return res; + *data0 = NULL; + *data1 = NULL; + *data2 = NULL; + *d0len = 0; + *d1len = 0; + *d2len = 0; + return -1; } static struct crash_t *crash_find_matched_child(const struct crash_t *crash, @@ -276,8 +284,10 @@ static struct crash_t *crash_find_matched_child(const struct crash_t *crash, * or NULL if not. */ static struct crash_t *crash_reclassify_by_content(const struct crash_t *rcrash, - const char *rtrfile_fmt, char **data0, - char **data1, char **data2) + const char *rtrfile_fmt, + char **data0, size_t *d0len, + char **data1, size_t *d1len, + char **data2, size_t *d2len) { int count; const struct crash_t *crash; @@ -286,12 +296,17 @@ static struct crash_t *crash_reclassify_by_content(const struct crash_t *rcrash, char **trfiles; void *content; unsigned long size; - int res; int i; - if (!rcrash) + if (!rcrash || !data0 || !d0len || !data1 || !d1len || !data2 || !d2len) return NULL; + *data0 = NULL; + *data1 = NULL; + *data2 = NULL; + *d0len = 0; + *d1len = 0; + *d2len = 0; crash = rcrash; while (1) { @@ -307,25 +322,26 @@ static struct crash_t *crash_reclassify_by_content(const struct crash_t *rcrash, else trfile_fmt = ret_crash->trigger->path; + /* trfile may not be specified */ + if (!trfile_fmt) + return (struct crash_t *)ret_crash; + count = config_fmt_to_files(trfile_fmt, &trfiles); if (count <= 0) return (struct crash_t *)ret_crash; /* get data from last file */ - res = read_file(trfiles[count - 1], &size, &content); - if (res == -1) { - LOGE("read %s failed, error (%s)\n", + if (read_file(trfiles[count - 1], &size, &content) == -1) { + LOGE("failed to read %s, error (%s)\n", trfiles[count - 1], strerror(errno)); goto free_files; } if (!size) goto free_files; - res = get_data(content, ret_crash, data0, data1, data2); - if (res < 0) { - LOGE("get data error, error (%s)\n", - strerror(res)); - } + if (get_data(content, ret_crash, data0, d0len, data1, d1len, + data2, d2len) == -1) + LOGE("failed to get data\n"); free(content); diff --git a/tools/acrn-crashlog/acrnprobe/history.c b/tools/acrn-crashlog/acrnprobe/history.c index cf9e918f8..831b9e8a6 100644 --- a/tools/acrn-crashlog/acrnprobe/history.c +++ b/tools/acrn-crashlog/acrnprobe/history.c @@ -199,7 +199,8 @@ void hist_raise_uptime(char *lastuptime) loop_uptime_event = (hours / uptime_hours) + 1; key = generate_event_id((const char *)uptime->name, - NULL, KEY_SHORT); + uptime->name_len, + NULL, 0, KEY_SHORT); if (key == NULL) { LOGE("generate event id failed, error (%s)\n", strerror(errno)); @@ -213,11 +214,11 @@ void hist_raise_uptime(char *lastuptime) } } -void hist_raise_infoerror(char *type) +void hist_raise_infoerror(const char *type, size_t tlen) { char *key; - key = generate_event_id("ERROR", (const char *)type, KEY_SHORT); + key = generate_event_id("ERROR", 5, type, tlen, KEY_SHORT); if (key == NULL) { LOGE("generate event id failed, error (%s)\n", strerror(errno)); diff --git a/tools/acrn-crashlog/acrnprobe/include/history.h b/tools/acrn-crashlog/acrnprobe/include/history.h index 02a59bf8b..64e6decef 100644 --- a/tools/acrn-crashlog/acrnprobe/include/history.h +++ b/tools/acrn-crashlog/acrnprobe/include/history.h @@ -27,7 +27,7 @@ extern char *history_file; int prepare_history(void); -void hist_raise_infoerror(char *type); +void hist_raise_infoerror(const char *type, size_t tlen); void hist_raise_uptime(char *lastuptime); void hist_raise_event(const char *event, const char *type, const char *log, const char *lastuptime, const char *key); diff --git a/tools/acrn-crashlog/acrnprobe/include/load_conf.h b/tools/acrn-crashlog/acrnprobe/include/load_conf.h index 24dee37c4..d1b17d055 100644 --- a/tools/acrn-crashlog/acrnprobe/include/load_conf.h +++ b/tools/acrn-crashlog/acrnprobe/include/load_conf.h @@ -85,7 +85,8 @@ struct crash_t { int wd; int level; struct crash_t *(*reclassify)(const struct crash_t *, const char*, - char**, char**, char**); + char**, size_t *, char**, size_t *, + char**, size_t *); }; struct info_t { diff --git a/tools/acrn-crashlog/acrnprobe/include/probeutils.h b/tools/acrn-crashlog/acrnprobe/include/probeutils.h index 45530190e..885970ed5 100644 --- a/tools/acrn-crashlog/acrnprobe/include/probeutils.h +++ b/tools/acrn-crashlog/acrnprobe/include/probeutils.h @@ -41,11 +41,13 @@ enum key_type { int get_uptime_string(char newuptime[24], int *hours); int get_current_time_long(char buf[32]); unsigned long long get_uptime(void); -char *generate_event_id(const char *seed1, const char *seed2, - enum key_type type); -void generate_crashfile(const char *dir, const char *event, const char *hashkey, - const char *type, const char *data0, - const char *data1, const char *data2); +char *generate_event_id(const char *seed1, size_t slen1, const char *seed2, + size_t slen2, enum key_type type); +void generate_crashfile(const char *dir, const char *event, size_t elen, + const char *hashkey, size_t hlen, + const char *type, size_t tlen, const char *data0, + size_t d0len, const char *data1, size_t d1len, + const char *data2, size_t d2len); char *generate_log_dir(enum e_dir_mode mode, char *hashkey); int is_boot_id_changed(void); diff --git a/tools/acrn-crashlog/acrnprobe/probeutils.c b/tools/acrn-crashlog/acrnprobe/probeutils.c index 1839bf762..d08205ef0 100644 --- a/tools/acrn-crashlog/acrnprobe/probeutils.c +++ b/tools/acrn-crashlog/acrnprobe/probeutils.c @@ -95,7 +95,8 @@ int get_current_time_long(char *buf) return strftime(buf, LONG_TIME_SIZE, "%Y-%m-%d/%H:%M:%S ", time_val); } -static int compute_key(char *key, size_t key_len, const char *seed) +static int compute_key(char *key, size_t klen, const char *seed, + const size_t slen) { SHA256_CTX sha; char buf[VERSION_SIZE]; @@ -105,9 +106,9 @@ static int compute_key(char *key, size_t key_len, const char *seed) unsigned char results[SHA256_DIGEST_LENGTH]; size_t i; - if (!key || !seed) + if (!key || !seed || !slen) return -1; - if (key_len > SHA256_DIGEST_LENGTH * 2 || !key_len) + if (klen > SHA256_DIGEST_LENGTH * 2 || !klen) return -1; SHA256_Init(&sha); @@ -117,12 +118,12 @@ static int compute_key(char *key, size_t key_len, const char *seed) if (s_not_expect(len , VERSION_SIZE)) return -1; - SHA256_Update(&sha, (unsigned char *)buf, strlen(buf)); - SHA256_Update(&sha, (unsigned char *)seed, strlen(seed)); + SHA256_Update(&sha, (unsigned char *)buf, strnlen(buf, VERSION_SIZE)); + SHA256_Update(&sha, (unsigned char *)seed, strnlen(seed, slen)); SHA256_Final(results, &sha); - for (i = 0; i < key_len / 2; i++) { + for (i = 0; i < klen / 2; i++) { len = snprintf(tmp_key, 3, "%02x", results[i]); if (s_not_expect(len, 3)) return -1; @@ -144,15 +145,15 @@ static int compute_key(char *key, size_t key_len, const char *seed) * * @return a pointer to result haskkey if successful, or NULL if not. */ -char *generate_event_id(const char *seed1, const char *seed2, - enum key_type type) +char *generate_event_id(const char *seed1, size_t slen1, const char *seed2, + size_t slen2, enum key_type type) { int ret; char *buf; char *key; size_t klen; - if (!seed1) + if (!seed1 || !slen1) return NULL; if (type == KEY_SHORT) @@ -174,10 +175,10 @@ char *generate_event_id(const char *seed1, const char *seed2, free(key); return NULL; } - ret = compute_key(key, klen, (const char *)buf); + ret = compute_key(key, klen, (const char *)buf, slen1 + slen2); free(buf); } else { - ret = compute_key(key, klen, seed1); + ret = compute_key(key, klen, seed1, slen1); } if (ret < 0) { @@ -255,14 +256,15 @@ static int reserve_log_folder(enum e_dir_mode mode, char *dir, return 0; } -#define strcat_fmt(buf, fmt, ...) \ -(__extension__ \ -({ \ - char __buf[1024] = {'\0',}; \ - snprintf(__buf, sizeof(__buf), fmt, ##__VA_ARGS__); \ - strcat(buf, __buf); \ -}) \ -) +static char *cf_line(char *dest, const char *k, size_t klen, const char *v, + size_t vlen) +{ + char *t; + + t = mempcpy(dest, k, klen); + t = mempcpy(t, v, vlen); + return mempcpy(t, "\n", 1); +} /** * Create a crashfile with given params. @@ -273,69 +275,78 @@ static int reserve_log_folder(enum e_dir_mode mode, char *dir, * @param type Subtype of this event. * @param data* String obtained by get_data. */ -void generate_crashfile(const char *dir, const char *event, const char *hashkey, - const char *type, const char *data0, - const char *data1, const char *data2) +void generate_crashfile(const char *dir, + const char *event, size_t elen, + const char *hashkey, size_t hlen, + const char *type, size_t tlen, + const char *data0, size_t d0len, + const char *data1, size_t d1len, + const char *data2, size_t d2len) { char *buf; char *path; + char *tail; char datetime[LONG_TIME_SIZE]; char uptime[UPTIME_SIZE]; int hours; - int ret; const int fmtsize = 128; + size_t ltlen; + int n; int filesize; - datetime[0] = 0; - ret = get_current_time_long(datetime); - if (ret <= 0) + if (!dir || !event || !elen || !hashkey || !hlen || + !type || !tlen) + return; + if (d0len > 0 && !data0) + return; + if (d1len > 0 && !data1) + return; + if (d2len > 0 && !data2) return; - uptime[0] = 0; - get_uptime_string(uptime, &hours); - filesize = fmtsize + strlen(event) + - strlen(hashkey) + strlen(guuid) + - strlen(datetime) + strlen(uptime) + - strlen(gbuildversion) + strlen(type); - if (data0) - filesize += strlen(data0); - if (data1) - filesize += strlen(data1); - if (data2) - filesize += strlen(data2); + ltlen = get_current_time_long(datetime); + if (!ltlen) + return; + n = get_uptime_string(uptime, &hours); + if (n < 0) + return; + + filesize = fmtsize + ltlen + n + elen + hlen + tlen + d0len + d1len + + d2len + strnlen(guuid, UUID_SIZE) + + strnlen(gbuildversion, BUILD_VERSION_SIZE); buf = malloc(filesize); if (buf == NULL) { - LOGE("compute string failed, out of memory\n"); + LOGE("out of memory\n"); return; } - memset(buf, 0, filesize); - strcat_fmt(buf, "EVENT=%s\n", event); - strcat_fmt(buf, "ID=%s\n", hashkey); - strcat_fmt(buf, "DEVICEID=%s\n", guuid); - strcat_fmt(buf, "DATE=%s\n", datetime); - strcat_fmt(buf, "UPTIME=%s\n", uptime); - strcat_fmt(buf, "BUILD=%s\n", gbuildversion); - strcat_fmt(buf, "TYPE=%s\n", type); - if (data0) - strcat_fmt(buf, "DATA0=%s\n", data0); - if (data1) - strcat_fmt(buf, "DATA1=%s\n", data1); - if (data2) - strcat_fmt(buf, "DATA2=%s\n", data2); - strcat(buf, "_END\n"); + tail = cf_line(buf, "EVENT=", 6, event, elen); + tail = cf_line(tail, "ID=", 3, hashkey, hlen); + tail = cf_line(tail, "DEVICEID=", 9, guuid, strnlen(guuid, UUID_SIZE)); + tail = cf_line(tail, "DATE=", 5, datetime, ltlen); + tail = cf_line(tail, "UPTIME=", 7, uptime, n); + tail = cf_line(tail, "BUILD=", 6, gbuildversion, + strnlen(gbuildversion, BUILD_VERSION_SIZE)); + tail = cf_line(tail, "TYPE=", 5, type, tlen); - ret = asprintf(&path, "%s/%s", dir, "crashfile"); - if (ret < 0) { - LOGE("compute string failed, out of memory\n"); + if (d0len) + tail = cf_line(tail, "DATA0=", 6, data0, d0len); + if (d1len) + tail = cf_line(tail, "DATA1=", 6, data1, d1len); + if (d2len) + tail = cf_line(tail, "DATA2=", 6, data2, d2len); + tail = mempcpy(tail, "_END\n", 5); + *tail = '\0'; + + if (asprintf(&path, "%s/crashfile", dir) == -1) { + LOGE("out of memory\n"); free(buf); return; } - ret = overwrite_file(path, buf); - if (ret) - LOGE("new crashfile (%s) fail, error (%s)\n", path, + if (overwrite_file(path, buf) != 0) + LOGE("failed to new crashfile (%s), error (%s)\n", path, strerror(errno)); free(buf); @@ -364,14 +375,14 @@ char *generate_log_dir(enum e_dir_mode mode, char *hashkey) ret = asprintf(&path, "%s%d_%s", dir, current, hashkey); if (ret == -1) { LOGE("construct log path failed, out of memory\n"); - hist_raise_infoerror("DIR CREATE"); + hist_raise_infoerror("DIR CREATE", 10); return NULL; } ret = mkdir(path, 0777); if (ret == -1) { LOGE("Cannot create dir %s\n", path); - hist_raise_infoerror("DIR CREATE"); + hist_raise_infoerror("DIR CREATE", 10); free(path); return NULL; } diff --git a/tools/acrn-crashlog/acrnprobe/sender.c b/tools/acrn-crashlog/acrnprobe/sender.c index 0dd315a7b..f782e06d6 100644 --- a/tools/acrn-crashlog/acrnprobe/sender.c +++ b/tools/acrn-crashlog/acrnprobe/sender.c @@ -275,7 +275,7 @@ static void crashlog_get_log(struct log_t *log, void *data) quota = atoi(crashlog->spacequota); if (!space_available(crashlog->outdir, quota)) { - hist_raise_infoerror("SPACE_FULL"); + hist_raise_infoerror("SPACE_FULL", 10); return; } @@ -357,7 +357,8 @@ static void telemd_send_crash(struct event_t *e) return; } - eventid = generate_event_id((const char *)class, NULL, KEY_LONG); + eventid = generate_event_id((const char *)class, ret, NULL, 0, + KEY_LONG); if (eventid == NULL) { LOGE("generate eventid failed, error (%s)\n", strerror(errno)); goto free_class; @@ -436,7 +437,8 @@ static void telemd_send_info(struct event_t *e) return; } - eventid = generate_event_id((const char *)class, NULL, KEY_LONG); + eventid = generate_event_id((const char *)class, ret, NULL, 0, + KEY_LONG); if (eventid == NULL) { LOGE("generate eventid failed, error (%s)\n", strerror(errno)); goto free_class; @@ -611,7 +613,8 @@ static int telemd_new_vmevent(const char *line_to_sync, goto free_vmlogpath; } - eventid = generate_event_id((const char *)class, NULL, KEY_LONG); + eventid = generate_event_id((const char *)class, res, NULL, 0, + KEY_LONG); if (eventid == NULL) { LOGE("generate eventid failed, error (%s)\n", strerror(errno)); ret = VMEVT_DEFER; @@ -713,53 +716,67 @@ static void telemd_send(struct event_t *e) static void crashlog_send_crash(struct event_t *e) { struct crash_t *crash; - struct log_t *log; - struct sender_t *crashlog; - char *key = NULL; + char *key; + char *data0; + char *data1; + char *data2; + size_t d0len; + size_t d1len; + size_t d2len; char *trfile = NULL; - char *data0 = NULL; - char *data1 = NULL; - char *data2 = NULL; - int id; - int ret = 0; - int quota; + struct sender_t *crashlog = get_sender_by_name("crashlog"); struct crash_t *rcrash = (struct crash_t *)e->private; + if (!crashlog) + return; + if (!strcmp(rcrash->trigger->type, "dir")) { - ret = asprintf(&trfile, "%s/%s", rcrash->trigger->path, - e->path); - if (ret < 0) { - LOGE("compute string failed, out of memory\n"); + if (asprintf(&trfile, "%s/%s", rcrash->trigger->path, + e->path) == -1) { + LOGE("out of memory\n"); return; } } - crash = rcrash->reclassify(rcrash, trfile, &data0, &data1, &data2); + crash = rcrash->reclassify(rcrash, trfile, &data0, &d0len, &data1, + &d1len, &data2, &d2len); + if (trfile) + free(trfile); if (crash == NULL) { - LOGE("reclassify crash (%s) failed\n", rcrash->name); - goto free_trfile; + LOGE("failed to reclassify rcrash (%s)\n", rcrash->name); + return; } - /* change the class for other senders */ e->private = (void *)crash; - key = generate_event_id("CRASH", (const char *)crash->name, KEY_SHORT); + + key = generate_event_id("CRASH", 5, (const char *)crash->name, + crash->name_len, KEY_SHORT); if (key == NULL) { - LOGE("generate event id failed, error (%s)\n", + LOGE("failed to generate event id, error (%s)\n", strerror(errno)); goto free_data; } - if (to_collect_logs(crash) || - !strcmp(e->channel, "inotify")) { + /* check space before collecting logs */ + if (!space_available(crashlog->outdir, atoi(crashlog->spacequota))) { + hist_raise_infoerror("SPACE_FULL", 10); + hist_raise_event("CRASH", crash->name, NULL, "", key); + goto free_key; + } + + if (to_collect_logs(crash) || !strcmp(e->channel, "inotify")) { + struct log_t *log; + int id; + e->dir = generate_log_dir(MODE_CRASH, key); if (e->dir == NULL) { - LOGE("generate crashlog dir failed\n"); + LOGE("failed to generate crashlog dir\n"); goto free_key; } - generate_crashfile(e->dir, "CRASH", key, - crash->name, - data0, data1, data2); + generate_crashfile(e->dir, "CRASH", 5, key, SHORT_KEY_LENGTH, + crash->name, crash->name_len, + data0, d0len, data1, d1len, data2, d2len); for_each_log_collect(id, log, crash) { if (!log) continue; @@ -769,36 +786,25 @@ static void crashlog_send_crash(struct event_t *e) } - crashlog = get_sender_by_name("crashlog"); - if (!crashlog) - goto free_key; - - quota = atoi(crashlog->spacequota); - if (!space_available(crashlog->outdir, quota)) { - hist_raise_infoerror("SPACE_FULL"); - } else if (!strcmp(e->channel, "inotify")) { + if (!strcmp(e->channel, "inotify")) { /* get the trigger file */ char *src; char *des; - ret = asprintf(&des, "%s/%s", e->dir, e->path); - if (ret < 0) { - LOGE("compute string failed, out of memory\n"); + if (asprintf(&des, "%s/%s", e->dir, e->path) == -1) { + LOGE("out of memory\n"); goto free_key; } - ret = asprintf(&src, "%s/%s", crash->trigger->path, e->path); - if (ret < 0) { - LOGE("compute string failed, out of memory\n"); + if (asprintf(&src, "%s/%s", crash->trigger->path, + e->path) == -1) { + LOGE("out of memory\n"); free(des); goto free_key; } - ret = do_copy_tail(src, des, 0); - if (ret < 0) { - LOGE("copy (%s) to (%s) failed, error (%s)\n", - src, des, strerror(-ret)); - } + if (do_copy_tail(src, des, 0) < 0) + LOGE("failed to copy (%s) to (%s)\n", src, des); free(src); free(des); @@ -809,11 +815,12 @@ static void crashlog_send_crash(struct event_t *e) free_key: free(key); free_data: - free(data0); - free(data1); - free(data2); -free_trfile: - free(trfile); + if (data0) + free(data0); + if (data1) + free(data1); + if (data2) + free(data2); } static void crashlog_send_info(struct event_t *e) @@ -821,8 +828,8 @@ static void crashlog_send_info(struct event_t *e) int id; struct info_t *info = (struct info_t *)e->private; struct log_t *log; - char *key = generate_event_id("INFO", (const char *)info->name, - KEY_SHORT); + char *key = generate_event_id("INFO", 4, (const char *)info->name, + info->name_len, KEY_SHORT); if (key == NULL) { LOGE("generate event id failed, error (%s)\n", @@ -866,7 +873,7 @@ static void crashlog_send_reboot(void) return; if (swupdated(crashlog)) { - key = generate_event_id("INFO", "SWUPDATE", KEY_SHORT); + key = generate_event_id("INFO", 4, "SWUPDATE", 8, KEY_SHORT); if (key == NULL) { LOGE("generate event id failed, error (%s)\n", strerror(errno)); @@ -878,7 +885,8 @@ static void crashlog_send_reboot(void) } read_startupreason(reason, sizeof(reason)); - key = generate_event_id("REBOOT", (const char *)reason, KEY_SHORT); + key = generate_event_id("REBOOT", 6, (const char *)reason, + strnlen(reason, REBOOT_REASON_SIZE), KEY_SHORT); if (key == NULL) { LOGE("generate event id failed, error (%s)\n", strerror(errno)); @@ -934,11 +942,12 @@ static int crashlog_new_vmevent(const char *line_to_sync, quota = atoi(crashlog->spacequota); if (!space_available(crashlog->outdir, quota)) { - hist_raise_infoerror("SPACE_FULL"); + hist_raise_infoerror("SPACE_FULL", 10); return ret; } - key = generate_event_id("SOS", (const char *)vmkey, KEY_SHORT); + key = generate_event_id("SOS", 3, (const char *)vmkey, + strnlen(vmkey, ANDROID_WORD_LEN), KEY_SHORT); if (key == NULL) { LOGE("generate event id failed, error (%s)\n", strerror(errno)); @@ -952,6 +961,12 @@ static int crashlog_new_vmevent(const char *line_to_sync, goto free_key; } + generate_crashfile(dir, event, strnlen(event, ANDROID_WORD_LEN), + key, SHORT_KEY_LENGTH, + type, strnlen(type, ANDROID_WORD_LEN), + vm->name, vm->name_len, + vmkey, strnlen(vmkey, ANDROID_WORD_LEN), NULL, 0); + /* if line contains log, we need dump each file in the logdir */ log = strstr(rest, "/logs/"); @@ -969,14 +984,12 @@ static int crashlog_new_vmevent(const char *line_to_sync, } res = remove(dir); if (res == -1 && errno != ENOENT) - LOGE("remove %s faield (%d)\n", dir, -errno); + LOGE("failed to remove %s (%d)\n", dir, -errno); goto free_dir; } } - generate_crashfile(dir, event, key, type, vm->name, - vmkey, NULL); hist_raise_event(vm->name, type, dir, "", key); free_dir: @@ -1066,15 +1079,13 @@ int init_sender(void) close(fd); } - if (!strncmp(sender->name, "crashlog", - strlen(sender->name))) { + if (!strcmp(sender->name, "crashlog")) { sender->send = crashlog_send; ret = prepare_history(); if (ret) return -1; #ifdef HAVE_TELEMETRICS_CLIENT - } else if (!strncmp(sender->name, "telemd", - strlen(sender->name))) { + } else if (!strcmp(sender->name, "telemd")) { sender->send = telemd_send; #endif } diff --git a/tools/acrn-crashlog/acrnprobe/startupreason.c b/tools/acrn-crashlog/acrnprobe/startupreason.c index 9c29b2a62..7ca5a45eb 100644 --- a/tools/acrn-crashlog/acrnprobe/startupreason.c +++ b/tools/acrn-crashlog/acrnprobe/startupreason.c @@ -35,10 +35,10 @@ static int get_cmdline_bootreason(char *bootreason, const size_t limit) int res; unsigned long size; char *start, *p1, *p2, *end; - void *cmdline; - const char key[] = "ABL.reset="; + char *cmdline; + const char *key = "ABL.reset="; - res = read_file(CURRENT_KERNEL_CMDLINE, &size, &cmdline); + res = read_file(CURRENT_KERNEL_CMDLINE, &size, (void *)&cmdline); if (res < 0) { LOGE("failed to read file %s - %s\n", CURRENT_KERNEL_CMDLINE, strerror(errno)); @@ -66,13 +66,15 @@ static int get_cmdline_bootreason(char *bootreason, const size_t limit) else end = MAX(p1, p2); - if (end) - *end = 0; + if (!end) + end = cmdline + size; - const size_t len = MIN(strlen(start), limit - 1); + const size_t len = MIN((size_t)(end - start), (size_t)(limit - 1)); - if (len > 0) - memcpy(bootreason, start, len + 1); + if (len > 0) { + memcpy(bootreason, start, len); + *(bootreason + len) = 0; + } free(cmdline); return len; @@ -99,6 +101,9 @@ void read_startupreason(char *startupreason, const size_t limit) int res; static char reboot_reason_cache[REBOOT_REASON_SIZE]; + if (!startupreason || !limit) + return; + if (!reboot_reason_cache[0]) { /* fill cache */ res = get_default_bootreason(reboot_reason_cache, @@ -108,7 +113,8 @@ void read_startupreason(char *startupreason, const size_t limit) sizeof(reboot_reason_cache)); } - const size_t len = MIN(strlen(reboot_reason_cache), limit - 1); + const size_t len = MIN(strnlen(reboot_reason_cache, REBOOT_REASON_SIZE), + limit - 1); memcpy(startupreason, reboot_reason_cache, len); *(startupreason + len) = 0;