From patchwork Tue Mar 15 22:15:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12781880 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5E2DEC4332F for ; Tue, 15 Mar 2022 22:16:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351357AbiCOWRS (ORCPT ); Tue, 15 Mar 2022 18:17:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46748 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350324AbiCOWRS (ORCPT ); Tue, 15 Mar 2022 18:17:18 -0400 Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81CCC55BD1; Tue, 15 Mar 2022 15:16:05 -0700 (PDT) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.nyi.internal (Postfix) with ESMTP id DF4E65C0207; Tue, 15 Mar 2022 18:16:04 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Tue, 15 Mar 2022 18:16:04 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bur.io; h=cc :content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm1; bh=SEC0H9OItPspyLXYSaNaZvwbL/b0zp vHbge9eZDq0b8=; b=wQWtjBHQi4w4F6P5/3m5foT7kaX9iZkEaEkX7OaeEf3Om9 3M/XTQJuG/DPNwAabJSjp5gqBYHyTYV8YT4Z+j38lIZMvCiORZIB3u3iyZxbINrd Z2fqIUORW+QtkDe7P6MSu8lttOnVvwUhQBS9S/lFTe5UghxJLNz0kZ7ZiMV5vIEv nZVi6YTnx40O7tHl/iETINXHEs/eBPPWt1BjqAjaqqGqdEJwELjAI9B5/4dV4IGL BN2ZGVKtEwSd2hu51mFnRPd6NEyyaMQy6bVIM3+JmVyneQhWfZ9R1iLMylLpwD/X 6jtrTsrexdDRPZIRY1NDksUvs9X3HO2q19sucrQg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; bh=SEC0H9 OItPspyLXYSaNaZvwbL/b0zpvHbge9eZDq0b8=; b=Bx5VfbtrC0idq+ptEz459M 897Avbbh4XlmKugfSiz48oTDwqwSfNP903lS98tHAgICFoQVcjyFIGCQTRJHYgMg dtSZxzKNJi41y+njDmMIJ9YRlDjeNYygkhMlM8x1/PC0PVoSCghA5k2xQqhViEC9 b8N7FkB58MXG0hyekfSOfufGtNA+RDZEVd+Arg3Xl/pouraM3ofbLQZp6Cf/svKa 6oG2gt2qarhQ/pK81tOFC43kQuIxg3FDJE/XCfxeNvt6W2Tq1+JinTmxW1tKafjC FStwMpxLzaetKj/W/qamTwouO+80YHNM9NH2CPvmOUqorCm3Z4QJPcfvWdv2+dag == X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvvddrudeftddgudehjecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeeuohhrihhsuceuuhhrkhhovhcuoegsohhrihhssegsuhhr rdhioheqnecuggftrfgrthhtvghrnhepieeuffeuvdeiueejhfehiefgkeevudejjeejff evvdehtddufeeihfekgeeuheelnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghm pehmrghilhhfrhhomhepsghorhhishessghurhdrihho X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 15 Mar 2022 18:16:04 -0400 (EDT) From: Boris Burkov To: fstests@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH v7 1/5] verity: require corruption functionality Date: Tue, 15 Mar 2022 15:15:57 -0700 Message-Id: <73ea99df928e64baf172fa38a0648fb21494e864.1647382272.git.boris@bur.io> X-Mailer: git-send-email 2.35.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org Corrupting ext4 and f2fs relies on xfs_io fiemap. Btrfs corruption testing will rely on a btrfs specific corruption utility. Add the ability to require corruption functionality to make this properly modular. To start, just check for fiemap, as that is needed universally for _fsv_scratch_corrupt_bytes. Signed-off-by: Boris Burkov Reviewed-by: Eric Biggers --- common/verity | 6 ++++++ tests/generic/574 | 1 + tests/generic/576 | 1 + 3 files changed, 8 insertions(+) diff --git a/common/verity b/common/verity index 38eea157..1afe4a82 100644 --- a/common/verity +++ b/common/verity @@ -141,6 +141,12 @@ _require_fsverity_dump_metadata() _fail "Unexpected output from 'fsverity dump_metadata': $(<"$tmpfile")" } +# Check for userspace tools needed to corrupt verity data or metadata. +_require_fsverity_corruption() +{ + _require_xfs_io_command "fiemap" +} + _scratch_mkfs_verity() { case $FSTYP in diff --git a/tests/generic/574 b/tests/generic/574 index 882baa21..17fdea52 100755 --- a/tests/generic/574 +++ b/tests/generic/574 @@ -28,6 +28,7 @@ _cleanup() _supported_fs generic _require_scratch_verity _disable_fsverity_signatures +_require_fsverity_corruption _scratch_mkfs_verity &>> $seqres.full _scratch_mount diff --git a/tests/generic/576 b/tests/generic/576 index 82fbdd71..d3e0a2d6 100755 --- a/tests/generic/576 +++ b/tests/generic/576 @@ -28,6 +28,7 @@ _supported_fs generic _require_scratch_verity _require_scratch_encryption _require_command "$KEYCTL_PROG" keyctl +_require_fsverity_corruption _disable_fsverity_signatures _scratch_mkfs_encrypted_verity &>> $seqres.full From patchwork Tue Mar 15 22:15:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12781881 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 91C6FC4332F for ; Tue, 15 Mar 2022 22:16:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352135AbiCOWRV (ORCPT ); Tue, 15 Mar 2022 18:17:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46810 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348522AbiCOWRU (ORCPT ); Tue, 15 Mar 2022 18:17:20 -0400 Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 212CA55BD1; Tue, 15 Mar 2022 15:16:07 -0700 (PDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 879CC5C01C1; Tue, 15 Mar 2022 18:16:06 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Tue, 15 Mar 2022 18:16:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bur.io; h=cc :content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm1; bh=8cyZZzg7Z6V2WSzkXXqiOwNHzjU+D5 5FACYRauf5FiI=; b=Hh9aoDOZp3CcbIgW2Bm7FA/fywEsdEFuczgN9JgVNOwWit WSWt0RKBBCmnKdmjLwucyaVxnHl7UQewQ7SfFnCOhYSg/QtgiC7RNGXbmFkt02lF cfZ1xZj8RIBdAeClCnIchtINX5vGZthqt7E8OP8bygkRAxqbaA766kgEd+sXGAmC 8pXFjNorsQwdKNQZqVQef0JwxaBABbfbYCHXxo0mQWb6E5GhQ7/ylszGLTo1zAVy MZ989n2Qxg13q+qPwLbsWlwFun685cvy9GOIicyslvCbSCJ9nPwIeS496E0IUM8u oj8FcOmcx0Td8zPlyFnt++0hfybUV34wUk40xurg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; bh=8cyZZz g7Z6V2WSzkXXqiOwNHzjU+D55FACYRauf5FiI=; b=O4FXNtTapAPNFkWy2uj595 UvGAycKjaWjmeY6vaQ5uC+2Ao20W6SMUt60VeM4IT6/g5j2e9NNEPEeNYV3uXapb 9wBkP17R49wgy5qoqZGL1RRmoMt0AMZ7+Gpq0pHTQLLLv7b0HsctkMRxgnqCdTLz q5g4VlCPt2EfiTugJm9YGMvOg8JwF353yR+QULy4GGb8fLiA5QY0GO+V6EDXJVhc YWmuMPCZa5Jb9g00SDJBgUcsLLg5zId9IYoRjODICtqTICOgS8HwIjooEQxAmvUW ly6ITGPQHTcjDJvKv/rc9GFUV0mUBSS/fqeiu+HH9IJC8XRlCUseSF14zee6UdSQ == X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvvddrudeftddgudehkecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeeuohhrihhsuceuuhhrkhhovhcuoegsohhrihhssegsuhhr rdhioheqnecuggftrfgrthhtvghrnhepieeuffeuvdeiueejhfehiefgkeevudejjeejff evvdehtddufeeihfekgeeuheelnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghm pehmrghilhhfrhhomhepsghorhhishessghurhdrihho X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 15 Mar 2022 18:16:06 -0400 (EDT) From: Boris Burkov To: fstests@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH v7 2/5] btrfs: test btrfs specific fsverity corruption Date: Tue, 15 Mar 2022 15:15:58 -0700 Message-Id: X-Mailer: git-send-email 2.35.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org There are some btrfs specific fsverity scenarios that don't map neatly onto the tests in generic/574 like holes, inline extents, and preallocated extents. Cover those in a btrfs specific test. This test relies on the btrfs implementation of fsverity in the patch: btrfs: initial fsverity support and on btrfs-corrupt-block for corruption in the patches titled: btrfs-progs: corrupt generic item data with btrfs-corrupt-block btrfs-progs: expand corrupt_file_extent in btrfs-corrupt-block Signed-off-by: Boris Burkov --- common/btrfs | 5 ++ common/config | 1 + common/verity | 14 ++++ tests/btrfs/290 | 168 ++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/290.out | 25 +++++++ 5 files changed, 213 insertions(+) create mode 100755 tests/btrfs/290 create mode 100644 tests/btrfs/290.out diff --git a/common/btrfs b/common/btrfs index 670d9d1f..c3a7dc6e 100644 --- a/common/btrfs +++ b/common/btrfs @@ -511,3 +511,8 @@ _btrfs_metadump() $BTRFS_IMAGE_PROG "$device" "$dumpfile" [ -n "$DUMP_COMPRESSOR" ] && $DUMP_COMPRESSOR -f "$dumpfile" &> /dev/null } + +_require_btrfs_corrupt_block() +{ + _require_command "$BTRFS_CORRUPT_BLOCK_PROG" btrfs-corrupt-block +} diff --git a/common/config b/common/config index 479e50d1..67bdf912 100644 --- a/common/config +++ b/common/config @@ -296,6 +296,7 @@ export BTRFS_UTIL_PROG=$(type -P btrfs) export BTRFS_SHOW_SUPER_PROG=$(type -P btrfs-show-super) export BTRFS_CONVERT_PROG=$(type -P btrfs-convert) export BTRFS_TUNE_PROG=$(type -P btrfstune) +export BTRFS_CORRUPT_BLOCK_PROG=$(type -P btrfs-corrupt-block) export XFS_FSR_PROG=$(type -P xfs_fsr) export MKFS_NFS_PROG="false" export MKFS_CIFS_PROG="false" diff --git a/common/verity b/common/verity index 1afe4a82..77766fca 100644 --- a/common/verity +++ b/common/verity @@ -3,6 +3,8 @@ # # Functions for setting up and testing fs-verity +. common/btrfs + _require_scratch_verity() { _require_scratch @@ -48,6 +50,15 @@ _require_scratch_verity() FSV_BLOCK_SIZE=$(get_page_size) } +# Check for userspace tools needed to corrupt verity data or metadata. +_require_fsverity_corruption() +{ + _require_xfs_io_command "fiemap" + if [ $FSTYP == "btrfs" ]; then + _require_btrfs_corrupt_block + fi +} + # Check for CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y, as well as the userspace # commands needed to generate certificates and add them to the kernel. _require_fsverity_builtin_signatures() @@ -153,6 +164,9 @@ _scratch_mkfs_verity() ext4|f2fs) _scratch_mkfs -O verity ;; + btrfs) + _scratch_mkfs + ;; *) _notrun "No verity support for $FSTYP" ;; diff --git a/tests/btrfs/290 b/tests/btrfs/290 new file mode 100755 index 00000000..f9acd55a --- /dev/null +++ b/tests/btrfs/290 @@ -0,0 +1,168 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021 Facebook, Inc. All Rights Reserved. +# +# FS QA Test 290 +# +# Test btrfs support for fsverity. +# This test extends the generic fsverity testing by corrupting inline extents, +# preallocated extents, holes, and the Merkle descriptor in a btrfs-aware way. +# +. ./common/preamble +_begin_fstest auto quick verity + +# Import common functions. +. ./common/filter +. ./common/verity + +# real QA test starts here +_supported_fs btrfs +_require_scratch_verity +_require_scratch_nocheck +_require_odirect +_require_xfs_io_command "falloc" +_require_xfs_io_command "pread" +_require_xfs_io_command "pwrite" +_require_btrfs_corrupt_block + +get_ino() { + local file=$1 + stat -c "%i" $file +} + +validate() { + local f=$1 + local sz=$(_get_filesize $f) + # buffered io + echo $(basename $f) + $XFS_IO_PROG -rc "pread -q 0 $sz" $f 2>&1 | _filter_scratch + # direct io + $XFS_IO_PROG -rdc "pread -q 0 $sz" $f 2>&1 | _filter_scratch +} + +# corrupt the data portion of an inline extent +corrupt_inline() { + local f=$SCRATCH_MNT/inl + $XFS_IO_PROG -fc "pwrite -q -S 0x58 0 42" $f + local ino=$(get_ino $f) + _fsv_enable $f + _scratch_unmount + # inline data starts at disk_bytenr + # overwrite the first u64 with random bogus junk + $BTRFS_CORRUPT_BLOCK_PROG -i $ino -x 0 -f disk_bytenr $SCRATCH_DEV > /dev/null 2>&1 + _scratch_mount + validate $f +} + +# preallocate a file, then corrupt it by changing it to a regular file +corrupt_prealloc_to_reg() { + local f=$SCRATCH_MNT/prealloc + $XFS_IO_PROG -fc "falloc 0 12k" $f + local ino=$(get_ino $f) + _fsv_enable $f + _scratch_unmount + # set extent type from prealloc (2) to reg (1) + $BTRFS_CORRUPT_BLOCK_PROG -i $ino -x 0 -f type -v 1 $SCRATCH_DEV >/dev/null 2>&1 + _scratch_mount + validate $f +} + +# corrupt a regular file by changing the type to preallocated +corrupt_reg_to_prealloc() { + local f=$SCRATCH_MNT/reg + $XFS_IO_PROG -fc "pwrite -q -S 0x58 0 12288" $f + local ino=$(get_ino $f) + _fsv_enable $f + _scratch_unmount + # set type from reg (1) to prealloc (2) + $BTRFS_CORRUPT_BLOCK_PROG -i $ino -x 0 -f type -v 2 $SCRATCH_DEV >/dev/null 2>&1 + _scratch_mount + validate $f +} + +# corrupt a file by punching a hole +corrupt_punch_hole() { + local f=$SCRATCH_MNT/punch + $XFS_IO_PROG -fc "pwrite -q -S 0x58 0 12288" $f + local ino=$(get_ino $f) + # make a new extent in the middle, sync so the writes don't coalesce + $XFS_IO_PROG -c sync $SCRATCH_MNT + $XFS_IO_PROG -fc "pwrite -q -S 0x59 4096 4096" $f + _fsv_enable $f + _scratch_unmount + # change disk_bytenr to 0, representing a hole + $BTRFS_CORRUPT_BLOCK_PROG -i $ino -x 4096 -f disk_bytenr -v 0 $SCRATCH_DEV > /dev/null 2>&1 + _scratch_mount + validate $f +} + +# plug hole +corrupt_plug_hole() { + local f=$SCRATCH_MNT/plug + $XFS_IO_PROG -fc "pwrite -q -S 0x58 0 12288" $f + local ino=$(get_ino $f) + $XFS_IO_PROG -fc "falloc 4k 4k" $f + _fsv_enable $f + _scratch_unmount + # change disk_bytenr to some value, plugging the hole + $BTRFS_CORRUPT_BLOCK_PROG -i $ino -x 4096 -f disk_bytenr -v 13639680 $SCRATCH_DEV > /dev/null 2>&1 + _scratch_mount + validate $f +} + +# corrupt the fsverity descriptor item indiscriminately (causes EINVAL) +corrupt_verity_descriptor() { + local f=$SCRATCH_MNT/desc + $XFS_IO_PROG -fc "pwrite -q -S 0x58 0 12288" $f + local ino=$(get_ino $f) + _fsv_enable $f + _scratch_unmount + # key for the descriptor item is , + # 88 is X. So we write 5 Xs to the start of the descriptor + $BTRFS_CORRUPT_BLOCK_PROG -r 5 -I $ino,36,1 -v 88 -o 0 -b 5 $SCRATCH_DEV > /dev/null 2>&1 + _scratch_mount + validate $f +} + +# specifically target the root hash in the descriptor (causes EIO) +corrupt_root_hash() { + local f=$SCRATCH_MNT/roothash + $XFS_IO_PROG -fc "pwrite -q -S 0x58 0 12288" $f + local ino=$(get_ino $f) + _fsv_enable $f + _scratch_unmount + $BTRFS_CORRUPT_BLOCK_PROG -r 5 -I $ino,36,1 -v 88 -o 16 -b 1 $SCRATCH_DEV > /dev/null 2>&1 + _scratch_mount + validate $f +} + +# corrupt the Merkle tree data itself +corrupt_merkle_tree() { + local f=$SCRATCH_MNT/merkle + $XFS_IO_PROG -fc "pwrite -q -S 0x58 0 12288" $f + local ino=$(get_ino $f) + _fsv_enable $f + _scratch_unmount + # key for the descriptor item is , + # 88 is X. So we write 5 Xs to somewhere in the middle of the first + # merkle item + $BTRFS_CORRUPT_BLOCK_PROG -r 5 -I $ino,37,0 -v 88 -o 100 -b 5 $SCRATCH_DEV > /dev/null 2>&1 + _scratch_mount + validate $f +} + +# real QA test starts here +_scratch_mkfs >/dev/null +_scratch_mount + +corrupt_inline +corrupt_prealloc_to_reg +corrupt_reg_to_prealloc +corrupt_punch_hole +corrupt_plug_hole +corrupt_verity_descriptor +corrupt_root_hash +corrupt_merkle_tree + +status=0 +exit diff --git a/tests/btrfs/290.out b/tests/btrfs/290.out new file mode 100644 index 00000000..056b114b --- /dev/null +++ b/tests/btrfs/290.out @@ -0,0 +1,25 @@ +QA output created by 290 +inl +pread: Input/output error +pread: Input/output error +prealloc +pread: Input/output error +pread: Input/output error +reg +pread: Input/output error +pread: Input/output error +punch +pread: Input/output error +pread: Input/output error +plug +pread: Input/output error +pread: Input/output error +desc +SCRATCH_MNT/desc: Invalid argument +SCRATCH_MNT/desc: Invalid argument +roothash +pread: Input/output error +pread: Input/output error +merkle +pread: Input/output error +pread: Input/output error From patchwork Tue Mar 15 22:15:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12781882 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7EA75C433F5 for ; Tue, 15 Mar 2022 22:16:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350324AbiCOWRX (ORCPT ); Tue, 15 Mar 2022 18:17:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352117AbiCOWRV (ORCPT ); Tue, 15 Mar 2022 18:17:21 -0400 Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D6CA355BD4; Tue, 15 Mar 2022 15:16:08 -0700 (PDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 32FC75C01FC; Tue, 15 Mar 2022 18:16:08 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Tue, 15 Mar 2022 18:16:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bur.io; h=cc :content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm1; bh=yBU7ee8GgstnrKpZtmIYUDQFJY8SAT 8Fh47TW6BpOoI=; b=vMVLsIYegBDYQP2rj7qwq79ZOiw+xpb/jR3TGSJWJVTOl8 Ha/53kUqzz/p0zXbTKuVUqwHqxuUzL/K/yBT5qDfCthUp3N3hRbp0Q0NDRoNDfvf Y9GBh0PUfWSbgmZQVTsKpPbA2qSAGhJDWT3u2dfR0e0Nvcah5LHSj3ZX+7yn9HJS t450GhxkmbE1qnmwKhyW3n1PCmdIJIuin3kLljIUSO9GRmo/4F17NDi4BcSIRVyX 3JtTnVAU+X77PZzPYN3z582D5GaDITNS3xRKHUACUczfu7B8uCqexKYqSxTGkC2S iUCywFOygXWOZKfq7opkIHHV2shfCr6ja4XSFVPQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; bh=yBU7ee 8GgstnrKpZtmIYUDQFJY8SAT8Fh47TW6BpOoI=; b=KXgC9QnbCwu/o2KNxmPc5E F6P/VucpZN+m1OpZpHwEG7w/A17UBZcto1X25DuRNGFsu4roQit6fcQ8KNTKM6Mu 8izKGzsuM83hzVePKtRH1OisKFBLyKYTSqe6CEOCPjQ3yQawQJHxJlVFhMHhOMuN MbEs2K8/mFBvikSPnpkjfYf1pqmMblWVlHZEFw66Q4LrC1jgft5ypfhVwWzggQ8a 3ucDhoXol8Dc21m1tkloqGauhANU+LGMZXAZix4v4yIjYAmj6NLYqPdSn+XzCxmN 6C1Jx+xFfQzcdXqUAK5rOGwYk/g/jcKK7I4w5dcOPurqRLOOlB3htienbnnyMPYA == X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvvddrudeftddgudehkecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeeuohhrihhsuceuuhhrkhhovhcuoegsohhrihhssegsuhhr rdhioheqnecuggftrfgrthhtvghrnhepieeuffeuvdeiueejhfehiefgkeevudejjeejff evvdehtddufeeihfekgeeuheelnecuvehluhhsthgvrhfuihiivgepudenucfrrghrrghm pehmrghilhhfrhhomhepsghorhhishessghurhdrihho X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 15 Mar 2022 18:16:07 -0400 (EDT) From: Boris Burkov To: fstests@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH v7 3/5] generic/574: corrupt btrfs merkle tree data Date: Tue, 15 Mar 2022 15:15:59 -0700 Message-Id: <6d08195d452509ebf0f8724fd3c25a7cd2079232.1647382272.git.boris@bur.io> X-Mailer: git-send-email 2.35.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org generic/574 has tests for corrupting the merkle tree data stored by the filesystem. Since btrfs uses a different scheme for storing this data, the existing logic for corrupting it doesn't work out of the box. Adapt it to properly corrupt btrfs merkle items. This test relies on the btrfs implementation of fsverity in the patch: btrfs: initial fsverity support and on btrfs-corrupt-block for corruption in the patches titled: btrfs-progs: corrupt generic item data with btrfs-corrupt-block btrfs-progs: expand corrupt_file_extent in btrfs-corrupt-block Signed-off-by: Boris Burkov --- common/verity | 15 +++++++++++++++ tests/generic/574 | 1 + 2 files changed, 16 insertions(+) diff --git a/common/verity b/common/verity index 77766fca..db03510e 100644 --- a/common/verity +++ b/common/verity @@ -328,6 +328,21 @@ _fsv_scratch_corrupt_merkle_tree() (( offset += ($(_get_filesize $file) + 65535) & ~65535 )) _fsv_scratch_corrupt_bytes $file $offset ;; + btrfs) + local ino=$(stat -c '%i' $file) + _scratch_unmount + local byte="" + while read -n 1 byte; do + local ascii=$(printf "%d" "'$byte'") + # This command will find a Merkle tree item for the inode (-I $ino,37,0) + # in the default filesystem tree (-r 5) and corrupt one byte (-b 1) at + # $offset (-o $offset) with the ascii representation of the byte we read + # (-v $ascii) + $BTRFS_CORRUPT_BLOCK_PROG -r 5 -I $ino,37,0 -v $ascii -o $offset -b 1 $SCRATCH_DEV + (( offset += 1 )) + done + _scratch_mount + ;; *) _fail "_fsv_scratch_corrupt_merkle_tree() unimplemented on $FSTYP" ;; diff --git a/tests/generic/574 b/tests/generic/574 index 17fdea52..18810ab2 100755 --- a/tests/generic/574 +++ b/tests/generic/574 @@ -27,6 +27,7 @@ _cleanup() # real QA test starts here _supported_fs generic _require_scratch_verity +_require_fsverity_corruption _disable_fsverity_signatures _require_fsverity_corruption From patchwork Tue Mar 15 22:16:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12781883 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1CBFDC43217 for ; Tue, 15 Mar 2022 22:16:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352139AbiCOWRY (ORCPT ); Tue, 15 Mar 2022 18:17:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46880 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352087AbiCOWRX (ORCPT ); Tue, 15 Mar 2022 18:17:23 -0400 Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 712A75C378; Tue, 15 Mar 2022 15:16:10 -0700 (PDT) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.nyi.internal (Postfix) with ESMTP id D2D905C020B; Tue, 15 Mar 2022 18:16:09 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Tue, 15 Mar 2022 18:16:09 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bur.io; h=cc :content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm1; bh=ny4Q2FVzFqb+sXdXjFmgDO8a4sK0jN +xSwCEIIx8Blk=; b=zU32nAqwS/4hgQrdu8W2Pe+rFR172gk6vPyBc/33bLsVj+ dBj7yE3hCja2PtXp/XkKBiCksbFPxQ7tzYJE2H++GLECDdE/y/Kl8RVenad6tK6F CY4dFcn0w2+g7186pSjjmIDHHY19/deWCdpaQnZIbF6s5dI+JA9Ep8seboCCcSY+ hTYTkh2V1Xo+W9qbsUpkuFBGC125trrQtfof1rcoCxAWd8nwxvUUv8ZnNqc99Cun xzrKP4Qp1CH4sQTsHVgJERELBN6GeLjulzb5ETrEYhEXNz95NLL+5lEWKzqh48WT mWNBqhKmHx+gE6OogLau1VxaNHD8NkCP/9klAK3A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; bh=ny4Q2F VzFqb+sXdXjFmgDO8a4sK0jN+xSwCEIIx8Blk=; b=Ug2meB8di6p/708GYVUJDf SLdrzGwU/57N63iNaejfS5EsffLTrWQ7WpIR7pc3lreTbafbYDGwhX+QBk9paRql T/e1kI1TafF1V3sohP2ENb+lRFLV194Ca/at89bIV3AMd3dC0BLOPZko16I4/l6d yZYGwANxpD+obWerEMXMiTRISnyYU1RCDOIPX5GAFJf5XGSJK9+mJJ4cCvV5EC3O lHXZlE1Hs+QNdIn6It8OevghCpQdGpEy+Sk6n68+HfrNBJxRuBdWyuSLfewK5zI2 ITBzHw+PMvCc2HSC6HmABtC/YALXAQrwewdKohdqj9Rh9wawSqZB1+p0I3XscTvg == X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvvddrudeftddgudehjecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeeuohhrihhsuceuuhhrkhhovhcuoegsohhrihhssegsuhhr rdhioheqnecuggftrfgrthhtvghrnhepieeuffeuvdeiueejhfehiefgkeevudejjeejff evvdehtddufeeihfekgeeuheelnecuvehluhhsthgvrhfuihiivgepudenucfrrghrrghm pehmrghilhhfrhhomhepsghorhhishessghurhdrihho X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 15 Mar 2022 18:16:09 -0400 (EDT) From: Boris Burkov To: fstests@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH v7 4/5] btrfs: test verity orphans with dmlogwrites Date: Tue, 15 Mar 2022 15:16:00 -0700 Message-Id: <5579a70597cd660ffb265db9e97840a1faca8812.1647382272.git.boris@bur.io> X-Mailer: git-send-email 2.35.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org The behavior of orphans is most interesting across mounts, interrupted at arbitrary points during fsverity enable. To cover as many such cases as possible, use dmlogwrites and dmsnapshot as in log-writes/replay-individual.sh. At each log entry, we want to assert a somewhat complicated invariant: If verity has not yet started: an orphan indicates that verity has started. If verity has started: mount should handle the orphan and blow away verity data: expect 0 merkle items after mounting the snapshot dev. If we can measure the file, verity has finished. If verity has finished: the orphan should be gone, so mount should not blow away merkle items. Expect the same number of merkle items before and after mounting the snapshot dev. Note that this relies on grepping btrfs inspect-internal dump-tree. Until btrfs-progs has the ability to print the new Merkle items, they will show up as UNKNOWN.36/37. Signed-off-by: Boris Burkov --- tests/btrfs/291 | 161 ++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/291.out | 2 + 2 files changed, 163 insertions(+) create mode 100755 tests/btrfs/291 create mode 100644 tests/btrfs/291.out diff --git a/tests/btrfs/291 b/tests/btrfs/291 new file mode 100755 index 00000000..1bb3f1b3 --- /dev/null +++ b/tests/btrfs/291 @@ -0,0 +1,161 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2021 Facebook, Inc. All Rights Reserved. +# +# FS QA Test 291 +# +# Test btrfs consistency after each FUA while enabling verity on a file +# This test works by following the pattern in log-writes/replay-individual.sh: +# 1. run a workload (verity + sync) while logging to the log device +# 2. replay an entry to the replay device +# 3. snapshot the replay device to the snapshot device +# 4. run destructive tests on the snapshot device (e.g. mount with orphans) +# 5. goto 2 +# +. ./common/preamble +_begin_fstest auto verity + +# Override the default cleanup function. +_cleanup() +{ + cd / + _log_writes_cleanup &> /dev/null + rm -f $img + $LVM_PROG vgremove -f -y $vgname >>$seqres.full 2>&1 + losetup -d $loop_dev >>$seqres.full 2>&1 +} + +# Import common functions. +. ./common/filter +. ./common/attr +. ./common/dmlogwrites +. ./common/verity + +# real QA test starts here +_supported_fs btrfs + +_require_scratch +_require_test +_require_log_writes +_require_dm_target snapshot +_require_command $LVM_PROG lvm +_require_scratch_verity +_require_btrfs_command inspect-internal dump-tree +_require_test_program "log-writes/replay-log" + +sync_loop() { + i=$1 + [ -z "$i" ] && _fail "sync loop needs a number of iterations" + while [ $i -gt 0 ] + do + $XFS_IO_PROG -c sync $SCRATCH_MNT + let i-=1 + done +} + +dump_tree() { + local dev=$1 + $BTRFS_UTIL_PROG inspect-internal dump-tree $dev +} + +count_item() { + local dev=$1 + local item=$2 + dump_tree $dev | grep -c $item +} + +_log_writes_init $SCRATCH_DEV +_log_writes_mkfs +_log_writes_mount + +f=$SCRATCH_MNT/fsv +MB=$((1024 * 1024)) +img=$TEST_DIR/$$.img +$XFS_IO_PROG -fc "pwrite -q 0 $((10 * $MB))" $f +$XFS_IO_PROG -c sync $SCRATCH_MNT +sync_loop 10 & +sync_proc=$! +_fsv_enable $f +$XFS_IO_PROG -c sync $SCRATCH_MNT +wait $sync_proc + +_log_writes_unmount +_log_writes_remove + +# the snapshot and the replay will each be the size of the log writes dev +# so we create a loop device of size 2 * logwrites and then split it into +# replay and snapshot with lvm. +log_writes_blocks=$(blockdev --getsz $LOGWRITES_DEV) +replay_bytes=$((512 * $log_writes_blocks)) +img_bytes=$((2 * $replay_bytes)) + +$XFS_IO_PROG -fc "pwrite -q -S 0 $img_bytes $MB" $img >>$seqres.full 2>&1 || \ + _fail "failed to create image for loop device" +loop_dev=$(losetup -f --show $img) +vgname=vg_replay +lvname=lv_replay +replay_dev=/dev/mapper/vg_replay-lv_replay +snapname=lv_snap +snap_dev=/dev/mapper/vg_replay-$snapname + +$LVM_PROG vgcreate -f $vgname $loop_dev >>$seqres.full 2>&1 || _fail "failed to vgcreate $vgname" +$LVM_PROG lvcreate -L "$replay_bytes"B -n $lvname $vgname -y >>$seqres.full 2>&1 || \ + _fail "failed to lvcreate $lvname" +$UDEV_SETTLE_PROG >>$seqres.full 2>&1 + +replay_log_prog=$here/src/log-writes/replay-log +num_entries=$($replay_log_prog --log $LOGWRITES_DEV --num-entries) +entry=$($replay_log_prog --log $LOGWRITES_DEV --replay $replay_dev --find --end-mark mkfs | cut -d@ -f1) +$replay_log_prog --log $LOGWRITES_DEV --replay $replay_dev --limit $entry || \ + _fail "failed to replay to start entry $entry" +let entry+=1 + +# state = 0: verity hasn't started +# state = 1: verity underway +# state = 2: verity done +state=0 +while [ $entry -lt $num_entries ]; +do + $replay_log_prog --limit 1 --log $LOGWRITES_DEV --replay $replay_dev --start $entry || \ + _fail "failed to take replay step at entry: $entry" + + $LVM_PROG lvcreate -s -L 4M -n $snapname $vgname/$lvname >>$seqres.full 2>&1 || \ + _fail "Failed to create snapshot" + $UDEV_SETTLE_PROG >>$seqres.full 2>&1 + + orphan=$(count_item $snap_dev ORPHAN) + if [ $state -eq 0 ]; then + [ $orphan -gt 0 ] && state=1 + fi + + pre_mount=$(count_item $snap_dev UNKNOWN.3[67]) + _mount $snap_dev $SCRATCH_MNT || _fail "mount failed at entry $entry" + fsverity measure $SCRATCH_MNT/fsv >>$seqres.full 2>&1 + measured=$? + umount $SCRATCH_MNT + [ $state -eq 1 ] && [ $measured -eq 0 ] && state=2 + [ $state -eq 2 ] && ([ $measured -eq 0 ] || _fail "verity done, but measurement failed at entry $entry") + post_mount=$(count_item $snap_dev UNKNOWN.3[67]) + + echo "entry: $entry, state: $state, orphan: $orphan, pre_mount: $pre_mount, post_mount: $post_mount" >> $seqres.full + + if [ $state -eq 1 ]; then + [ $post_mount -eq 0 ] || \ + _fail "mount failed to clear under-construction merkle items pre: $pre_mount, post: $post_mount at entry $entry"; + fi + if [ $state -eq 2 ]; then + [ $pre_mount -gt 0 ] || \ + _fail "expected to have verity items before mount at entry $entry" + [ $pre_mount -eq $post_mount ] || \ + _fail "mount cleared merkle items after verity was enabled $pre_mount vs $post_mount at entry $entry"; + fi + + let entry+=1 + $LVM_PROG lvremove $vgname/$snapname -y >>$seqres.full +done + +echo "Silence is golden" + +# success, all done +status=0 +exit diff --git a/tests/btrfs/291.out b/tests/btrfs/291.out new file mode 100644 index 00000000..04605c70 --- /dev/null +++ b/tests/btrfs/291.out @@ -0,0 +1,2 @@ +QA output created by 291 +Silence is golden From patchwork Tue Mar 15 22:16:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12781884 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EC444C433EF for ; Tue, 15 Mar 2022 22:16:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352131AbiCOWRZ (ORCPT ); Tue, 15 Mar 2022 18:17:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46912 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352148AbiCOWRY (ORCPT ); Tue, 15 Mar 2022 18:17:24 -0400 Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 247CF5C379; Tue, 15 Mar 2022 15:16:12 -0700 (PDT) Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id 7CD8E5C0200; Tue, 15 Mar 2022 18:16:11 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Tue, 15 Mar 2022 18:16:11 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bur.io; h=cc :content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm1; bh=B7aWnl6o+/fwtAlM3Qm/DL+gMV/6dV zUA8OGnisteTc=; b=MwWR1209ql1+TZJio4Qb1HZOmmvUK0JhtWX6BTYueS07qI OFHYI2sA5PLBB4wB97KfB9AH05qTERzvFjlkWXb0HBgb5WZ8nAIvgHbI+WfBkxPC ClBM7R1SF63sGhE7on/vmOak8vkQ5FxJ0s1qaPK9f+V42+cOJLc1YJE5tuTwITs5 Jnp9iHv+K30TKTofsJcpB4PNl8scHXsn//PuZwLx9p9wLrf1enz0JiMfV9E9uxxJ CUFcLJfKDshqOoQlgGkiA63GeQDag4TPMBjPjFg9fS0g6gd7V85RFkKHypfv3rq/ HkfWfGynx0SlE1unkbq9+1Wd1ITFRPtx8toOhxbA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; bh=B7aWnl 6o+/fwtAlM3Qm/DL+gMV/6dVzUA8OGnisteTc=; b=Vr50i+E08m8jNox/C80lPu svvv7wIk7q8RXiuBbUMMMnyFwDxLys+aj4c4wr26X11vrfzBCI1CDUuwGAN7Ll5f NIFBZtXN2eVi4wFBLfNU/fo2cdhGAt2x04C86FpJpIYyCPTNySjdt7LQM8I+NIOC yANbzN8wbumRxz271Gm1uEAJDt1a1SA0rMm6+tejRJLyLoujsQehSUZrCoCQIgkq QGXmB43fYwjjJMZQJhyrhxOOE6ab0CGeAUMvr/9kyhdTWj5tD4psIXDdcdUNQbmf jMn8vi21qqlg1/61t0PnesACHuOuHZg2mu3FIO2yU7vO8ZjrReisnk5DLCB4sKZA == X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvvddrudeftddgudehjecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtke ertdertddtnecuhfhrohhmpeeuohhrihhsuceuuhhrkhhovhcuoegsohhrihhssegsuhhr rdhioheqnecuggftrfgrthhtvghrnhepieeuffeuvdeiueejhfehiefgkeevudejjeejff evvdehtddufeeihfekgeeuheelnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghm pehmrghilhhfrhhomhepsghorhhishessghurhdrihho X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 15 Mar 2022 18:16:11 -0400 (EDT) From: Boris Burkov To: fstests@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH v7 5/5] generic: test fs-verity EFBIG scenarios Date: Tue, 15 Mar 2022 15:16:01 -0700 Message-Id: X-Mailer: git-send-email 2.35.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org btrfs, ext4, and f2fs cache the Merkle tree past EOF, which restricts the maximum file size beneath the normal maximum. Test the logic in those filesystems against files with sizes near the maximum. To work properly, this does require some understanding of the practical but not standardized layout of the Merkle tree. This is a bit unpleasant and could make the test incorrect in the future, if the implementation changes. On the other hand, it feels quite useful to test this tricky edge case. It could perhaps be made more generic by adding some ioctls to let the file system communicate the maximum file size for a verity file or some information about the storage of the Merkle tree. Signed-off-by: Boris Burkov Reviewed-by: Eric Biggers --- common/verity | 11 ++++++++ tests/generic/690 | 64 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/690.out | 7 +++++ 3 files changed, 82 insertions(+) create mode 100755 tests/generic/690 create mode 100644 tests/generic/690.out diff --git a/common/verity b/common/verity index db03510e..2b3d4dae 100644 --- a/common/verity +++ b/common/verity @@ -348,3 +348,14 @@ _fsv_scratch_corrupt_merkle_tree() ;; esac } + +_require_fsverity_max_file_size_limit() +{ + case $FSTYP in + btrfs|ext4|f2fs) + ;; + *) + _notrun "$FSTYP does not store verity data past EOF; no special file size limit" + ;; + esac +} diff --git a/tests/generic/690 b/tests/generic/690 new file mode 100755 index 00000000..afdd95f2 --- /dev/null +++ b/tests/generic/690 @@ -0,0 +1,64 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2021 Facebook, Inc. All Rights Reserved. +# +# FS QA Test 690 +# +# fs-verity requires the filesystem to decide how it stores the Merkle tree, +# which can be quite large. +# It is convenient to treat the Merkle tree as past EOF, and ext4, f2fs, and +# btrfs do so in at least some fashion. This leads to an edge case where a +# large file can be under the file system file size limit, but trigger EFBIG +# on enabling fs-verity. Test enabling verity on some large files to exercise +# EFBIG logic for filesystems with fs-verity specific limits. +# +. ./common/preamble +_begin_fstest auto quick verity + + +# Import common functions. +. ./common/filter +. ./common/verity + +# real QA test starts here +_supported_fs generic +_require_test +_require_math +_require_scratch_verity +_require_fsverity_max_file_size_limit + +_scratch_mkfs_verity &>> $seqres.full +_scratch_mount + +fsv_file=$SCRATCH_MNT/file.fsv + +max_sz=$(_get_max_file_size) +_fsv_scratch_begin_subtest "way too big: fail on first merkle block" +truncate -s $max_sz $fsv_file +_fsv_enable $fsv_file |& _filter_scratch + +# The goal of this second test is to make a big enough file that we trip the +# EFBIG codepath, but not so big that we hit it immediately when writing the +# first Merkle leaf. +# +# The Merkle tree is stored with the leaf node level (L0) last, but it is +# written first. To get an interesting overflow, we need the maximum file size +# (MAX) to be in the middle of L0 -- ideally near the beginning of L0 so that we +# don't have to write many blocks before getting an error. +# +# With SHA-256 and 4K blocks, there are 128 hashes per block. Thus, ignoring +# padding, L0 is 1/128 of the file size while the other levels in total are +# 1/128**2 + 1/128**3 + 1/128**4 + ... = 1/16256 of the file size. So still +# ignoring padding, for L0 start exactly at MAX, the file size must be s such +# that s + s/16256 = MAX, i.e. s = MAX * (16256/16257). Then to get a file size +# where MAX occurs *near* the start of L0 rather than *at* the start, we can +# just subtract an overestimate of the padding: 64K after the file contents, +# then 4K per level, where the consideration of 8 levels is sufficient. +sz=$(echo "scale=20; $max_sz * (16256/16257) - 65536 - 4096*8" | $BC -q | cut -d. -f1) +_fsv_scratch_begin_subtest "still too big: fail on first invalid merkle block" +truncate -s $sz $fsv_file +_fsv_enable $fsv_file |& _filter_scratch + +# success, all done +status=0 +exit diff --git a/tests/generic/690.out b/tests/generic/690.out new file mode 100644 index 00000000..a3e2b9b9 --- /dev/null +++ b/tests/generic/690.out @@ -0,0 +1,7 @@ +QA output created by 690 + +# way too big: fail on first merkle block +ERROR: FS_IOC_ENABLE_VERITY failed on 'SCRATCH_MNT/file.fsv': File too large + +# still too big: fail on first invalid merkle block +ERROR: FS_IOC_ENABLE_VERITY failed on 'SCRATCH_MNT/file.fsv': File too large