From bb946deb0dc285867be394613ddb19ce281392cc Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Fri, 25 Aug 2017 13:27:56 +0300 Subject: [PATCH] replay-log: add validations for corrupt log entries Check for all zeros entry and for non zero padded entry and report log offset of corrupted log entry. Also report log offsets with -v and -vv debug prints. Signed-off-by: Amir Goldstein --- src/log-writes/log-writes.c | 55 +++++++++++++++++++++++++++++++------ src/log-writes/log-writes.h | 1 + src/log-writes/replay-log.c | 8 ++++-- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/log-writes/log-writes.c b/src/log-writes/log-writes.c index fa4f3f3b4..673a769ef 100644 --- a/src/log-writes/log-writes.c +++ b/src/log-writes/log-writes.c @@ -117,6 +117,26 @@ int log_discard(struct log *log, struct log_write_entry *entry) return 0; } +/* + * @entry: entry to be replayed. + * + * @return: 1 if the entry is sane, 0 if it is invalid. + * + * Check if this is a sane log entry. + */ +int log_entry_valid(struct log_write_entry *entry) +{ + u64 flags = le64_to_cpu(entry->flags); + + /* Suspect all zeroes entry */ + if (!flags && !entry->nr_sectors) + return 0; + /* Suspect non zero padded entry */ + if (flags != LOG_MARK_FLAG && entry->data[0] != 0) + return 0; + return 1; +} + /* * @log: the log we are replaying. * @entry: where we put the entry. @@ -141,11 +161,16 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, if (log->cur_entry >= log->nr_entries) return 1; + offset = lseek(log->logfd, 0, SEEK_CUR); ret = read(log->logfd, entry, read_size); if (ret != read_size) { fprintf(stderr, "Error reading entry: %d\n", errno); return -1; } + if (!log_entry_valid(entry)) { + fprintf(stderr, "Malformed entry @%llu\n", offset / log->sectorsize); + return -1; + } log->cur_entry++; size = le64_to_cpu(entry->nr_sectors) * log->sectorsize; @@ -158,12 +183,13 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, } } - if (log_writes_verbose) - printf("replaying %d: sector %llu, size %llu, flags %llu\n", - (int)log->cur_entry - 1, + if (log_writes_verbose) { + printf("replaying %d@%llu: sector %llu, size %llu, flags %llu\n", + (int)log->cur_entry - 1, offset / log->sectorsize, (unsigned long long)le64_to_cpu(entry->sector), (unsigned long long)size, (unsigned long long)le64_to_cpu(entry->flags)); + } if (!size) return 0; @@ -221,15 +247,20 @@ int log_seek_entry(struct log *log, u64 entry_num) ssize_t ret; off_t seek_size; u64 flags; + off_t offset = lseek(log->logfd, 0, SEEK_CUR); ret = read(log->logfd, &entry, sizeof(entry)); if (ret != sizeof(entry)) { fprintf(stderr, "Error reading entry: %d\n", errno); return -1; } + if (!log_entry_valid(&entry)) { + fprintf(stderr, "Malformed entry @%llu\n", offset / log->sectorsize); + return -1; + } if (log_writes_verbose > 1) - printf("seek entry %d: %llu, size %llu, flags %llu\n", - (int)i, + printf("seek entry %d@%llu: %llu, size %llu, flags %llu\n", + (int)i, offset / log->sectorsize, (unsigned long long)le64_to_cpu(entry.sector), (unsigned long long)le64_to_cpu(entry.nr_sectors), (unsigned long long)le64_to_cpu(entry.flags)); @@ -264,17 +295,23 @@ int log_seek_next_entry(struct log *log, struct log_write_entry *entry, { size_t read_size = read_data ? log->sectorsize : sizeof(struct log_write_entry); + off_t offset; u64 flags; ssize_t ret; if (log->cur_entry >= log->nr_entries) return 1; + offset = lseek(log->logfd, 0, SEEK_CUR); ret = read(log->logfd, entry, read_size); if (ret != read_size) { fprintf(stderr, "Error reading entry: %d\n", errno); return -1; } + if (!log_entry_valid(entry)) { + fprintf(stderr, "Malformed entry @%llu\n", offset / log->sectorsize); + return -1; + } log->cur_entry++; if (read_size < log->sectorsize) { @@ -286,14 +323,14 @@ int log_seek_next_entry(struct log *log, struct log_write_entry *entry, } } if (log_writes_verbose > 1) - printf("seek entry %d: %llu, size %llu, flags %llu\n", - (int)log->cur_entry - 1, + printf("seek entry %d@%llu: %llu, size %llu, flags %llu\n", + (int)log->cur_entry - 1, offset / log->sectorsize, (unsigned long long)le64_to_cpu(entry->sector), (unsigned long long)le64_to_cpu(entry->nr_sectors), (unsigned long long)le64_to_cpu(entry->flags)); - flags = le32_to_cpu(entry->flags); - read_size = le32_to_cpu(entry->nr_sectors) * log->sectorsize; + flags = le64_to_cpu(entry->flags); + read_size = le64_to_cpu(entry->nr_sectors) * log->sectorsize; if (!read_size || (flags & LOG_DISCARD_FLAG)) return 0; diff --git a/src/log-writes/log-writes.h b/src/log-writes/log-writes.h index 13f98ffe1..bbc7e3454 100644 --- a/src/log-writes/log-writes.h +++ b/src/log-writes/log-writes.h @@ -43,6 +43,7 @@ struct log_write_entry { __le64 nr_sectors; __le64 flags; __le64 data_len; + char data[1]; }; #define LOG_IGNORE_DISCARD (1 << 0) diff --git a/src/log-writes/replay-log.c b/src/log-writes/replay-log.c index 759c3c702..a507b5484 100644 --- a/src/log-writes/replay-log.c +++ b/src/log-writes/replay-log.c @@ -69,7 +69,7 @@ static int should_stop(struct log_write_entry *entry, u64 stop_flags, { u64 flags = le64_to_cpu(entry->flags); int check_mark = (stop_flags & LOG_MARK_FLAG); - char *buf = (char *)(entry + 1); + char *buf = entry->data; if (flags & stop_flags) { if (!check_mark) @@ -284,8 +284,10 @@ int main(int argc, char **argv) num_entries++; if ((run_limit && num_entries == run_limit) || should_stop(entry, stop_flags, end_mark)) { - printf("%llu\n", - (unsigned long long)log->cur_entry - 1); + off_t offset = lseek(log->logfd, 0, SEEK_CUR); + + printf("%llu@%llu\n", + (unsigned long long)log->cur_entry - 1, offset / log->sectorsize); log_free(log); return 0; }