public inbox for linux-btrfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Filipe Manana <fdmanana@kernel.org>
To: Boris Burkov <boris@bur.io>
Cc: fstests@vger.kernel.org, linux-btrfs@vger.kernel.org,
	 Filipe Manana <fdmanana@suse.com>
Subject: Re: [PATCH] btrfs: test create a bunch of files with name hash collision
Date: Thu, 5 Mar 2026 17:59:32 +0000	[thread overview]
Message-ID: <CAL3q7H6cR_utsRReNbZLL6x2KgZvLeSaLL8JDuzayOH=hU4jkw@mail.gmail.com> (raw)
In-Reply-To: <20260305175643.GB1172981@zen.localdomain>

On Thu, Mar 5, 2026 at 5:56 PM Boris Burkov <boris@bur.io> wrote:
>
> On Thu, Feb 26, 2026 at 02:34:37PM +0000, fdmanana@kernel.org wrote:
> > From: Filipe Manana <fdmanana@suse.com>
> >
> > Test that if we create a high number of files with a name that results in
> > a hash collision, the filesystem is not turned to RO due to a transaction
> > abort. This could be exploited by malicious users to disrupt a system.
> >
> > This exercies a bug fixed by the following kernel patch:
> >
> >  "btrfs: fix transaction abort on file creation due to name hash collision"
> >
> > Signed-off-by: Filipe Manana <fdmanana@suse.com>
>
> Looks good, thanks. One non-blocking question inline.
>
> Reviewed-by: Boris Burkov <boris@bur.io>
>
> > ---
> >  tests/btrfs/346     | 95 +++++++++++++++++++++++++++++++++++++++++++++
> >  tests/btrfs/346.out |  3 ++
> >  2 files changed, 98 insertions(+)
> >  create mode 100755 tests/btrfs/346
> >  create mode 100644 tests/btrfs/346.out
> >
> > diff --git a/tests/btrfs/346 b/tests/btrfs/346
> > new file mode 100755
> > index 00000000..ef301ef7
> > --- /dev/null
> > +++ b/tests/btrfs/346
> > @@ -0,0 +1,95 @@
> > +#! /bin/bash
> > +# SPDX-License-Identifier: GPL-2.0
> > +# Copyright (c) 2026 SUSE S.A.  All Rights Reserved.
> > +#
> > +# FS QA Test 346
> > +#
> > +# Test that if we create a high number of files with a name that results in a
> > +# hash collision, the filesystem is not turned to RO due to a transaction abort.
> > +# This could be exploited by malicious users to disrupt a system.
> > +#
> > +. ./common/preamble
> > +_begin_fstest auto quick subvol
> > +
> > +_require_scratch
> > +_require_btrfs_support_sectorsize 4096
> > +
> > +_fixed_by_kernel_commit xxxxxxxxxxxx \
> > +     "btrfs: fix transaction abort on file creation due to name hash collision"
> > +
> > +# Use a 4K node/leaf size to make the test faster and require less file names
> > +# that trigger a crc32c hash collision.
> > +_scratch_mkfs -n 4K >> $seqres.full 2>&1 || _fail "mkfs failed"
> > +_scratch_mount
> > +
> > +# List of names that result in the same crc32c hash for btrfs.
>
> How did you generate these? Is it slow/costly?

By brute force. There's btrfs-crc.c in btrfs-progs for that, I
slightly changed it to allow for brute forcing with random lengths
rather than fixed lengths and with more ascii characters ($, _, -,
etc).

> It could be interesting to include a mode to "generate more", in which
> case the test could be generalized to other fileystems directory
> hashing, or to generate more names if needed. With a fixed nodesize and
> btrfs, I don't see a need, though.

That takes a lot of time to generate, that's why I used a hardcoded list.
It took about 4 hours to generate these names, using 12 processes in parallel.

Thanks.

