Message ID | 20221014084837.1787196-4-hrkanabar@gmail.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4ac7:0:0:0:0:0 with SMTP id y7csp71487wrs; Fri, 14 Oct 2022 01:51:57 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6iobOwf663yG0dYt0/ON4RV8DwaRktjAfBrFksQoyQnfrcDzAY7xHcudYPM4EpsTJzHB4w X-Received: by 2002:a05:6402:5202:b0:45c:9525:9bc4 with SMTP id s2-20020a056402520200b0045c95259bc4mr3477039edd.380.1665737517169; Fri, 14 Oct 2022 01:51:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665737517; cv=none; d=google.com; s=arc-20160816; b=LATcUoKpZ4WvKIWlrwurlpSICIvrn4hX4XYD+LePwte4afQxhNY+x8fgqGHCicPYzY DTi4+SI0DTeivqW4p/wN9VIN7rfHwiHDBSxJYLgbckmkfnqlx+8glzVFf4/IkNWAtzFH LG+NzTyBOz2INb+wWdsFGB5zovvd/07L2Q9bJRg6n1x/olAnPQuyygjk2O+MDhqQeOrD DPyizG4ZXWH/riEy63BJ8YRLwfdyu340twtQJEAR2sIJ7JswW+OPC8EbxU+PUAHgPghg XgbNOQlkYJ+aQaBxUdeQH7Z8KydEf1Pd3FaCDMqkgAPu6z6Oi8sKjhDxPcwdSzppWbvo nVrQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=noZwzVYPpBsDl5CECnOrP5rsHRqU5K36GF5tioVqhvo=; b=CnUtPnvKvQyaieMLkK+pGUKmT9nvA8B0gzayQO5Nfd5jCCkTsZj+Y0LYKK0IcfrVLT 6opZEXBT7tJeytLja4f0k78mONToT1lj66WYVXoNSASupAPyTXGqsEMV8ZB/LO88o80V Z/5sYisL8ouX26kT26a/d0mzNndizrFu5KCd+l65YQ0NMzCB5kFPzxZpUxy/6BZp5cUl 1BwIcYfmXCrlcYd4HSmdpxSU5Cq01bBHHxhJhw+nUusgUvbi9LuTrS4sVnZnGer1z8Nf mDfVSNHn5KHSr1CRI3Jl1BDdR0EbcJfVhosBbmxV++bOp8hJtnk5YiMbaSk+zF00CRra Fm0A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=FQxuL83N; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bx26-20020a170906a1da00b0078d45e9d485si1482052ejb.709.2022.10.14.01.51.30; Fri, 14 Oct 2022 01:51:57 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=FQxuL83N; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229991AbiJNIuJ (ORCPT <rfc822;ouuuleilei@gmail.com> + 99 others); Fri, 14 Oct 2022 04:50:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34070 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229887AbiJNItw (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Fri, 14 Oct 2022 04:49:52 -0400 Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7C8F521E36; Fri, 14 Oct 2022 01:49:50 -0700 (PDT) Received: by mail-wm1-x32e.google.com with SMTP id r3-20020a05600c35c300b003b4b5f6c6bdso3069601wmq.2; Fri, 14 Oct 2022 01:49:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=noZwzVYPpBsDl5CECnOrP5rsHRqU5K36GF5tioVqhvo=; b=FQxuL83NlA1dTcPa+tFZaBKev/381N92shWjcokB6Cq01pDQV8v3dKmLzskweZmrg7 Jz6tAKO28qyNZhcKa1omEDpp9WjDAaZzKcErysdgfT7V0um+TyLLNk2Cij8EO/EsRY7j mM4PW1pXSuwF/LnXS5kzwEDyOA+AX2w5cE1DhAa9FuWqFFyXvj/NZ+KCCIthXLghAk0u a86+6OK4+3IB+C4bjSyDRdPIS9Ojxhjig1vaZtK+KEGWoBJunSCvCvMdY3KFEsTnmGGH vhkRbzjwDO4lnOX6LHYeQne4mhhiyroqBB3oVZA+u+phCefTTmPtrCeo3CV7uh6afgQ3 Zvrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=noZwzVYPpBsDl5CECnOrP5rsHRqU5K36GF5tioVqhvo=; b=NrYTcHyfyF2rCxRI0gZ9j8/v593JThtMk8Wb75cFABf3iEp2qMMRgHa6xnQhYpgBok 9B81ZfW1GsL4olM2FIbse3pKdtDJytbjmXrWQWSkpXxCUdV/5oXYRux4t4tFIFaJWfQU ek68m1cWTYDNEjPi+3HYab98s5UFxWdBU9vLrtcMRlpWc8MZOEaB+GX1G+U3x4in6w// vSPQuIR/eQ//NSgJ/BwuLspKmolFxYPEpt0nkIHlfx6XVbxKN7o6Mcm4abqZop4IoycZ NNS1lgWyUJG+MkNIzfSDAuuNtn6OFaoQaJ33fNSq1E28mkX1CU7EE2d4P3+N/TduJ8tj YkdA== X-Gm-Message-State: ACrzQf296Zl8SR5ElvHDEUevggqMsiFhOun/La7+sksb3MNAVR/y99oA K/0vyj5pbr6ta5Yo+f1kmwo= X-Received: by 2002:a05:600c:288:b0:3c6:c44a:1d30 with SMTP id 8-20020a05600c028800b003c6c44a1d30mr9545255wmk.46.1665737388927; Fri, 14 Oct 2022 01:49:48 -0700 (PDT) Received: from hrutvik.c.googlers.com.com (120.142.205.35.bc.googleusercontent.com. [35.205.142.120]) by smtp.gmail.com with ESMTPSA id 123-20020a1c1981000000b003c6c4639ac6sm1547372wmz.34.2022.10.14.01.49.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 01:49:48 -0700 (PDT) From: Hrutvik Kanabar <hrkanabar@gmail.com> To: Hrutvik Kanabar <hrutvik@google.com> Cc: Marco Elver <elver@google.com>, Aleksandr Nogikh <nogikh@google.com>, kasan-dev@googlegroups.com, Alexander Viro <viro@zeniv.linux.org.uk>, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Theodore Ts'o <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, linux-ext4@vger.kernel.org, Chris Mason <clm@fb.com>, Josef Bacik <josef@toxicpanda.com>, David Sterba <dsterba@suse.com>, linux-btrfs@vger.kernel.org, Jaegeuk Kim <jaegeuk@kernel.org>, Chao Yu <chao@kernel.org>, linux-f2fs-devel@lists.sourceforge.net, "Darrick J . Wong" <djwong@kernel.org>, linux-xfs@vger.kernel.org, Namjae Jeon <linkinjeon@kernel.org>, Sungjong Seo <sj1557.seo@samsung.com>, Anton Altaparmakov <anton@tuxera.com>, linux-ntfs-dev@lists.sourceforge.net Subject: [PATCH RFC 3/7] fs/btrfs: support `DISABLE_FS_CSUM_VERIFICATION` config option Date: Fri, 14 Oct 2022 08:48:33 +0000 Message-Id: <20221014084837.1787196-4-hrkanabar@gmail.com> X-Mailer: git-send-email 2.38.0.413.g74048e4d9e-goog In-Reply-To: <20221014084837.1787196-1-hrkanabar@gmail.com> References: <20221014084837.1787196-1-hrkanabar@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1746652383152264792?= X-GMAIL-MSGID: =?utf-8?q?1746652383152264792?= |
Series |
fs: Debug config option to disable filesystem checksum verification for fuzzing
|
|
Commit Message
Hrutvik Kanabar
Oct. 14, 2022, 8:48 a.m. UTC
From: Hrutvik Kanabar <hrutvik@google.com> When `DISABLE_FS_CSUM_VERIFICATION` is enabled, bypass checksum verification. Signed-off-by: Hrutvik Kanabar <hrutvik@google.com> --- fs/btrfs/check-integrity.c | 3 ++- fs/btrfs/disk-io.c | 6 ++++-- fs/btrfs/free-space-cache.c | 3 ++- fs/btrfs/inode.c | 3 ++- fs/btrfs/scrub.c | 9 ++++++--- 5 files changed, 16 insertions(+), 8 deletions(-)
Comments
On 2022/10/14 16:48, Hrutvik Kanabar wrote: > From: Hrutvik Kanabar <hrutvik@google.com> > > When `DISABLE_FS_CSUM_VERIFICATION` is enabled, bypass checksum > verification. > > Signed-off-by: Hrutvik Kanabar <hrutvik@google.com> I always want more fuzz for btrfs, so overall this is pretty good. But there are some comments related to free space cache part. Despite the details, I'm wondering would it be possible for your fuzzing tool to do a better job at user space? Other than relying on loosen checks from kernel? For example, implement a (mostly) read-only tool to do the following workload: - Open the fs Including understand the checksum algo, how to re-generate the csum. - Read out the used space bitmap In btrfs case, it's going to read the extent tree, process the backrefs items. - Choose the victim sectors and corrupt them Obviously, vitims should be choosen from above used space bitmap. - Re-calculate the checksum for above corrupted sectors For btrfs, if it's a corrupted metadata, re-calculate the checksum. By this, we can avoid such change to kernel, and still get a much better coverage. If you need some help on such user space tool, I'm pretty happy to provide help. > --- > fs/btrfs/check-integrity.c | 3 ++- > fs/btrfs/disk-io.c | 6 ++++-- > fs/btrfs/free-space-cache.c | 3 ++- > fs/btrfs/inode.c | 3 ++- > fs/btrfs/scrub.c | 9 ++++++--- > 5 files changed, 16 insertions(+), 8 deletions(-) > > diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c > index 98c6e5feab19..eab82593a325 100644 > --- a/fs/btrfs/check-integrity.c > +++ b/fs/btrfs/check-integrity.c > @@ -1671,7 +1671,8 @@ static noinline_for_stack int btrfsic_test_for_metadata( > crypto_shash_update(shash, data, sublen); > } > crypto_shash_final(shash, csum); > - if (memcmp(csum, h->csum, fs_info->csum_size)) > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > + memcmp(csum, h->csum, fs_info->csum_size)) > return 1; > > return 0; /* is metadata */ > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index a2da9313c694..7cd909d44b24 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -184,7 +184,8 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, > crypto_shash_digest(shash, raw_disk_sb + BTRFS_CSUM_SIZE, > BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, result); > > - if (memcmp(disk_sb->csum, result, fs_info->csum_size)) > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > + memcmp(disk_sb->csum, result, fs_info->csum_size)) > return 1; > > return 0; > @@ -494,7 +495,8 @@ static int validate_extent_buffer(struct extent_buffer *eb) > header_csum = page_address(eb->pages[0]) + > get_eb_offset_in_page(eb, offsetof(struct btrfs_header, csum)); > > - if (memcmp(result, header_csum, csum_size) != 0) { > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > + memcmp(result, header_csum, csum_size) != 0) { I believe this is the main thing fuzzing would take advantage of. It would be much better if this is the only override... > btrfs_warn_rl(fs_info, > "checksum verify failed on logical %llu mirror %u wanted " CSUM_FMT " found " CSUM_FMT " level %d", > eb->start, eb->read_mirror, > diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c > index f4023651dd68..203c8a9076a6 100644 > --- a/fs/btrfs/free-space-cache.c > +++ b/fs/btrfs/free-space-cache.c > @@ -574,7 +574,8 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) > io_ctl_map_page(io_ctl, 0); > crc = btrfs_crc32c(crc, io_ctl->orig + offset, PAGE_SIZE - offset); > btrfs_crc32c_final(crc, (u8 *)&crc); > - if (val != crc) { > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > + val != crc) { I'm already seeing this to cause problems, especially for btrfs. Btrfs has a very strong dependency on free space tracing, as all of our metadata (and data by default) relies on COW to keep the fs consistent. I tried a lot of different methods in the past to make sure we won't write into previously used space, but it's causing a lot of performance impact. Unlike tree-checker, we can not easily got a centerlized space to handle all the free space cross-check thing (thus it's only verified by things like btrfs-check). Furthermore, even if you skip this override, with latest default free-space-tree feature, free space info is stored in regular btrfs metadata (tree blocks), with regular metadata checksum protection. Thus I'm pretty sure we will have tons of reports on this, and unfortunately we can only go whac-a-mole way for it. > btrfs_err_rl(io_ctl->fs_info, > "csum mismatch on free space cache"); > io_ctl_unmap_page(io_ctl); > diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c > index b0807c59e321..1a49d897b5c1 100644 > --- a/fs/btrfs/inode.c > +++ b/fs/btrfs/inode.c > @@ -3434,7 +3434,8 @@ int btrfs_check_sector_csum(struct btrfs_fs_info *fs_info, struct page *page, > crypto_shash_digest(shash, kaddr, fs_info->sectorsize, csum); > kunmap_local(kaddr); > > - if (memcmp(csum, csum_expected, fs_info->csum_size)) > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > + memcmp(csum, csum_expected, fs_info->csum_size)) This skips data csum check, I don't know how valueable it is, but this should be harmless mostly. If we got reports related to this, it would be a nice surprise. > return -EIO; > return 0; > } > diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c > index f260c53829e5..a7607b492f47 100644 > --- a/fs/btrfs/scrub.c > +++ b/fs/btrfs/scrub.c > @@ -1997,7 +1997,8 @@ static int scrub_checksum_data(struct scrub_block *sblock) > > crypto_shash_digest(shash, kaddr, fs_info->sectorsize, csum); > > - if (memcmp(csum, sector->csum, fs_info->csum_size)) > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > + memcmp(csum, sector->csum, fs_info->csum_size)) Same as data csum verification overide. Not necessary/useful but good to have. > sblock->checksum_error = 1; > return sblock->checksum_error; > } > @@ -2062,7 +2063,8 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) > } > > crypto_shash_final(shash, calculated_csum); > - if (memcmp(calculated_csum, on_disk_csum, sctx->fs_info->csum_size)) > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > + memcmp(calculated_csum, on_disk_csum, sctx->fs_info->csum_size)) This is much less valueable, since it's only affecting scrub, and scrub itself is already very little checking the content of metadata. Thanks, Qu > sblock->checksum_error = 1; > > return sblock->header_error || sblock->checksum_error; > @@ -2099,7 +2101,8 @@ static int scrub_checksum_super(struct scrub_block *sblock) > crypto_shash_digest(shash, kaddr + BTRFS_CSUM_SIZE, > BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, calculated_csum); > > - if (memcmp(calculated_csum, s->csum, sctx->fs_info->csum_size)) > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > + memcmp(calculated_csum, s->csum, sctx->fs_info->csum_size)) > ++fail_cor; > > return fail_cor + fail_gen;
On Fri, 14 Oct 2022 at 12:24, 'Qu Wenruo' via kasan-dev <kasan-dev@googlegroups.com> wrote: > > On 2022/10/14 16:48, Hrutvik Kanabar wrote: > > From: Hrutvik Kanabar <hrutvik@google.com> > > > > When `DISABLE_FS_CSUM_VERIFICATION` is enabled, bypass checksum > > verification. > > > > Signed-off-by: Hrutvik Kanabar <hrutvik@google.com> > > I always want more fuzz for btrfs, so overall this is pretty good. > > But there are some comments related to free space cache part. > > Despite the details, I'm wondering would it be possible for your fuzzing > tool to do a better job at user space? Other than relying on loosen > checks from kernel? > > For example, implement a (mostly) read-only tool to do the following > workload: > > - Open the fs > Including understand the checksum algo, how to re-generate the csum. > > - Read out the used space bitmap > In btrfs case, it's going to read the extent tree, process the > backrefs items. > > - Choose the victim sectors and corrupt them > Obviously, vitims should be choosen from above used space bitmap. > > - Re-calculate the checksum for above corrupted sectors > For btrfs, if it's a corrupted metadata, re-calculate the checksum. > > By this, we can avoid such change to kernel, and still get a much better > coverage. > > If you need some help on such user space tool, I'm pretty happy to > provide help. > > > --- > > fs/btrfs/check-integrity.c | 3 ++- > > fs/btrfs/disk-io.c | 6 ++++-- > > fs/btrfs/free-space-cache.c | 3 ++- > > fs/btrfs/inode.c | 3 ++- > > fs/btrfs/scrub.c | 9 ++++++--- > > 5 files changed, 16 insertions(+), 8 deletions(-) > > > > diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c > > index 98c6e5feab19..eab82593a325 100644 > > --- a/fs/btrfs/check-integrity.c > > +++ b/fs/btrfs/check-integrity.c > > @@ -1671,7 +1671,8 @@ static noinline_for_stack int btrfsic_test_for_metadata( > > crypto_shash_update(shash, data, sublen); > > } > > crypto_shash_final(shash, csum); > > - if (memcmp(csum, h->csum, fs_info->csum_size)) > > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > > + memcmp(csum, h->csum, fs_info->csum_size)) > > return 1; > > > > return 0; /* is metadata */ > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > > index a2da9313c694..7cd909d44b24 100644 > > --- a/fs/btrfs/disk-io.c > > +++ b/fs/btrfs/disk-io.c > > @@ -184,7 +184,8 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, > > crypto_shash_digest(shash, raw_disk_sb + BTRFS_CSUM_SIZE, > > BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, result); > > > > - if (memcmp(disk_sb->csum, result, fs_info->csum_size)) > > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > > + memcmp(disk_sb->csum, result, fs_info->csum_size)) > > return 1; > > > > return 0; > > @@ -494,7 +495,8 @@ static int validate_extent_buffer(struct extent_buffer *eb) > > header_csum = page_address(eb->pages[0]) + > > get_eb_offset_in_page(eb, offsetof(struct btrfs_header, csum)); > > > > - if (memcmp(result, header_csum, csum_size) != 0) { > > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > > + memcmp(result, header_csum, csum_size) != 0) { > > I believe this is the main thing fuzzing would take advantage of. > > It would be much better if this is the only override... > > > btrfs_warn_rl(fs_info, > > "checksum verify failed on logical %llu mirror %u wanted " CSUM_FMT " found " CSUM_FMT " level %d", > > eb->start, eb->read_mirror, > > diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c > > index f4023651dd68..203c8a9076a6 100644 > > --- a/fs/btrfs/free-space-cache.c > > +++ b/fs/btrfs/free-space-cache.c > > @@ -574,7 +574,8 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) > > io_ctl_map_page(io_ctl, 0); > > crc = btrfs_crc32c(crc, io_ctl->orig + offset, PAGE_SIZE - offset); > > btrfs_crc32c_final(crc, (u8 *)&crc); > > - if (val != crc) { > > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > > + val != crc) { > > I'm already seeing this to cause problems, especially for btrfs. > > Btrfs has a very strong dependency on free space tracing, as all of our > metadata (and data by default) relies on COW to keep the fs consistent. > > I tried a lot of different methods in the past to make sure we won't > write into previously used space, but it's causing a lot of performance > impact. > > Unlike tree-checker, we can not easily got a centerlized space to handle > all the free space cross-check thing (thus it's only verified by things > like btrfs-check). > > Furthermore, even if you skip this override, with latest default > free-space-tree feature, free space info is stored in regular btrfs > metadata (tree blocks), with regular metadata checksum protection. > > Thus I'm pretty sure we will have tons of reports on this, and > unfortunately we can only go whac-a-mole way for it. Hi Qu, I don't fully understand what you mean. Could you please elaborate? Do you mean that btrfs uses this checksum check to detect blocks that were written to w/o updating the checksum? > > btrfs_err_rl(io_ctl->fs_info, > > "csum mismatch on free space cache"); > > io_ctl_unmap_page(io_ctl); > > diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c > > index b0807c59e321..1a49d897b5c1 100644 > > --- a/fs/btrfs/inode.c > > +++ b/fs/btrfs/inode.c > > @@ -3434,7 +3434,8 @@ int btrfs_check_sector_csum(struct btrfs_fs_info *fs_info, struct page *page, > > crypto_shash_digest(shash, kaddr, fs_info->sectorsize, csum); > > kunmap_local(kaddr); > > > > - if (memcmp(csum, csum_expected, fs_info->csum_size)) > > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > > + memcmp(csum, csum_expected, fs_info->csum_size)) > > This skips data csum check, I don't know how valueable it is, but this > should be harmless mostly. > > If we got reports related to this, it would be a nice surprise. > > > return -EIO; > > return 0; > > } > > diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c > > index f260c53829e5..a7607b492f47 100644 > > --- a/fs/btrfs/scrub.c > > +++ b/fs/btrfs/scrub.c > > @@ -1997,7 +1997,8 @@ static int scrub_checksum_data(struct scrub_block *sblock) > > > > crypto_shash_digest(shash, kaddr, fs_info->sectorsize, csum); > > > > - if (memcmp(csum, sector->csum, fs_info->csum_size)) > > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > > + memcmp(csum, sector->csum, fs_info->csum_size)) > > Same as data csum verification overide. > Not necessary/useful but good to have. > > > sblock->checksum_error = 1; > > return sblock->checksum_error; > > } > > @@ -2062,7 +2063,8 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) > > } > > > > crypto_shash_final(shash, calculated_csum); > > - if (memcmp(calculated_csum, on_disk_csum, sctx->fs_info->csum_size)) > > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > > + memcmp(calculated_csum, on_disk_csum, sctx->fs_info->csum_size)) > > This is much less valueable, since it's only affecting scrub, and scrub > itself is already very little checking the content of metadata. Could you please elaborate here as well? This is less valuable from what perspective? The data loaded from disk can have any combination of (correct/incorrect metadata) x (correct/incorrect checksum). Correctness of metadata and checksum are effectively orthogonal, right? > Thanks, > Qu > > > sblock->checksum_error = 1; > > > > return sblock->header_error || sblock->checksum_error; > > @@ -2099,7 +2101,8 @@ static int scrub_checksum_super(struct scrub_block *sblock) > > crypto_shash_digest(shash, kaddr + BTRFS_CSUM_SIZE, > > BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, calculated_csum); > > > > - if (memcmp(calculated_csum, s->csum, sctx->fs_info->csum_size)) > > + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && > > + memcmp(calculated_csum, s->csum, sctx->fs_info->csum_size)) > > ++fail_cor; > > > > return fail_cor + fail_gen;
On 2022/10/17 16:43, Dmitry Vyukov wrote: > On Fri, 14 Oct 2022 at 12:24, 'Qu Wenruo' via kasan-dev > <kasan-dev@googlegroups.com> wrote: >> >> On 2022/10/14 16:48, Hrutvik Kanabar wrote: >>> From: Hrutvik Kanabar <hrutvik@google.com> >>> >>> When `DISABLE_FS_CSUM_VERIFICATION` is enabled, bypass checksum >>> verification. >>> >>> Signed-off-by: Hrutvik Kanabar <hrutvik@google.com> >> >> I always want more fuzz for btrfs, so overall this is pretty good. >> >> But there are some comments related to free space cache part. >> >> Despite the details, I'm wondering would it be possible for your fuzzing >> tool to do a better job at user space? Other than relying on loosen >> checks from kernel? >> >> For example, implement a (mostly) read-only tool to do the following >> workload: >> >> - Open the fs >> Including understand the checksum algo, how to re-generate the csum. >> >> - Read out the used space bitmap >> In btrfs case, it's going to read the extent tree, process the >> backrefs items. >> >> - Choose the victim sectors and corrupt them >> Obviously, vitims should be choosen from above used space bitmap. >> >> - Re-calculate the checksum for above corrupted sectors >> For btrfs, if it's a corrupted metadata, re-calculate the checksum. >> >> By this, we can avoid such change to kernel, and still get a much better >> coverage. >> >> If you need some help on such user space tool, I'm pretty happy to >> provide help. >> >>> --- >>> fs/btrfs/check-integrity.c | 3 ++- >>> fs/btrfs/disk-io.c | 6 ++++-- >>> fs/btrfs/free-space-cache.c | 3 ++- >>> fs/btrfs/inode.c | 3 ++- >>> fs/btrfs/scrub.c | 9 ++++++--- >>> 5 files changed, 16 insertions(+), 8 deletions(-) >>> >>> diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c >>> index 98c6e5feab19..eab82593a325 100644 >>> --- a/fs/btrfs/check-integrity.c >>> +++ b/fs/btrfs/check-integrity.c >>> @@ -1671,7 +1671,8 @@ static noinline_for_stack int btrfsic_test_for_metadata( >>> crypto_shash_update(shash, data, sublen); >>> } >>> crypto_shash_final(shash, csum); >>> - if (memcmp(csum, h->csum, fs_info->csum_size)) >>> + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && >>> + memcmp(csum, h->csum, fs_info->csum_size)) >>> return 1; >>> >>> return 0; /* is metadata */ >>> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c >>> index a2da9313c694..7cd909d44b24 100644 >>> --- a/fs/btrfs/disk-io.c >>> +++ b/fs/btrfs/disk-io.c >>> @@ -184,7 +184,8 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, >>> crypto_shash_digest(shash, raw_disk_sb + BTRFS_CSUM_SIZE, >>> BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, result); >>> >>> - if (memcmp(disk_sb->csum, result, fs_info->csum_size)) >>> + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && >>> + memcmp(disk_sb->csum, result, fs_info->csum_size)) >>> return 1; >>> >>> return 0; >>> @@ -494,7 +495,8 @@ static int validate_extent_buffer(struct extent_buffer *eb) >>> header_csum = page_address(eb->pages[0]) + >>> get_eb_offset_in_page(eb, offsetof(struct btrfs_header, csum)); >>> >>> - if (memcmp(result, header_csum, csum_size) != 0) { >>> + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && >>> + memcmp(result, header_csum, csum_size) != 0) { >> >> I believe this is the main thing fuzzing would take advantage of. >> >> It would be much better if this is the only override... >> >>> btrfs_warn_rl(fs_info, >>> "checksum verify failed on logical %llu mirror %u wanted " CSUM_FMT " found " CSUM_FMT " level %d", >>> eb->start, eb->read_mirror, >>> diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c >>> index f4023651dd68..203c8a9076a6 100644 >>> --- a/fs/btrfs/free-space-cache.c >>> +++ b/fs/btrfs/free-space-cache.c >>> @@ -574,7 +574,8 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) >>> io_ctl_map_page(io_ctl, 0); >>> crc = btrfs_crc32c(crc, io_ctl->orig + offset, PAGE_SIZE - offset); >>> btrfs_crc32c_final(crc, (u8 *)&crc); >>> - if (val != crc) { >>> + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && >>> + val != crc) { >> >> I'm already seeing this to cause problems, especially for btrfs. >> >> Btrfs has a very strong dependency on free space tracing, as all of our >> metadata (and data by default) relies on COW to keep the fs consistent. >> >> I tried a lot of different methods in the past to make sure we won't >> write into previously used space, but it's causing a lot of performance >> impact. >> >> Unlike tree-checker, we can not easily got a centerlized space to handle >> all the free space cross-check thing (thus it's only verified by things >> like btrfs-check). >> >> Furthermore, even if you skip this override, with latest default >> free-space-tree feature, free space info is stored in regular btrfs >> metadata (tree blocks), with regular metadata checksum protection. >> >> Thus I'm pretty sure we will have tons of reports on this, and >> unfortunately we can only go whac-a-mole way for it. > > Hi Qu, > > I don't fully understand what you mean. Could you please elaborate? > > Do you mean that btrfs uses this checksum check to detect blocks that > were written to w/o updating the checksum? I mean, btrfs uses this particular checksum for its (free) space cache, and currently btrfs just trust the space cache completely to do COW. This means, if we ignore the checksum for free space cache, we can easily screw up the COW, e.g. allocate a range for the new metadata to be written into. But the truth is, that range is still being utilized by some other metadata. Thus would completely break COW. This is indeed a problem for btrfs, but it is not that easiy to fix, since this involves cross-check 3 different data (free space cache for free space, extent tree for used space, and the metadata itself). Thus my concern is, disabling free space cache csum can easily lead to various crashes, all related to broken COW, and we don't have a good enough way to validate the result. > > > > >>> btrfs_err_rl(io_ctl->fs_info, >>> "csum mismatch on free space cache"); >>> io_ctl_unmap_page(io_ctl); >>> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c >>> index b0807c59e321..1a49d897b5c1 100644 >>> --- a/fs/btrfs/inode.c >>> +++ b/fs/btrfs/inode.c >>> @@ -3434,7 +3434,8 @@ int btrfs_check_sector_csum(struct btrfs_fs_info *fs_info, struct page *page, >>> crypto_shash_digest(shash, kaddr, fs_info->sectorsize, csum); >>> kunmap_local(kaddr); >>> >>> - if (memcmp(csum, csum_expected, fs_info->csum_size)) >>> + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && >>> + memcmp(csum, csum_expected, fs_info->csum_size)) >> >> This skips data csum check, I don't know how valueable it is, but this >> should be harmless mostly. >> >> If we got reports related to this, it would be a nice surprise. >> >>> return -EIO; >>> return 0; >>> } >>> diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c >>> index f260c53829e5..a7607b492f47 100644 >>> --- a/fs/btrfs/scrub.c >>> +++ b/fs/btrfs/scrub.c >>> @@ -1997,7 +1997,8 @@ static int scrub_checksum_data(struct scrub_block *sblock) >>> >>> crypto_shash_digest(shash, kaddr, fs_info->sectorsize, csum); >>> >>> - if (memcmp(csum, sector->csum, fs_info->csum_size)) >>> + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && >>> + memcmp(csum, sector->csum, fs_info->csum_size)) >> >> Same as data csum verification overide. >> Not necessary/useful but good to have. >> >>> sblock->checksum_error = 1; >>> return sblock->checksum_error; >>> } >>> @@ -2062,7 +2063,8 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) >>> } >>> >>> crypto_shash_final(shash, calculated_csum); >>> - if (memcmp(calculated_csum, on_disk_csum, sctx->fs_info->csum_size)) >>> + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && >>> + memcmp(calculated_csum, on_disk_csum, sctx->fs_info->csum_size)) >> >> This is much less valueable, since it's only affecting scrub, and scrub >> itself is already very little checking the content of metadata. > > Could you please elaborate here as well? These checksum verification is only done in the scrub path (just as the file name indicates). > This is less valuable from what perspective? It's just much harder to trigger, regular filesystem operations won't go into scrub path. Unless there is also a full ioctl fuzzing tests, after corrupting the image. > The data loaded from disk can have any combination of > (correct/incorrect metadata) x (correct/incorrect checksum). > Correctness of metadata and checksum are effectively orthogonal, Oh, I almost forgot another problem with the compile time csum verification skip. If we skip csum check completely, just like the patch, it may cause less path coverage (this is very btrfs specific) The problem is, btrfs has some repair path (scrub, and read-time), which requires to have a checksum mismatch (and a good copy with good checksum). Thus if we ignore csum completely, the repair path will never be covered (as we treat them all as csum match). Thanks, Qu > right? > > > >> Thanks, >> Qu >> >>> sblock->checksum_error = 1; >>> >>> return sblock->header_error || sblock->checksum_error; >>> @@ -2099,7 +2101,8 @@ static int scrub_checksum_super(struct scrub_block *sblock) >>> crypto_shash_digest(shash, kaddr + BTRFS_CSUM_SIZE, >>> BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, calculated_csum); >>> >>> - if (memcmp(calculated_csum, s->csum, sctx->fs_info->csum_size)) >>> + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && >>> + memcmp(calculated_csum, s->csum, sctx->fs_info->csum_size)) >>> ++fail_cor; >>> >>> return fail_cor + fail_gen;
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 98c6e5feab19..eab82593a325 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -1671,7 +1671,8 @@ static noinline_for_stack int btrfsic_test_for_metadata( crypto_shash_update(shash, data, sublen); } crypto_shash_final(shash, csum); - if (memcmp(csum, h->csum, fs_info->csum_size)) + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && + memcmp(csum, h->csum, fs_info->csum_size)) return 1; return 0; /* is metadata */ diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a2da9313c694..7cd909d44b24 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -184,7 +184,8 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, crypto_shash_digest(shash, raw_disk_sb + BTRFS_CSUM_SIZE, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, result); - if (memcmp(disk_sb->csum, result, fs_info->csum_size)) + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && + memcmp(disk_sb->csum, result, fs_info->csum_size)) return 1; return 0; @@ -494,7 +495,8 @@ static int validate_extent_buffer(struct extent_buffer *eb) header_csum = page_address(eb->pages[0]) + get_eb_offset_in_page(eb, offsetof(struct btrfs_header, csum)); - if (memcmp(result, header_csum, csum_size) != 0) { + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && + memcmp(result, header_csum, csum_size) != 0) { btrfs_warn_rl(fs_info, "checksum verify failed on logical %llu mirror %u wanted " CSUM_FMT " found " CSUM_FMT " level %d", eb->start, eb->read_mirror, diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index f4023651dd68..203c8a9076a6 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -574,7 +574,8 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) io_ctl_map_page(io_ctl, 0); crc = btrfs_crc32c(crc, io_ctl->orig + offset, PAGE_SIZE - offset); btrfs_crc32c_final(crc, (u8 *)&crc); - if (val != crc) { + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && + val != crc) { btrfs_err_rl(io_ctl->fs_info, "csum mismatch on free space cache"); io_ctl_unmap_page(io_ctl); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index b0807c59e321..1a49d897b5c1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3434,7 +3434,8 @@ int btrfs_check_sector_csum(struct btrfs_fs_info *fs_info, struct page *page, crypto_shash_digest(shash, kaddr, fs_info->sectorsize, csum); kunmap_local(kaddr); - if (memcmp(csum, csum_expected, fs_info->csum_size)) + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && + memcmp(csum, csum_expected, fs_info->csum_size)) return -EIO; return 0; } diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index f260c53829e5..a7607b492f47 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -1997,7 +1997,8 @@ static int scrub_checksum_data(struct scrub_block *sblock) crypto_shash_digest(shash, kaddr, fs_info->sectorsize, csum); - if (memcmp(csum, sector->csum, fs_info->csum_size)) + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && + memcmp(csum, sector->csum, fs_info->csum_size)) sblock->checksum_error = 1; return sblock->checksum_error; } @@ -2062,7 +2063,8 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) } crypto_shash_final(shash, calculated_csum); - if (memcmp(calculated_csum, on_disk_csum, sctx->fs_info->csum_size)) + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && + memcmp(calculated_csum, on_disk_csum, sctx->fs_info->csum_size)) sblock->checksum_error = 1; return sblock->header_error || sblock->checksum_error; @@ -2099,7 +2101,8 @@ static int scrub_checksum_super(struct scrub_block *sblock) crypto_shash_digest(shash, kaddr + BTRFS_CSUM_SIZE, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, calculated_csum); - if (memcmp(calculated_csum, s->csum, sctx->fs_info->csum_size)) + if (!IS_ENABLED(CONFIG_DISABLE_FS_CSUM_VERIFICATION) && + memcmp(calculated_csum, s->csum, sctx->fs_info->csum_size)) ++fail_cor; return fail_cor + fail_gen;