From 2e74ca0f15d6d25568f5af1cc9cd30b4b01aa849 Mon Sep 17 00:00:00 2001 From: Jakub Filak Date: Tue, 14 Oct 2014 03:15:28 +0200 Subject: [PATCH] journal-oops: use the length result of sd_journal_get_data() journald doesn't guarantee NULL terminated strings returned from sd_journal_get_data(). It usually works but not always. This patch fixes the issue by using the length of field data instead of assuming that string is NULL terminated. Resolves: #1141549 Signed-off-by: Jakub Filak --- src/plugins/abrt-dump-journal-oops.c | 13 ++++++----- src/plugins/abrt-journal.c | 43 ++++++++++++++++++++++-------------- src/plugins/abrt-journal.h | 8 ++++--- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/plugins/abrt-dump-journal-oops.c b/src/plugins/abrt-dump-journal-oops.c index 3f1f419..0ff9fe0 100644 --- a/src/plugins/abrt-dump-journal-oops.c +++ b/src/plugins/abrt-dump-journal-oops.c @@ -38,8 +38,8 @@ static GList* abrt_journal_extract_kernel_oops(abrt_journal_t *journal) do { - const char *line = NULL; - if (abrt_journal_get_log_line(journal, &line) < 0) + char *line = abrt_journal_get_log_line(journal); + if (line == NULL) error_msg_and_die(_("Cannot read journal data.")); if (lines_info_count == lines_info_size) @@ -48,10 +48,13 @@ static GList* abrt_journal_extract_kernel_oops(abrt_journal_t *journal) lines_info = xrealloc(lines_info, lines_info_size * sizeof(lines_info[0])); } - lines_info[lines_info_count].level = koops_line_skip_level(&line); - koops_line_skip_jiffies(&line); + char *orig_line = line; + lines_info[lines_info_count].level = koops_line_skip_level((const char **)&line); + koops_line_skip_jiffies((const char **)&line); - lines_info[lines_info_count].ptr = xstrdup(line); + memmove(orig_line, line, strlen(line) + 1); + + lines_info[lines_info_count].ptr = orig_line; ++lines_info_count; } diff --git a/src/plugins/abrt-journal.c b/src/plugins/abrt-journal.c index 89c8393..e0ae159 100644 --- a/src/plugins/abrt-journal.c +++ b/src/plugins/abrt-journal.c @@ -23,6 +23,12 @@ #include +/* + * http://www.freedesktop.org/software/systemd/man/sd_journal_get_data.html + * sd_journal_set_data_threshold() : This threshold defaults to 64K by default. + */ +#define JOURNALD_MAX_FIELD_SIZE (64*1024) + struct abrt_journal { @@ -84,33 +90,38 @@ int abrt_journal_get_field(abrt_journal_t *journal, const char *field, const voi return 0; } -int abrt_journal_get_string_field(abrt_journal_t *journal, const char *field, const char **value) +char *abrt_journal_get_string_field(abrt_journal_t *journal, const char *field, char *value) { - size_t value_len; - const int r = abrt_journal_get_field(journal, field, (const void **)value, &value_len); + size_t data_len; + const char *data; + const int r = abrt_journal_get_field(journal, field, (const void **)&data, &data_len); if (r < 0) { - return r; + log_notice("Cannot read journal data"); + return NULL; } const size_t pfx_len = strlen(field) + 1; - if (value_len < pfx_len) + if (data_len < pfx_len) { error_msg("Invalid data format from journal: field data are not prefixed with field name"); - return -EBADMSG; + return NULL; } - *value += pfx_len; - return 0; + const size_t len = data_len - pfx_len; + if (value == NULL) + return xstrndup(data + pfx_len, len); + /*else*/ + + strncpy(value, data + pfx_len, len); + /* journal data are not NULL terminated strings, so terminate the string */ + value[len] = '\0'; + return value; } -int abrt_journal_get_log_line(abrt_journal_t *journal, const char **line) +char *abrt_journal_get_log_line(abrt_journal_t *journal) { - const int r = abrt_journal_get_string_field(journal, "MESSAGE", line); - if (r < 0) - log_notice("Cannot read journal data. Exiting"); - - return r; + return abrt_journal_get_string_field(journal, "MESSAGE", NULL); } int abrt_journal_get_cursor(abrt_journal_t *journal, char **cursor) @@ -272,9 +283,9 @@ void abrt_journal_watch_notify_strings(abrt_journal_watch_t *watch, void *data) { struct abrt_journal_watch_notify_strings *conf = (struct abrt_journal_watch_notify_strings *)data; - const char *message = NULL; + char message[JOURNALD_MAX_FIELD_SIZE + 1]; - if (abrt_journal_get_string_field(abrt_journal_watch_get_journal(watch), "MESSAGE", &message) < 0) + if (abrt_journal_get_string_field(abrt_journal_watch_get_journal(watch), "MESSAGE", (char *)message) == NULL) error_msg_and_die("Cannot read journal data."); GList *cur = conf->strings; diff --git a/src/plugins/abrt-journal.h b/src/plugins/abrt-journal.h index 219cf60..d509d96 100644 --- a/src/plugins/abrt-journal.h +++ b/src/plugins/abrt-journal.h @@ -40,11 +40,13 @@ int abrt_journal_get_field(abrt_journal_t *journal, const void **value, size_t *value_len); -int abrt_journal_get_string_field(abrt_journal_t *journal, +/* Returns allocated memory if value is NULL; otherwise makes copy of journald + * field to memory pointed by value arg. */ +char *abrt_journal_get_string_field(abrt_journal_t *journal, const char *field, - const char **value); + char *value); -int abrt_journal_get_log_line(abrt_journal_t *journal, const char **line); +char *abrt_journal_get_log_line(abrt_journal_t *journal); int abrt_journal_get_cursor(abrt_journal_t *journal, char **cursor); -- 2.1.0