>
> > +declare -a names=(
> > +     'foobar'
> > +     '%a8tYkxfGMLWRGr55QSeQc4PBNH9PCLIvR6jZnkDtUUru1t@RouaUe_L:@xGkbO3nCwvLNYeK9vhE628gss:T$yZjZ5l-Nbd6CbC$M=hqE-ujhJICXyIxBvYrIU9-TDC'
> > +     'AQci3EUB%shMsg-N%frgU:02ByLs=IPJU0OpgiWit5nexSyxZDncY6WB:=zKZuk5Zy0DD$Ua78%MelgBuMqaHGyKsJUFf9s=UW80PcJmKctb46KveLSiUtNmqrMiL9-Y0I_l5Fnam04CGIg=8@U:Z'
> > +     'CvVqJpJzueKcuA$wqwePfyu7VxuWNN3ho$p0zi2H8QFYK$7YlEqOhhb%:hHgjhIjW5vnqWHKNP4'
> > +     'ET:vk@rFU4tsvMB0$C_p=xQHaYZjvoF%-BTc%wkFW8yaDAPcCYoR%x$FH5O:'
> > +     'HwTon%v7SGSP4FE08jBwwiu5aot2CFKXHTeEAa@38fUcNGOWvE@Mz6WBeDH_VooaZ6AgsXPkVGwy9l@@ZbNXabUU9csiWrrOp0MWUdfi$EZ3w9GkIqtz7I_eOsByOkBOO'
> > +     'Ij%2VlFGXSuPvxJGf5UWy6O@1svxGha%b@=%wjkq:CIgE6u7eJOjmQY5qTtxE2Rjbis9@us'
> > +     'KBkjG5%9R8K9sOG8UTnAYjxLNAvBmvV5vz3IiZaPmKuLYO03-6asI9lJ_j4@6Xo$KZicaLWJ3Pv8XEwVeUPMwbHYWwbx0pYvNlGMO9F:ZhHAwyctnGy%_eujl%WPd4U2BI7qooOSr85J-C2V$LfY'
> > +     'NcRfDfuUQ2=zP8K3CCF5dFcpfiOm6mwenShsAb_F%n6GAGC7fT2JFFn:c35X-3aYwoq7jNX5$ZJ6hI3wnZs$7KgGi7wjulffhHNUxAT0fRRLF39vJ@NvaEMxsMO'
> > +     'Oj42AQAEzRoTxa5OuSKIr=A_lwGMy132v4g3Pdq1GvUG9874YseIFQ6QU'
> > +     'Ono7avN5GjC:_6dBJ_'
> > +     'WHmN2gnmaN-9dVDy4aWo:yNGFzz8qsJyJhWEWcud7$QzN2D9R0efIWWEdu5kwWr73NZm4=@CoCDxrrZnRITr-kGtU_cfW2:%2_am'
> > +     'WiFnuTEhAG9FEC6zopQmj-A-$LDQ0T3WULz%ox3UZAPybSV6v1Z$b4L_XBi4M4BMBtJZpz93r9xafpB77r:lbwvitWRyo$odnAUYlYMmU4RvgnNd--e=I5hiEjGLETTtaScWlQp8mYsBovZwM2k'
> > +     'XKyH=OsOAF3p%uziGF_ZVr$ivrvhVgD@1u%5RtrV-gl_vqAwHkK@x7YwlxX3qT6WKKQ%PR56NrUBU2dOAOAdzr2=5nJuKPM-T-$ZpQfCL7phxQbUcb:BZOTPaFExc-qK-gDRCDW2'
> > +     'd3uUR6OFEwZr%ns1XH_@tbxA@cCPmbBRLdyh7p6V45H$P2$F%w0RqrD3M0g8aGvWpoTFMiBdOTJXjD:JF7=h9a_43xBywYAP%r$SPZi%zDg%ql-KvkdUCtF9OLaQlxmd'
> > +     'ePTpbnit%hyNm@WELlpKzNZYOzOTf8EQ$sEfkMy1VOfIUu3coyvIr13-Y7Sv5v-Ivax2Go_GQRFMU1b3362nktT9WOJf3SpT%z8sZmM3gvYQBDgmKI%%RM-G7hyrhgYflOw%z::ZRcv5O:lDCFm'
> > +     'evqk743Y@dvZAiG5J05L_ROFV@$2%rVWJ2%3nxV72-W7$e$-SK3tuSHA2mBt$qloC5jwNx33GmQUjD%akhBPu=VJ5g$xhlZiaFtTrjeeM5x7dt4cHpX0cZkmfImndYzGmvwQG:$euFYmXn$_2rA9mKZ'
> > +     'gkgUtnihWXsZQTEkrMAWIxir09k3t7jk_IK25t1:cy1XWN0GGqC%FrySdcmU7M8MuPO_ppkLw3=Dfr0UuBAL4%GFk2$Ma10V1jDRGJje%Xx9EV2ERaWKtjpwiZwh0gCSJsj5UL7CR8RtW5opCVFKGGy8Cky'
> > +     'hNgsG_8lNRik3PvphqPm0yEH3P%%fYG:kQLY=6O-61Wa6nrV_WVGR6TLB09vHOv%g4VQRP8Gzx7VXUY1qvZyS'
> > +     'isA7JVzN12xCxVPJZ_qoLm-pTBuhjjHMvV7o=F:EaClfYNyFGlsfw-Kf%uxdqW-kwk1sPl2vhbjyHU1A6$hz'
> > +     'kiJ_fgcdZFDiOptjgH5PN9-PSyLO4fbk_:u5_2tz35lV_iXiJ6cx7pwjTtKy-XGaQ5IefmpJ4N_ZqGsqCsKuqOOBgf9LkUdffHet@Wu'
> > +     'lvwtxyhE9:%Q3UxeHiViUyNzJsy:fm38pg_b6s25JvdhOAT=1s0$pG25x=LZ2rlHTszj=gN6M4zHZYr_qrB49i=pA--@WqWLIuX7o1S_SfS@2FSiUZN'
> > +     'rC24cw3UBDZ=5qJBUMs9e$=S4Y94ni%Z8639vnrGp=0Hv4z3dNFL0fBLmQ40=EYIY:Z=SLc@QLMSt2zsss2ZXrP7j4='
> > +     'uwGl2s-fFrf@GqS=DQqq2I0LJSsOmM%xzTjS:lzXguE3wChdMoHYtLRKPvfaPOZF2fER@j53evbKa7R%A7r4%YEkD=kicJe@SFiGtXHbKe4gCgPAYbnVn'
> > +     'UG37U6KKua2bgc:IHzRs7BnB6FD:2Mt5Cc5NdlsW%$1tyvnfz7S27FvNkroXwAW:mBZLA1@qa9WnDbHCDmQmfPMC9z-Eq6QT0jhhPpqyymaD:R02ghwYo%yx7SAaaq-:x33LYpei$5g8DMl3C'
> > +     'y2vjek0FE1PDJC0qpfnN:x8k2wCFZ9xiUF2ege=JnP98R%wxjKkdfEiLWvQzmnW'
> > +     '8-HCSgH5B%K7P8_jaVtQhBXpBk:pE-$P7ts58U0J@iR9YZntMPl7j$s62yAJO@_9eanFPS54b=UTw$94C-t=HLxT8n6o9P=QnIxq-f1=Ne2dvhe6WbjEQtc'
> > +     'YPPh:IFt2mtR6XWSmjHptXL_hbSYu8bMw-JP8@PNyaFkdNFsk$M=xfL6LDKCDM-mSyGA_2MBwZ8Dr4=R1D%7-mCaaKGxb990jzaagRktDTyp'
> > +     '9hD2ApKa_t_7x-a@GCG28kY:7$M@5udI1myQ$x5udtggvagmCQcq9QXWRC5hoB0o-_zHQUqZI5rMcz_kbMgvN5jr63LeYA4Cj-c6F5Ugmx6DgVf@2Jqm%MafecpgooqreJ53P-QTS'
> > +)
> > +
> > +# Now create files with all those names in the same parent directory.
> > +# It should not fail since a 4K leaf has enough space for them.
> > +for name in "${names[@]}"; do
> > +     touch $SCRATCH_MNT/$name
> > +done
> > +
> > +# Now add one more file name that causes a crc32c hash collision.
> > +# This should fail, but it should not cause a transaction abort and turn the
> > +# filesystem into RO mode (which could be exploited by malicious users).
> > +touch $SCRATCH_MNT/'W6tIm-VK2@BGC@IBfcgg6j_p:pxp_QUqtWpGD5Ok_GmijKOJJt' \
> > +      >> $seqres.full 2>&1
> > +[ $? -eq 0 ] && echo "should not have been able to create file"
> > +
> > +# Check that we are able to create another file, with a name that does not cause
> > +# a crc32c hash collision.
> > +echo -n "hello world" > $SCRATCH_MNT/baz
> > +
> > +# Unmount and mount again, verify file baz exists and with the right content.
> > +_scratch_cycle_mount
> > +echo "File baz content: $(cat $SCRATCH_MNT/baz)"
> > +
> > +# Now try to create a subvolume with the same name that causes a hash collision.
> > +# It should fail, but it shouldn't trigger a transaction abort and turns the
> > +# filesystem to RO mode. Subvolume creation takes a different code path.
> > +$BTRFS_UTIL_PROG subvolume create \
> > +     $SCRATCH_MNT/'W6tIm-VK2@BGC@IBfcgg6j_p:pxp_QUqtWpGD5Ok_GmijKOJJt' \
> > +             >> $seqres.full 2>&1
> > +[ $? -eq 0 ] && echo "should not have been able to subvolume"
> > +
> > +# Check that we are able to create another file, with a name that does not cause
> > +# a crc32c hash collision.
> > +echo -n "yada yada" > $SCRATCH_MNT/xyz
> > +
> > +# Unmount and mount again, verify file xyz exists and with the right content.
> > +_scratch_cycle_mount
> > +echo "File xyz content: $(cat $SCRATCH_MNT/xyz)"
> > +
> > +_exit 0
> > diff --git a/tests/btrfs/346.out b/tests/btrfs/346.out
> > new file mode 100644
> > index 00000000..e1b82cbd
> > --- /dev/null
> > +++ b/tests/btrfs/346.out
> > @@ -0,0 +1,3 @@
> > +QA output created by 346
> > +File baz content: hello world
> > +File xyz content: yada yada
> > --
> > 2.47.2
> >

  reply	other threads:[~2026-03-05 18:00 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-26 14:34 [PATCH] btrfs: test create a bunch of files with name hash collision fdmanana
2026-03-05 17:56 ` Boris Burkov
2026-03-05 17:59   ` Filipe Manana [this message]
2026-03-06 14:35 ` Christoph Hellwig
2026-03-06 14:55   ` Filipe Manana
2026-03-10 13:13     ` Christoph Hellwig
2026-03-10 13:40       ` Filipe Manana
2026-03-10 10:29 ` Daniel Vacek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAL3q7H6cR_utsRReNbZLL6x2KgZvLeSaLL8JDuzayOH=hU4jkw@mail.gmail.com' \
    --to=fdmanana@kernel.org \
    --cc=boris@bur.io \
    --cc=fdmanana@suse.com \
    --cc=fstests@vger.kernel.org \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox