From patchwork Tue Apr 26 22:40:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12828020 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 2B437C433F5 for ; Tue, 26 Apr 2022 22:40:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355895AbiDZWnb (ORCPT ); Tue, 26 Apr 2022 18:43:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49056 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240418AbiDZWna (ORCPT ); Tue, 26 Apr 2022 18:43:30 -0400 Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7FF2A13F0A; Tue, 26 Apr 2022 15:40:20 -0700 (PDT) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 399195C0164; Tue, 26 Apr 2022 18:40:20 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Tue, 26 Apr 2022 18:40:20 -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; t=1651012820; x=1651099220; bh=ss XnEw9itOkmvU5n03mfVnTTvDIDQzuYWNCfiA8EImc=; b=rdXJO4n+zvSMyf0bfx APovOQXpWQ+u708ePQHg17Ds1IB0TngWZjqZvgzpZOT6R7Mpw+aOXoTvff0dbOn+ YOcxxA+sFmR0RvskXAH6vkt9TbEG46PDbLLEAbIEqqmPqNsT276VPiysigBYZSFQ l42G49F2YYJWf4fFAAnPR+aa7kD4oUrk9432pAm5s3I3ShbOukJYe0Ek4xq1lZ2L 0scbHK7wLT0lUJ1uYeyIygn08M/q3myk3h6zTnxQF7onwkTNrdoreuIQPo88Ysxa 7/+WjMM8ejPGxmdFBB3bI2foGhrFfND201iNxMv8PCazyoxRaR8wJjbIf11O/+wA KblQ== 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=fm1; t= 1651012820; x=1651099220; bh=ssXnEw9itOkmvU5n03mfVnTTvDIDQzuYWNC fiA8EImc=; b=zhStwTUOtdyr2aNfIiAfMk78ksLMpxJzhvGZ2c7HVjOBDWqTAbT TOnAAXonChn9l6yDQFWgYfmo/ZYztqf8n7md0pOuYIV/M3sHTN+j7ee70D8B+dz/ Lt5CTM3ItLPck8QGuS6skEARWD7YlR9jMj1xJCCoZdRFPtCnH3G2xs83GYEOq7Xb dlwui8y8iw8uQ0IqdNSLLku12J652b4BZavm3o1+MXU5Y+RszCQp8LZjf8AjV2x2 w2if+QOL/i7ZikQa0M1tS15brT37zG3gY0/Q/DUyNASnHn1AxFdga3XM61hjKSl1 Z/puZ2Jmoli5kMmvqKKc9QNiLU9lLHvnlnA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrudeggddugecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpeeuohhrihhsuceuuhhrkhhovhcuoegsohhrihhssegsuhhrrdhi oheqnecuggftrfgrthhtvghrnhepieeuffeuvdeiueejhfehiefgkeevudejjeejffevvd ehtddufeeihfekgeeuheelnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehm rghilhhfrhhomhepsghorhhishessghurhdrihho X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 26 Apr 2022 18:40:19 -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 v9 1/5] common/verity: require corruption functionality Date: Tue, 26 Apr 2022 15:40:12 -0700 Message-Id: <657cd5facdbd0b41ee99ab18ad0bba9f0d690729.1651012461.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: Josef Bacik 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..d58cad90 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 Apr 26 22:40:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12828022 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 5AA51C433F5 for ; Tue, 26 Apr 2022 22:40:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345860AbiDZWnd (ORCPT ); Tue, 26 Apr 2022 18:43:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49134 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355900AbiDZWnc (ORCPT ); Tue, 26 Apr 2022 18:43:32 -0400 Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 03AD514026; Tue, 26 Apr 2022 15:40:23 -0700 (PDT) Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id 668F45C0176; Tue, 26 Apr 2022 18:40:22 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute5.internal (MEProxy); Tue, 26 Apr 2022 18:40:22 -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; t=1651012822; x=1651099222; bh=YE aTmrniy5m8AfmjwUsMBxrwMa8bYqmGYLciN6SG0XY=; b=npPNJBDwePqBXGBfJq IaQnz1gKXTDUIh0CzEPnlLFlyyeYYYAyHM5jpxR92Cns92gqZmOuKQ+rOHx3Qe9b n5xng0oa67lXw/BZQvP+Ga8yv8SVckhQo1hwvmxH3gELCma4x/QHiPUnV54VfU4/ GWwcQ9wBeU7VGYV79mhw4o7zBHBMVMZlFUuaogU9C1pvp9wL+zpGg4IAqFn9gV+H IhWtrLAkREyEtmhFLLhd2VdI5YzVeljSjztJbfUrKhAT4eGclvUlMxJnCGmxGju6 C0LNTaCr2oMRWDJn6MzSXBVRM/61nVQdRJBpnYYqlSDPVyK5KgwjjXWSC94YjyFc PllQ== 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=fm1; t= 1651012822; x=1651099222; bh=YEaTmrniy5m8AfmjwUsMBxrwMa8bYqmGYLc iN6SG0XY=; b=LD4rAQShqNhx5caDJR6OCo9RnZxpr4b1aZkZF08iZuSQDECvxH/ 8hvBUS62zJuyPhEnLJGQogQsIkZ2VQsuRsIkCX2GwQN6n1A3o/2Zfv/NICO8+fR5 sPpHzeCfWT3dpoW2PhpXRxW/R8wanX9gLOfLasXZVmHTD3YCXYjrmNcqj6zUiE0n vi2Tdo7ZGBq9JNtWBuNLvfj3MiQAvk0Tn+XutP8U77+X+dX5ko5Z1NgFIDhZB9po 5gU9BqjCcpCAgW7xOEgPhdZxX0CYZrK5TsOUTytlcY+Al0K7w1siCVJjq4tZmW7A LR/ddrFH7swfRNt8vd+VRNs7b/X4FyAZu2w== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrudeggddufecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpeeuohhrihhsuceuuhhrkhhovhcuoegsohhrihhssegsuhhrrdhi oheqnecuggftrfgrthhtvghrnhepieeuffeuvdeiueejhfehiefgkeevudejjeejffevvd ehtddufeeihfekgeeuheelnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehm rghilhhfrhhomhepsghorhhishessghurhdrihho X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 26 Apr 2022 18:40:22 -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 v9 2/5] common/verity: support btrfs in generic fsverity tests Date: Tue, 26 Apr 2022 15:40:13 -0700 Message-Id: <3ac2f088ab31052659aa37a7e2f0821ef7b95e60.1651012461.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/572-579 have tests for fsverity. Now that btrfs supports fsverity, make these tests function as well. For a majority of the tests that pass, simply adding the case to mkfs a btrfs filesystem with no extra options is sufficient. However, generic/574 has tests for corrupting the merkle tree itself. Since btrfs uses a different scheme from ext4 and f2fs 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. 576 does not run because btrfs does not support transparent encryption. 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 Reviewed-by: Josef Bacik --- common/btrfs | 5 +++++ common/config | 1 + common/verity | 28 ++++++++++++++++++++++++++++ tests/generic/574 | 39 +++++++++++++++++++++++++++++++++++++-- tests/generic/574.out | 12 +++--------- 5 files changed, 74 insertions(+), 11 deletions(-) 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 d58cad90..8cde2737 100644 --- a/common/verity +++ b/common/verity @@ -3,6 +3,13 @@ # # Functions for setting up and testing fs-verity +. common/btrfs +# btrfs will return IO errors on corrupted data with or without fs-verity. +# to really test fs-verity, use nodatasum. +if [ "$FSTYP" == "btrfs" ]; then + export MOUNT_OPTIONS="-o nodatasum" +fi + _require_scratch_verity() { _require_scratch @@ -145,6 +152,9 @@ _require_fsverity_dump_metadata() _require_fsverity_corruption() { _require_xfs_io_command "fiemap" + if [ $FSTYP == "btrfs" ]; then + _require_btrfs_corrupt_block + fi } _scratch_mkfs_verity() @@ -153,6 +163,9 @@ _scratch_mkfs_verity() ext4|f2fs) _scratch_mkfs -O verity ;; + btrfs) + _scratch_mkfs + ;; *) _notrun "No verity support for $FSTYP" ;; @@ -314,6 +327,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..680cece3 100755 --- a/tests/generic/574 +++ b/tests/generic/574 @@ -126,6 +126,41 @@ corruption_test() fi } +# xfs_io mread's output is parseable by xxd -r, except it has an extra space +# after the colon. Output the number of non zero characters in the parsed contents. +filter_mread() { + sed 's/: /: /' | xxd -r | sed 's/\x0//g' | wc -c +} + +# this expects to see stdout + stderr passed through filter_sigbus and filter_mread. +# Outputs "OK" on a bus error or 0 non-zero characters counted by mread. +filter_eof_block() { + sed 's/^Bus error$/OK/' | sed 's/^0$/OK/' +} + +# some filesystems return zeros in the last block past EOF, regardless of +# their contents. Handle those with a special test that accepts either zeros +# or SIGBUS on an mmap+read of that block. +corrupt_eof_block_test() { + local file_len=$1 + local zap_len=$2 + local page_aligned_eof=$(round_up_to_page_boundary $file_len) + local eof_page_start=$((page_aligned_eof - $(get_page_size))) + local corrupt_func=_fsv_scratch_corrupt_bytes + _fsv_scratch_begin_subtest "Corruption test: EOF block" + setup_zeroed_file $file_len false + cmp $fsv_file $fsv_orig_file + echo "Corrupting bytes..." + head -c $zap_len /dev/zero | tr '\0' X \ + | $corrupt_func $fsv_file $((file_len + 1)) + + echo "Validating corruption or zeros (reading eof block via mmap)..." + bash -c "trap '' SIGBUS; $XFS_IO_PROG -r $fsv_file \ + -c 'mmap -r $eof_page_start $(get_page_size)' \ + -c 'mread -v $eof_page_start $(get_page_size)'" \ + |& filter_mread | filter_sigbus | filter_eof_block +} + # Note: these tests just overwrite some bytes without checking their original # values. Therefore, make sure to overwrite at least 5 or so bytes, to make it # nearly guaranteed that there will be a change -- even when the test file is @@ -137,8 +172,8 @@ corruption_test 131072 65536 65536 corruption_test 131072 131067 5 # Non-zeroed bytes in the final partial block beyond EOF should cause reads to -# fail too. Such bytes would be visible via mmap(). -corruption_test 130999 131000 72 +# fail too. Such bytes could be visible via mmap(). +corrupt_eof_block_test 130999 72 # Merkle tree corruption. corruption_test 200000 100 10 true diff --git a/tests/generic/574.out b/tests/generic/574.out index 3c08d3e8..51bbd17b 100644 --- a/tests/generic/574.out +++ b/tests/generic/574.out @@ -56,17 +56,11 @@ Bus error Validating corruption (reading just corrupted part via mmap)... Bus error -# Corruption test: file_len=130999 zap_offset=131000 zap_len=72 +# Corruption test: EOF block f5cca0d7fbb8b02bc6118a9954d5d306 SCRATCH_MNT/file.fsv Corrupting bytes... -Validating corruption (reading full file)... -md5sum: SCRATCH_MNT/file.fsv: Input/output error -Validating corruption (direct I/O)... -dd: error reading 'SCRATCH_MNT/file.fsv': Input/output error -Validating corruption (reading full file via mmap)... -Bus error -Validating corruption (reading just corrupted part via mmap)... -Bus error +Validating corruption or zeros (reading eof block via mmap)... +OK # Corruption test: file_len=200000 zap_offset=100 (in Merkle tree) zap_len=10 4a1e4325031b13f933ac4f1db9ecb63f SCRATCH_MNT/file.fsv From patchwork Tue Apr 26 22:40:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12828023 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 9F013C4167E for ; Tue, 26 Apr 2022 22:40:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355900AbiDZWne (ORCPT ); Tue, 26 Apr 2022 18:43:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49168 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355905AbiDZWnd (ORCPT ); Tue, 26 Apr 2022 18:43:33 -0400 Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A7C4914096; Tue, 26 Apr 2022 15:40:24 -0700 (PDT) Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id 16AA35C0178; Tue, 26 Apr 2022 18:40:24 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Tue, 26 Apr 2022 18:40:24 -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; t=1651012824; x=1651099224; bh=kd CQVT5iGxrkT4Rh51mMDn0TbprGq2A1KbBC1nlNg58=; b=Ow8s9+ksnR5NnpOANb gx5zMFwOnDPbkoyuzvtbT/5Mou+by/PPEtRfgKA91r//jsXlMjROsLIkJQrH4DdV 2mVTKYyU2Q6XskeX7C1DaePsztC6tKrToTBmuDgcKIFc+b/3MvpTx5EE/5BWtpcK g8U6sNGdg72d9Cq6yFKpRAtREoTLB7XIdqmjJGNpaI874YyjaPy1ElU24CbOu2Fh uCzJel2tU7K1P5E5uOE9A4agSBU1Z4ai4jSRCaqJKfgO6q8z5jWYbdMhKL98w6HK pxQeS6TcsHnbIvP+iuyLqXaBNsDL6Nc5hVC9JKreKEdJGWATVq7e9J/JdN2tDSQR 0mvA== 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=fm1; t= 1651012824; x=1651099224; bh=kdCQVT5iGxrkT4Rh51mMDn0TbprGq2A1KbB C1nlNg58=; b=LVDZhVf3DaEwFWkNPWX2MBLFnJYcWGoKpHfIDKBD6jJB9oApyF/ 3OyudEiM6T9bkXBSHXnHAoSX1MG+3r3A44ixY2Y3K56SrnOCKQyQNSP+By81FQuS LCsdahWCNe+xrXjOxoq1iuMzg7nCbrBsk02QmRZt8dZoIq7OsWaBqFoPWl9xePJ4 gfqJmI27f99cMu8/mN23Enpbp604SqUZrTzDoDHeYcNJ0SghlPOhPn8O0SIVHr2+ MzAKcXY8w9Dvm4Gsk0FO8zSE/dSzCjF/TzPnFAZF7KyrBQAWnG7Thz6mtYRUxd5S I+ZQ+7ekabUViGbDcOFkCM8zF1jC9eQ+mjg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrudeggddufecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpeeuohhrihhsuceuuhhrkhhovhcuoegsohhrihhssegsuhhrrdhi oheqnecuggftrfgrthhtvghrnhepieeuffeuvdeiueejhfehiefgkeevudejjeejffevvd ehtddufeeihfekgeeuheelnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehm rghilhhfrhhomhepsghorhhishessghurhdrihho X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 26 Apr 2022 18:40:23 -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 v9 3/5] btrfs: test btrfs specific fsverity corruption Date: Tue, 26 Apr 2022 15:40:14 -0700 Message-Id: <5fb8fbcf72ad2e7cca0badae1f48c695b3dd8e67.1651012461.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 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 --- tests/btrfs/290 | 168 ++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/290.out | 25 +++++++ 2 files changed, 193 insertions(+) create mode 100755 tests/btrfs/290 create mode 100644 tests/btrfs/290.out 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 Apr 26 22:40:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12828024 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 EF99FC433FE for ; Tue, 26 Apr 2022 22:40:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355910AbiDZWnh (ORCPT ); Tue, 26 Apr 2022 18:43:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49264 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355905AbiDZWng (ORCPT ); Tue, 26 Apr 2022 18:43:36 -0400 Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3C2B815806; Tue, 26 Apr 2022 15:40:26 -0700 (PDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id A1C845C0172; Tue, 26 Apr 2022 18:40:25 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Tue, 26 Apr 2022 18:40:25 -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; t=1651012825; x=1651099225; bh=RY lCIpGr73cUBkgW3S5yoqcSnk4QBZRP3VUSpFtXMmc=; b=EVQLqKyJZnUByoOvz9 u06C1wF4GYGIs0NQ3S1MKyFfHLk6bYzWU/rfWKCzSKN8gSBy9GEc0gIg4Bzg97Tv emBuUQXwOeMHU2yLy5rQ8KATj21/0VSCll750KVPB69zykHM6vQlOUdTzFZ1Th84 bhuBWk5P2UC+CemTj5J9H63r4Vd6jgouVBX4qRoCx/Fvg5O6MnM4hckogH965Y0g UPTbfv2dMeP55NW/yq5UVZhMRXm6bWzbzsQFiTAUhUPFGkjvfFFwgSesOAMp6Js/ nhtSZ7ZuPbjfsTUd8MvdThshAWruVD34hyZXutBCOmCylT6voKnibhaaj7G0aIM0 +vkA== 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=fm1; t= 1651012825; x=1651099225; bh=RYlCIpGr73cUBkgW3S5yoqcSnk4QBZRP3VU SpFtXMmc=; b=ffQiCqKZLadvP/Gn1dN7QKAQWFTXkYDFOsbuZER0UFxna6VELsN 7bLomZgl/Z0k25HtUxEnud5B8BgXnSQ1hYSM4Hq4nqYauEAyKrqMhe4Qd/WPZ4B4 AvEL+VKkJNMBqn47jEKMXOdCPuBAwn2ucSQq8TsrWUiHdzCGuKi0o9LVcbJ2+Ovp apH9glkQUs/640OQK/x4rtB3R4O7NovIDrJmCkMMGi/w79KI8hsRLJwp/JWo0pWL zY89gDAYS6sK2H7y+vZDlGQv3P7+wXYpQEvNP8JiKZ07F5ZgiLxOMMNmShDSmpgz YnxRVNgyVhsVtb7e/e0Yrby3YVuOTJ8XwWQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrudeggddugecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpeeuohhrihhsuceuuhhrkhhovhcuoegsohhrihhssegsuhhrrdhi oheqnecuggftrfgrthhtvghrnhepieeuffeuvdeiueejhfehiefgkeevudejjeejffevvd ehtddufeeihfekgeeuheelnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehm rghilhhfrhhomhepsghorhhishessghurhdrihho X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 26 Apr 2022 18:40:25 -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 v9 4/5] btrfs: test verity orphans with dmlogwrites Date: Tue, 26 Apr 2022 15:40:15 -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 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 Apr 26 22:40:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12828025 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 67BB6C43219 for ; Tue, 26 Apr 2022 22:40:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355915AbiDZWnh (ORCPT ); Tue, 26 Apr 2022 18:43:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49290 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355909AbiDZWng (ORCPT ); Tue, 26 Apr 2022 18:43:36 -0400 Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E2D3314096; Tue, 26 Apr 2022 15:40:27 -0700 (PDT) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 531905C0164; Tue, 26 Apr 2022 18:40:27 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Tue, 26 Apr 2022 18:40:27 -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; t=1651012827; x=1651099227; bh=I+ HxmkzZNhZ0P3kPMHejig53XLe7o7IFnigO5Hnymis=; b=dD5voST/UNPV3LAvqm 9YFkDYbX/aUWFcvPheEKOB9ZesQWvlj58+IiWZRtxd1QaRkQk3JaiHN9PI8Dy+9j eB3RDd1Ftkh97dfpVyWZnFYuK9CYmeAP7LeUmHIqjFz2UuwEyWw1/Jx22QX6WuGC qMtuV7UMyBjN25ZtcWAkrRAvvx+t2pgHPLhTUdf2DhzMqeJPoyDU7MfmPztWwNwj boiQCoPDSIJEgaRKQ2bx2d5Te0AC71+KDZhYOn1qDuwYfGwMaf5KnI1iE4P2qxMb AwDVTdcwghlpPiVh46MyJxTmXQ/lxO0U6kNOoHRyXQ08VGMdPriofvMHEks8p8eq j2Iw== 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=fm1; t= 1651012827; x=1651099227; bh=I+HxmkzZNhZ0P3kPMHejig53XLe7o7IFnig O5Hnymis=; b=LwFgGjVq0k+hb1XkNxidvjbI/g1kz0XShklE4qfDjS8mh38w/pt oHrVmFb7Ba7VfJWgF2+lYXwvf70RTmRKIpH0LakWwHxKQCi9/+vrwkMDEgDcajGh Hrx/GO4OCVzP8H1GA/B2aK9cpdIDpwLb58lmDgJ0MoSEanZApwrtzECHv9VM5PKZ Ngl8F3/psUE8XYHS/oWAafr78nlsPfUjqnPljP+CItLGFIxs/N1mliepHCOyXD9e HqzWHei7AAd0rNOf2derMPLJ3ZLtuCNsxcDPisHmW2c4Qz7lSWdK6DsqpIniBr9Q xJ+PNfz3Z0OnrpWVhhIpQJ8XEHvj7EqbhZg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrudeggddufecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpeeuohhrihhsuceuuhhrkhhovhcuoegsohhrihhssegsuhhrrdhi oheqnecuggftrfgrthhtvghrnhepieeuffeuvdeiueejhfehiefgkeevudejjeejffevvd ehtddufeeihfekgeeuheelnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehm rghilhhfrhhomhepsghorhhishessghurhdrihho X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 26 Apr 2022 18:40:26 -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 v9 5/5] generic: test fs-verity EFBIG scenarios Date: Tue, 26 Apr 2022 15:40:16 -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 8cde2737..657af8aa 100644 --- a/common/verity +++ b/common/verity @@ -347,3 +347,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