From patchwork Mon Jul 18 23:58:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12921881 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 8C8B9C433EF for ; Mon, 18 Jul 2022 23:59:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230369AbiGRX7X (ORCPT ); Mon, 18 Jul 2022 19:59:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34066 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236271AbiGRX6t (ORCPT ); Mon, 18 Jul 2022 19:58:49 -0400 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C305633E32; Mon, 18 Jul 2022 16:58:37 -0700 (PDT) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id B9CE35C0136; Mon, 18 Jul 2022 19:58:36 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 18 Jul 2022 19:58:36 -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=fm3; t=1658188716; x=1658275116; bh=2s f0/qhtYUFQefEjNOYr1zz/jjRB8K8ODeUOsWiRJsQ=; b=GpfElRbvztBBzx3exA n7K2M3iq7VJiRTVP112/Ndr0Ba59kvzXjSV08f3awQLstY++baFAyOvMrMIWk0M3 72XkHi6Q6iOvIkZY8Vv00GIQc7c0vqTfsdsurVpNfAxeBhjGNfkgFFBmTJoAc6dJ BM1qjKWZ4hvW5UsOFsquqNURLP2Zx99Dg7u6NTh3JCeBYSmG23NcdVaQJPxo9cwB nR5JFphLoLofAr94yUQe74ww3Iad4nLqoizlI+UkQ1yx/TeKTSmcCet8heR8Ztv7 E2vocvUEq2Elp3vCclTUg0nUe8LO0u2Eeb+yvhvA2OUOjzDznqZhfIPvNy9C886H rUhA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:date :feedback-id:feedback-id: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; t=1658188716; x=1658275116; bh=2sf0/qhtYUFQe fEjNOYr1zz/jjRB8K8ODeUOsWiRJsQ=; b=WtJSojBfrGv0FnT3SkhvGOx7VwoqO 54ALmEY3obJgcdBcbFsBvYkEJlRUxmfXkpXHXalJLLTGy7UMPDYwxbrNDCBxi91B lDCLRDIGeoAoT4kTVIpPlqCFTQ7WVu+vl2HmBniS6mHLtKdaYwyKg7bAu384uu5Z Y0QhvzSad8FSR+2ml2/VwryK9dNO4ye9troiN7V+H8PgxHwob46CLRoQ7xH+n1Y5 GTen45jLB41yVAlbUSs1wVN4itxYam8l8D1zyVWnqW2rawqjadxdo4ZvQsdbTqxi NVCsYQkZkGnAm1LfeVHgKlX81Pb8IlG9l1k8UwcapMKS5G9K3ayPP//Vg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrudekledgvdelucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepuehorhhishcuuehurhhkohhvuceosghorhhishessghurhdr ihhoqeenucggtffrrghtthgvrhhnpeeiueffuedvieeujefhheeigfekvedujeejjeffve dvhedtudefiefhkeegueehleenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhep mhgrihhlfhhrohhmpegsohhrihhssegsuhhrrdhioh X-ME-Proxy: Feedback-ID: i083147f8:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 18 Jul 2022 19:58:36 -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 v12 1/5] common/verity: require corruption functionality Date: Mon, 18 Jul 2022 16:58:29 -0700 Message-Id: <8a0a68f0729b66fceb43e2638305fc85ace58702.1658188603.git.boris@bur.io> X-Mailer: git-send-email 2.37.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: fstests@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 3ef04953..c8862de2 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 Mon Jul 18 23:58:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12921885 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 3C767CCA485 for ; Tue, 19 Jul 2022 00:01:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236005AbiGSABC (ORCPT ); Mon, 18 Jul 2022 20:01:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34118 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235613AbiGRX6u (ORCPT ); Mon, 18 Jul 2022 19:58:50 -0400 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C6CED33A32; Mon, 18 Jul 2022 16:58:39 -0700 (PDT) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 71A4C5C0144; Mon, 18 Jul 2022 19:58:38 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Mon, 18 Jul 2022 19:58:38 -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=fm3; t=1658188718; x=1658275118; bh=2m MBqFCNMwj9UJE5HtzaC9bHoY8WfX+Y4yXIwJvAldM=; b=bbycJ/kYLd0mwix1H2 VJ7TM/vxQ+EuyU2+5tOH//CbC4endftRwEL/WqtBJJEaWiUFr3FkYT5dD9KXazhr 1NYjBqBQtGizSk/ZNM7G3PwvWXprSH2twH673lD0IKJzJ8QJbApm7eLYPYadDUWS kLVIF0lQXajaNtJ70sjlDf2tTcujteGoioXFBStmIahDESWHFJABFrsjP6TRCs1Q DZsVMhKmhNwzmJWZU9JpzgtBiLKJ6JcTJUDifYvlq321KJhDnX9TrO5XKc2VmyVQ cSe8vC0mmzNSSOTI98pX+nbY/n5T67+EzripIBMItWCDrBR/pG/yve1OIcP9WqPQ Hp+A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:date :feedback-id:feedback-id: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; t=1658188718; x=1658275118; bh=2mMBqFCNMwj9U JE5HtzaC9bHoY8WfX+Y4yXIwJvAldM=; b=qehE1V9VS8mEONeBLo37KMh5LkDYv 8U2oF5X/EBmi3389fcx7dfGUG4LubgTcJZBebcsG3QfyAVgAOpZSRTCR6GPC4CnQ Z9LT0L6RJTigV2dPse4Sr36F35wjrq2+kP+eGWWuExziaA5pmcrlya31DHdVsiZJ 5wpbiimjthR+hCDjuxHv/a0KUWLMs7zqKjB+M7FbpxpXYMBjntzShV8ESWeM5niM NWw4yKuDP/bbe5K1FRwps2x6b+Xk72ppIvO+2tlk6vU/SgCVjU8Aqcikdz7F/xnd Je8T9jm4lzmEB4a+I3tC77PwrSlM86pq5R410PHl1S0j6PkWemsqDiEhg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrudekledgvdekucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepuehorhhishcuuehurhhkohhvuceosghorhhishessghurhdr ihhoqeenucggtffrrghtthgvrhhnpeeiueffuedvieeujefhheeigfekvedujeejjeffve dvhedtudefiefhkeegueehleenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhep mhgrihhlfhhrohhmpegsohhrihhssegsuhhrrdhioh X-ME-Proxy: Feedback-ID: i083147f8:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 18 Jul 2022 19:58:37 -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 v12 2/5] common/verity: support btrfs in generic fsverity tests Date: Mon, 18 Jul 2022 16:58:30 -0700 Message-Id: X-Mailer: git-send-email 2.37.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: fstests@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 --- common/btrfs | 5 +++++ common/config | 1 + common/verity | 31 +++++++++++++++++++++++++++++++ tests/generic/574 | 37 ++++++++++++++++++++++++++++++++++--- tests/generic/574.out | 13 ++++--------- 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/common/btrfs b/common/btrfs index 14ad890e..bd2639bf 100644 --- a/common/btrfs +++ b/common/btrfs @@ -580,3 +580,8 @@ _btrfs_buffered_read_on_mirror() : done } + +_require_btrfs_corrupt_block() +{ + _require_command "$BTRFS_CORRUPT_BLOCK_PROG" btrfs-corrupt-block +} diff --git a/common/config b/common/config index de3aba15..c30eec6d 100644 --- a/common/config +++ b/common/config @@ -297,6 +297,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..7d61511c 100644 --- a/common/verity +++ b/common/verity @@ -3,6 +3,16 @@ # # Functions for setting up and testing fs-verity +# btrfs will return IO errors on corrupted data with or without fs-verity. +# to really test fs-verity, use nodatasum. +if [ "$FSTYP" == "btrfs" ]; then + if [ -z $MOUNT_OPTIONS ]; then + export MOUNT_OPTIONS="-o nodatasum" + else + export MOUNT_OPTIONS+=" -o nodatasum" + fi +fi + _require_scratch_verity() { _require_scratch @@ -145,6 +155,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 +166,9 @@ _scratch_mkfs_verity() ext4|f2fs) _scratch_mkfs -O verity ;; + btrfs) + _scratch_mkfs + ;; *) _notrun "No verity support for $FSTYP" ;; @@ -314,6 +330,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..5ba4be7e 100755 --- a/tests/generic/574 +++ b/tests/generic/574 @@ -126,6 +126,39 @@ corruption_test() fi } +# Reading the last block of the file with mmap is tricky, so we need to be +# a bit careful. Some filesystems read the last block in full, while others +# return zeros in the last block past EOF, regardless of the contents on +# disk. In the former, corruption should be detected and result in SIGBUS, +# while in the latter we would expect zeros past EOF, but no error. +corrupt_eof_block_test() { + local file_len=$1 + local zap_len=$2 + local page_aligned_eof=$(round_up_to_page_boundary $file_len) + _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 \ + | _fsv_scratch_corrupt_bytes $fsv_file $file_len + + echo "Reading eof block via mmap into a temporary file..." + bash -c "trap '' SIGBUS; $XFS_IO_PROG -r $fsv_file \ + -c 'mmap -r 0 $page_aligned_eof' \ + -c 'mread -v $file_len $zap_len'" \ + |& filter_sigbus >$tmp.eof_block_read 2>&1 + + head -c $file_len /dev/zero > $tmp.zero_cmp_file + $XFS_IO_PROG -r $tmp.zero_cmp_file \ + -c "mmap -r 0 $page_aligned_eof" \ + -c "mread -v $file_len $zap_len" >$tmp.eof_zero_read + + echo "Checking for SIGBUS or zeros..." + <$tmp.eof_block_read grep -q -e '^Bus error$' \ + || diff $tmp.eof_block_read $tmp.eof_zero_read \ + && echo "OK" +} + # 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 @@ -136,9 +169,7 @@ corruption_test 131072 4091 5 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 +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..d40d1263 100644 --- a/tests/generic/574.out +++ b/tests/generic/574.out @@ -56,17 +56,12 @@ 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 +Reading eof block via mmap into a temporary file... +Checking for SIGBUS or zeros... +OK # Corruption test: file_len=200000 zap_offset=100 (in Merkle tree) zap_len=10 4a1e4325031b13f933ac4f1db9ecb63f SCRATCH_MNT/file.fsv From patchwork Mon Jul 18 23:58:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12921882 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 AFC6ECCA486 for ; Mon, 18 Jul 2022 23:59:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235547AbiGRX7Y (ORCPT ); Mon, 18 Jul 2022 19:59:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35532 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235864AbiGRX6y (ORCPT ); Mon, 18 Jul 2022 19:58:54 -0400 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 63D56357D5; Mon, 18 Jul 2022 16:58:41 -0700 (PDT) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.nyi.internal (Postfix) with ESMTP id 215695C014F; Mon, 18 Jul 2022 19:58:40 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Mon, 18 Jul 2022 19:58:40 -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=fm3; t=1658188720; x=1658275120; bh=lz 41RhC44hJZSB8wBNhpeduk4A1cB9xHfyPqzM1f0m8=; b=W//2ukW23Jr+8x9ubH wRy8/FFpkfjGlw+hlm8HANOTUnnkoY9VC7govmWu3lVRzl8TR51XrrEFqlDgk3qb nxI8YdUgZ9lKrUt+2STDEQTuEeeRu7lP4Mmm39P6frF9KlqJToyIx3BwAb9gUoLQ 2mDyxwgA3jxipsTpO+Qw+6kcmAjxdmpXXAQsjcrn3ZVmidTAEdixzebLg2QAdPTq 6WmgcVfTbDqg8EUnmCzso2CgjdBK+Kw12oHav17RzaWq/6sUF1rte/kxmRr67oed T9zckE8WtB6qY414e0d32dYb2ZVBGiB1n4jUWwvgLz3AP4P1haAabMiQwYr1/qwX Vzrg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:date :feedback-id:feedback-id: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; t=1658188720; x=1658275120; bh=lz41RhC44hJZS B8wBNhpeduk4A1cB9xHfyPqzM1f0m8=; b=WVl5n53QOrxLYliW5xlPW1pmYox1y In7qNaeUkuA7NU2LlriqxSGvpdpdjJfkwkIPiS4MXRr6X+u8VKYeUGOqZ1UqGN4Q ozl1RvULFkk7Zl+tQE0ZdR3rcLSiy5NbLPanRiGgHwyx9q5othvg6c5B8A4nNHy7 yO0dX+PcEHDZTZeqXvow/twFq/s+g7TnuERjkp7NLmd99itpBbaEugusl4Vo9ALN ofPIj5bhiU62NEkr7M+Fwl6++AXMkEUoibVzEZFaa9am9VyQMvwFSDprm63YLxLM Hu9eBSYfJ0DSHcESIWU2zpcAJ7gJTsSbUnFx12tdnNWEmu7sTtfs9iUbA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrudekledgvdekucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepuehorhhishcuuehurhhkohhvuceosghorhhishessghurhdr ihhoqeenucggtffrrghtthgvrhhnpeeiueffuedvieeujefhheeigfekvedujeejjeffve dvhedtudefiefhkeegueehleenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhep mhgrihhlfhhrohhmpegsohhrihhssegsuhhrrdhioh X-ME-Proxy: Feedback-ID: i083147f8:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 18 Jul 2022 19:58:39 -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 v12 3/5] btrfs: test btrfs specific fsverity corruption Date: Mon, 18 Jul 2022 16:58:31 -0700 Message-Id: X-Mailer: git-send-email 2.37.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: fstests@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 | 172 ++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/290.out | 25 +++++++ 2 files changed, 197 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..b7254c5e --- /dev/null +++ b/tests/btrfs/290 @@ -0,0 +1,172 @@ +#! /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 + # ensure non-zero at the pre-allocated region on disk + # 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 + # now that it's a regular file, reading actually looks at the previously + # preallocated region, so ensure that has non-zero contents. + head -c 5 /dev/zero | tr '\0' X | _fsv_scratch_corrupt_bytes $f 0 + 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 Mon Jul 18 23:58:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12921883 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 5236FCCA488 for ; Mon, 18 Jul 2022 23:59:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235706AbiGRX7Z (ORCPT ); Mon, 18 Jul 2022 19:59:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35884 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235843AbiGRX7D (ORCPT ); Mon, 18 Jul 2022 19:59:03 -0400 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5ABD733E0F; Mon, 18 Jul 2022 16:58:42 -0700 (PDT) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id B95E35C014D; Mon, 18 Jul 2022 19:58:41 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Mon, 18 Jul 2022 19:58:41 -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=fm3; t=1658188721; x=1658275121; bh=rk LMXNuWE2W/uc6hezIxybG+Bv4sAU9qCC7tfw/E6i4=; b=XyhYQ2/5sNBOI9mYxx blkyL2bKWvCpEDscQwRPMmNTXUEW13xHpoCRn3fzlRz5IZwFMxWi9s+97AUXVzQo LMemmTRFU/rnXsIcvBVnVLjTk62B04RD/7kDSupCU20RxIv60ZVMK7t8yywRiAQp 3QD2TdJ8GEIJz9hoRRmdMbfnEUslkJyyxJZsFpM//RFxeojTo7KgwNRKBoioL+3c Dz+L2AopaAHMG0FI2tEVzMmdXBfNvnNm8c76xUhR+t77fpux/4DfVGjCitEs8Kad Q+FRMipeVgwi9/97K1mP+grvvau1aYHitsU7mqUTOfF/Ye/oHMu1vc3OeKXakvWI nNCA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:date :feedback-id:feedback-id: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; t=1658188721; x=1658275121; bh=rkLMXNuWE2W/u c6hezIxybG+Bv4sAU9qCC7tfw/E6i4=; b=qjSwvMFQ+BC/JpM4YqosnYpqJm8Rc gn86eZOV5gUDIxtlXLaqSBl7k6VREtjzNTA3sCK8awUefnRoDGbSnnuCrSowZM1g 2E+vLykz84zWe54nK9EbWVmTT+VsKpDKZHACHBURz0PVFMgi+9ILQbsyvaFo68wC 1nO5/L84kksPiILdlCdxUnHydMzrhSNj23c8aKRZtbPZ/Uuwjn50aPYdALUJX1Nh z0CvXOCJdRn656ZZlfHg5M7iC6z70Yu9lmBXv6wSj8gCypvEQ9gKCQZu94uySapF ABeGLEilSU7ec2OJanVEQ5vmP6TBPtMDeLGUd8DOuEMZaWJuGZJIDE5bg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrudekledgvdekucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepuehorhhishcuuehurhhkohhvuceosghorhhishessghurhdr ihhoqeenucggtffrrghtthgvrhhnpeeiueffuedvieeujefhheeigfekvedujeejjeffve dvhedtudefiefhkeegueehleenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhep mhgrihhlfhhrohhmpegsohhrihhssegsuhhrrdhioh X-ME-Proxy: Feedback-ID: i083147f8:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 18 Jul 2022 19:58:41 -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 v12 4/5] btrfs: test verity orphans with dmlogwrites Date: Mon, 18 Jul 2022 16:58:32 -0700 Message-Id: <73cfa9631ed78ce99c20bcc09114ac28e9ff2148.1658188603.git.boris@bur.io> X-Mailer: git-send-email 2.37.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: fstests@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. As we replay the log events, we run a state machine with different invariants enforced at each state. There are three possible states for a given point in the log: 0. Verity has not yet started 1. Verity has started but not finished 2. Verity has finished. The possible transitions with causes are: 0->1: We see an orphan item for the file. 1->2: Running 'fsverity measure' succeeds on the file. Each state has its own invariant for testing: 0: No verity items exist. 1: Mount should handle the orphan and blow away verity data: expect 0 Merkle items after mounting. 2: The orphan should be gone and mount should not blow away merkle items. Expect the same number of merkle items before and after mounting. As a result, we can be confident that if the file system loses power at any point during enabling verity on a file, the work is either completed, or gets rolled-back by mount. Signed-off-by: Boris Burkov --- tests/btrfs/291 | 167 ++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/291.out | 2 + 2 files changed, 169 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..97cb78c7 --- /dev/null +++ b/tests/btrfs/291 @@ -0,0 +1,167 @@ +#! /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_loop +_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" +} + +count_merkle_items() { + local dev=$1 + local count_old=$(count_item $dev 'UNKNOWN.3[67]') + local count_new=$(count_item $dev 'VERITY_\(DESC\|MERKLE\)_ITEM') + echo $((count_old + count_new)) +} + +_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) + [ $state -eq 0 ] && [ $orphan -gt 0 ] && state=1 + + pre_mount=$(count_merkle_items $snap_dev) + _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_merkle_items $snap_dev) + + 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 Mon Jul 18 23:58:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Burkov X-Patchwork-Id: 12921884 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 E54E2CCA485 for ; Mon, 18 Jul 2022 23:59:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235784AbiGRX70 (ORCPT ); Mon, 18 Jul 2022 19:59:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34746 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236463AbiGRX7I (ORCPT ); Mon, 18 Jul 2022 19:59:08 -0400 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B926E33A1D; Mon, 18 Jul 2022 16:58:44 -0700 (PDT) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id BB2395C00C5; Mon, 18 Jul 2022 19:58:43 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Mon, 18 Jul 2022 19:58:43 -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=fm3; t=1658188723; x=1658275123; bh=qy 7N1GyHcvwMceOhY4MUI5S8Z6Lx7/pKZC1pdl3g7J0=; b=c9E2rEzpaKRTGh6hw2 HXVevhm8R6auLAnzy51YD9veW6ck2zOWWN+b02w3myq663oIhsEVMUw10v39limd /wbEIQnwPVVuV5ag91Gm1bc5/ABUQS5be7+l3Y9F4WBxV1As0q4nclLzEkinGnX3 npbk/yPuLrkms6Oy816IJwzE3z8YdT9klJj1EZLJ2+ILrrjQuFX4X4IwUm71gXaQ srvGdjvDe43cvjTCQSw5hyEEipZLUsFeyoygYUZwjXdD1KBLxcCHtDIw7GQaQPWj qbiKn7Q2f4m2S+E92ShS6LRL5bEzU4ej66AWUQ4x13OuKTfyb41KHMom8mdScZaU ehWg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:date :feedback-id:feedback-id: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; t=1658188723; x=1658275123; bh=qy7N1GyHcvwMc eOhY4MUI5S8Z6Lx7/pKZC1pdl3g7J0=; b=IWXM5a7bdaKyBTpC/kLvJ8FDQ8udx Ohr2wYy9oDalpCGBFCn3T+vvdOZw56p5xFVVLHVWZBJfEcCyFhK+2olwpwZmL9aU qYlIyLG/c9vTgrs/3EfFYmTjObG3azlCeqEXfbJg8Kdxxfcxy04Ax/dF3Fe45gWq YCl8bTAje5CpH2J/OX+hSJrvuQzoZ9OYjcQ12fdTPl9H8saIl30eweXzmlfyGv1l VnEzA+9chxPVC4i3gX+X55SWTeHbteQxDJ8GHfIwCo1SNFcnK9ICvAIDSeZMPYD/ 5q/W/4hS4IgOXn6YRc735HHtW/Vp0J/Y6PKWk2dyOW1Hj6Ah6s/edEAxQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrudekledgvdelucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepuehorhhishcuuehurhhkohhvuceosghorhhishessghurhdr ihhoqeenucggtffrrghtthgvrhhnpeeiueffuedvieeujefhheeigfekvedujeejjeffve dvhedtudefiefhkeegueehleenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhep mhgrihhlfhhrohhmpegsohhrihhssegsuhhrrdhioh X-ME-Proxy: Feedback-ID: i083147f8:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 18 Jul 2022 19:58:43 -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 v12 5/5] generic: test fs-verity EFBIG scenarios Date: Mon, 18 Jul 2022 16:58:33 -0700 Message-Id: X-Mailer: git-send-email 2.37.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: fstests@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/692 | 64 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/692.out | 7 +++++ 3 files changed, 82 insertions(+) create mode 100644 tests/generic/692 create mode 100644 tests/generic/692.out diff --git a/common/verity b/common/verity index 7d61511c..cb7fa333 100644 --- a/common/verity +++ b/common/verity @@ -350,3 +350,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/692 b/tests/generic/692 new file mode 100644 index 00000000..0bb1fd33 --- /dev/null +++ b/tests/generic/692 @@ -0,0 +1,64 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2022 Meta, Inc. All Rights Reserved. +# +# FS QA Test 692 +# +# 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/692.out b/tests/generic/692.out new file mode 100644 index 00000000..05996713 --- /dev/null +++ b/tests/generic/692.out @@ -0,0 +1,7 @@ +QA output created by 692 + +# 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