From patchwork Tue Sep 5 19:11:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 9939529 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 54734604D4 for ; Tue, 5 Sep 2017 19:11:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 456A3289EB for ; Tue, 5 Sep 2017 19:11:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3A7B7289FF; Tue, 5 Sep 2017 19:11:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A62BC289EB for ; Tue, 5 Sep 2017 19:11:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752592AbdIETLH (ORCPT ); Tue, 5 Sep 2017 15:11:07 -0400 Received: from mail-wr0-f195.google.com ([209.85.128.195]:36279 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752459AbdIETLD (ORCPT ); Tue, 5 Sep 2017 15:11:03 -0400 Received: by mail-wr0-f195.google.com with SMTP id 40so2135647wrv.3; Tue, 05 Sep 2017 12:11:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=BOd31Ec3YrEB0xRTwSC2b5wCVPvbgUuitNNuGCe1eEg=; b=ftS5Reud2r8rg9cjv74sT0FpXs1tBMl4nw0HbZXRLDyLFTWLK52lvcIlu76D14/dbm t+TWdKJKhHgxXQOltbjxHzreRyNGeZBB46A7ufXumypcmloYQARh9CvlSG+dHliOXWW+ R10MIT0+/KGfPr7YfauW/wN6U0/n8HixgpVfByoT7HwJtX7Fv+P6sKBt7REBGLI84ghg +Uq23jGGu058Hj4CaCMfAmXoAiDaQAozLiqJJ0gtLjR6mYWLmav/AAeqlS+/onk8e8ep ZR0PEbzaGDUNGBzXm670kXpH44tyEyfwnPgvMP29up5pkcSyibQlDaEeGsKbhAPRjHsX oN7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=BOd31Ec3YrEB0xRTwSC2b5wCVPvbgUuitNNuGCe1eEg=; b=B9vFYwneqDTD5HVP7GhoZn2UnmZJsDb+AvzDP4OS5wH5puzk1+q49T2qRFKYsPXrzj BKOe+FtRsIx+RIhf+Lbd+kvTOmaBbbcZTYhKS640ys+bM7r10LfCS6mLxMpEO78QxczI 1/5vi7OLBKkQF9jjAHBZHRbFYUVqR6qO86YSDQnaTn924gv8jmwlgWZFGfrRC8wN45vB 4qI1xkdSUbuFIP4j7htI2sPbmh1TzYmvO2t/+SYcsRWk9JSSuTf9qyu81flQn7kJxrX6 xWG3q45Bd+Bo3flkYq4o0Jd5xdcL3s7/Oc94tvBivuhYuceTiEdZ7LhtMTcw9nEaCfXN 2PVw== X-Gm-Message-State: AHPjjUirXX2EqqI7IYicuMQ5eDd09p9OIX4gQObFmoMLY0+YkQZCENd8 yEYw1De5c5e9uA== X-Google-Smtp-Source: ADKCNb7Uqs5rBd6jllxlEFwnpWDrLmbbNwujLuEgUGsTxL6RF52mYlA9Kp7C9xvW+cLUbxGSa3Wcfg== X-Received: by 10.223.131.99 with SMTP id 90mr49516wrd.198.1504638662058; Tue, 05 Sep 2017 12:11:02 -0700 (PDT) Received: from localhost.localdomain (bzq-79-182-137-119.red.bezeqint.net. [79.182.137.119]) by smtp.gmail.com with ESMTPSA id 30sm1829015wry.34.2017.09.05.12.11.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 05 Sep 2017 12:11:01 -0700 (PDT) From: Amir Goldstein To: Eryu Guan Cc: Josef Bacik , fstests@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v3 07/13] replay-log: add validations for corrupt log entries Date: Tue, 5 Sep 2017 22:11:14 +0300 Message-Id: <1504638680-25682-8-git-send-email-amir73il@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504638680-25682-1-git-send-email-amir73il@gmail.com> References: <1504638680-25682-1-git-send-email-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 | 84 ++++++++++++++++++++++++++++++++++----------- src/log-writes/log-writes.h | 2 ++ src/log-writes/replay-log.c | 7 ++-- 3 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/log-writes/log-writes.c b/src/log-writes/log-writes.c index a215fef..dbfeef7 100644 --- a/src/log-writes/log-writes.c +++ b/src/log-writes/log-writes.c @@ -118,6 +118,26 @@ int log_discard(struct log *log, struct log_write_entry *entry) } /* + * @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. * @read_data: read the entry data as well, entry must be log->sectorsize sized @@ -146,24 +166,32 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, fprintf(stderr, "Error reading entry: %d\n", errno); return -1; } + if (!log_entry_valid(entry)) { + fprintf(stderr, "Malformed entry @%llu\n", + log->cur_pos / log->sectorsize); + return -1; + } log->cur_entry++; size = le64_to_cpu(entry->nr_sectors) * log->sectorsize; if (read_size < log->sectorsize) { - if (lseek(log->logfd, - log->sectorsize - sizeof(struct log_write_entry), - SEEK_CUR) == (off_t)-1) { + log->cur_pos = lseek(log->logfd, + log->sectorsize - sizeof(struct log_write_entry), SEEK_CUR); + if (log->cur_pos == (off_t)-1) { fprintf(stderr, "Error seeking in log: %d\n", errno); return -1; } + } else { + log->cur_pos += read_size; } - 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, log->cur_pos / 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; @@ -183,6 +211,7 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, free(buf); return -1; } + log->cur_pos += size; offset = le64_to_cpu(entry->sector) * log->sectorsize; ret = pwrite(log->replayfd, buf, size, offset); @@ -212,7 +241,8 @@ int log_seek_entry(struct log *log, u64 entry_num) } /* Skip the first sector containing the log super block */ - if (lseek(log->logfd, log->sectorsize, SEEK_SET) == (off_t)-1) { + log->cur_pos = lseek(log->logfd, log->sectorsize, SEEK_SET); + if (log->cur_pos == (off_t)-1) { fprintf(stderr, "Error seeking in file: %d\n", errno); return -1; } @@ -229,9 +259,14 @@ int log_seek_entry(struct log *log, u64 entry_num) fprintf(stderr, "Error reading entry: %d\n", errno); return -1; } + if (!log_entry_valid(&entry)) { + fprintf(stderr, "Malformed entry @%llu\n", + log->cur_pos / 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, log->cur_pos / 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)); @@ -240,7 +275,8 @@ int log_seek_entry(struct log *log, u64 entry_num) if (!(flags & LOG_DISCARD_FLAG)) seek_size += le64_to_cpu(entry.nr_sectors) * log->sectorsize; - if (lseek(log->logfd, seek_size, SEEK_CUR) == (off_t)-1) { + log->cur_pos = lseek(log->logfd, seek_size, SEEK_CUR); + if (log->cur_pos == (off_t)-1) { fprintf(stderr, "Error seeking in file: %d\n", errno); return -1; } @@ -277,29 +313,37 @@ int log_seek_next_entry(struct log *log, struct log_write_entry *entry, fprintf(stderr, "Error reading entry: %d\n", errno); return -1; } + if (!log_entry_valid(entry)) { + fprintf(stderr, "Malformed entry @%llu\n", + log->cur_pos / log->sectorsize); + return -1; + } log->cur_entry++; if (read_size < log->sectorsize) { - if (lseek(log->logfd, - log->sectorsize - sizeof(struct log_write_entry), - SEEK_CUR) == (off_t)-1) { + log->cur_pos = lseek(log->logfd, + log->sectorsize - sizeof(struct log_write_entry), SEEK_CUR); + if (log->cur_pos == (off_t)-1) { fprintf(stderr, "Error seeking in log: %d\n", errno); return -1; } + } else { + log->cur_pos += read_size; } 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, log->cur_pos / 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; - if (lseek(log->logfd, read_size, SEEK_CUR) == (off_t)-1) { + log->cur_pos = lseek(log->logfd, read_size, SEEK_CUR); + if (log->cur_pos == (off_t)-1) { fprintf(stderr, "Error seeking in log: %d\n", errno); return -1; } @@ -369,8 +413,8 @@ struct log *log_open(char *logfile, char *replayfile) log->nr_entries = le64_to_cpu(super.nr_entries); log->max_zero_size = 128 * 1024 * 1024; - if (lseek(log->logfd, log->sectorsize - sizeof(super), SEEK_CUR) == - (off_t) -1) { + log->cur_pos = lseek(log->logfd, log->sectorsize - sizeof(super), SEEK_CUR); + if (log->cur_pos == (off_t) -1) { fprintf(stderr, "Error seeking to first entry: %d\n", errno); log_free(log); return NULL; diff --git a/src/log-writes/log-writes.h b/src/log-writes/log-writes.h index 6cadb66..c89b119 100644 --- a/src/log-writes/log-writes.h +++ b/src/log-writes/log-writes.h @@ -50,6 +50,8 @@ struct log_write_entry { __le64 nr_sectors; __le64 flags; __le64 data_len; + /* Read extra byte when seeking to verify that header is zero padded */ + 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 c3de9c4..cf67931 100644 --- a/src/log-writes/replay-log.c +++ b/src/log-writes/replay-log.c @@ -75,7 +75,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); /* mark data begins after entry header */ - char *buf = (char *)(entry + 1); + char *buf = entry->data; /* entry buffer is padded with at least 1 zero after data_len */ u64 buflen = le64_to_cpu(entry->data_len) + 1; @@ -293,8 +293,9 @@ 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); + printf("%llu@%llu\n", + (unsigned long long)log->cur_entry - 1, + log->cur_pos / log->sectorsize); log_free(log); return 0; }