From patchwork Thu Sep 7 10:03:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 9942007 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 76219602CC for ; Thu, 7 Sep 2017 10:03:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 87CB628600 for ; Thu, 7 Sep 2017 10:03:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7C8A828607; Thu, 7 Sep 2017 10:03:16 +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=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham 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 D263C28600 for ; Thu, 7 Sep 2017 10:03:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754237AbdIGKDO (ORCPT ); Thu, 7 Sep 2017 06:03:14 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:37080 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753393AbdIGKCw (ORCPT ); Thu, 7 Sep 2017 06:02:52 -0400 Received: by mail-wm0-f66.google.com with SMTP id f4so1018137wmh.4; Thu, 07 Sep 2017 03:02:51 -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=mira05EVmNOZ2ADlNSWxASHoHzzNLrAHXHbtzbPHIVSf7mUIT/CtKhn4AW+JsgTfut JHIF3/2yHLecHoFxUcnQy/xJ2Ix/3kNfPyid1mT6OL9hH9oBp7DXIdsaIN42eTKwuIPn dmjiXEDElxm79YSTixGo1LdB95jp5a5hV3NuZxca764JDOlnFsLAYRfJ69yuFmOfNdQh /KEXunKztEKWolHLGq04S2SxtDKVbqZAyxFvnx46JdKjtWS9M1TCV1IoxFzgllAToYrL qwSBp8xLhPcIn8Yksjp7OqeX5qDX+nA5uglKxb9MX74qDqXmPP7e1XrGRfOwtywn785l O1hw== 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=K9fRsmwKl9uvvPpPlOFr86Vku6Nv+QuaGAQUHXWcPfriem3MV0CRKchjd/2N2lUZMa YAdo+s7w2kGdr6WdxwR0nt48rgsv7cfb9ccj4oNr6Qea4cn5kMrIlto3qkF0qebj42ue vWvOOzEiml5cbaa9/p0g3bDR/bCRGQEYpgHr7091U4KuCgnGChA0jkOEMDVEZCIHpa+y daVbydYwh6ml3zsu0b32uzM5LO2FUhpQZvB+6bhNNDEubs1+LLPK8AoQUF6doYOBV6e2 b+xmZFIV9tuCfzT3mvOXX1ZVDx0odIQaw75zBAaPdc33NSRj+x8evwojGoQV+O/Ehlm7 5s3Q== X-Gm-Message-State: AHPjjUhLXcZirl1WzMUS+1R8qd9DIesNtK7cug3QDeqZDdkczbANGDR6 DGRuk+LRfLI678gW X-Google-Smtp-Source: AOwi7QApRu6kB1sn3nf+JoPjg1THmd2fQxUGfQWjzLBEDB+mRnypQwXJLjT12VyfXQRulKxJp1zO/g== X-Received: by 10.28.234.136 with SMTP id g8mr81865wmi.76.1504778570340; Thu, 07 Sep 2017 03:02:50 -0700 (PDT) Received: from localhost.localdomain (bzq-166-168-31-246.red.bezeqint.net. [31.168.166.246]) by smtp.gmail.com with ESMTPSA id z108sm2190403wrc.49.2017.09.07.03.02.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 07 Sep 2017 03:02:49 -0700 (PDT) From: Amir Goldstein To: Eryu Guan Cc: Josef Bacik , fstests@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 2/8] replay-log: add validations for corrupt log entries Date: Thu, 7 Sep 2017 13:03:07 +0300 Message-Id: <1504778593-12071-3-git-send-email-amir73il@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504778593-12071-1-git-send-email-amir73il@gmail.com> References: <1504778593-12071-1-git-send-email-amir73il@gmail.com> Sender: fstests-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: fstests@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; }