All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dave Chinner <david@fromorbit.com>
To: "hubert ." <hubjin657@outlook.com>
Cc: Carlos Maiolino <cem@kernel.org>,
	"linux-xfs@vger.kernel.org" <linux-xfs@vger.kernel.org>
Subject: Re: xfs_metadump segmentation fault on large fs - xfsprogs 6.1
Date: Fri, 26 Sep 2025 19:39:18 +1000	[thread overview]
Message-ID: <aNZfRuIVgIOiP6Qp@dread.disaster.area> (raw)
In-Reply-To: <IA0PR05MB99755ED06F9965745B20D9DAFA1EA@IA0PR05MB9975.namprd05.prod.outlook.com>

On Fri, Sep 26, 2025 at 09:04:12AM +0000, hubert . wrote:
> >> Regarding the xfs_metadump segfault, yes, a core might be useful to
> >> investigate where the segfault is triggered, but you'll need to be
> >> running xfsprogs from the upstream tree (preferentially latest code), so
> >> we can actually match the core information the code.
> >
> > I figured it was not all the needed info, thanks for clarifying.
> >
> > Right now we had to put away the original hdds, as we cannot afford
> > another failed drive and time is pressing, and are dd'ing the image to a
> > real partition to try xfs_repair on it directly (takes days, of course,
> > but we're lucky we got the storage).
> > I will try the metadump and do further debugging if it segfaults again.
> 
> So I'm back now with a real partition. 
> First, I ran "xfs_repair -vn" and it did complete, reporting - as expected - a 
> bunch of entries to junk, skipping the last phases with "Inode allocation 
> btrees are too corrupted, skipping phases 6 and 7".
> It created a 270MB log, I can upload it somewhere if it could be of interest.

No need, but thanks for the offer.

> Core was generated by `/usr/sbin/xfs_db -i -p xfs_metadump -c metadump /dev/sda1'.
> Program terminated with signal SIGSEGV, Segmentation fault.
> #0  libxfs_bmbt_disk_get_all (rec=0x55c47aec3eb0, irec=<synthetic pointer>) at ../include/libxfs.h:226
> 
> warning: 226	../include/libxfs.h: No such file or directory
> (gdb) bt full
> #0  libxfs_bmbt_disk_get_all (rec=0x55c47aec3eb0, irec=<synthetic pointer>) at ../include/libxfs.h:226
>         l0 = <optimized out>
>         l1 = <optimized out>
>         l0 = <optimized out>
>         l1 = <optimized out>

Ok, so it's faulted when trying to read a BMBT record from an
in-memory buffer...

Remember the addr of the rec (0x55c47aec3eb0) now....

> #1  convert_extent (rp=0x55c47aec3eb0, op=<synthetic pointer>, sp=<synthetic pointer>, cp=<synthetic pointer>, fp=<synthetic pointer>) at /build/reproducible-path/xfsprogs-6.16.0/db/bmap.c:320
>         irec = <optimized out>
>         irec = <optimized out>
> #2  process_bmbt_reclist (dip=dip@entry=0x55c37aec3e00, whichfork=whichfork@entry=0, rp=0x55c37aec3eb0, numrecs=numrecs@entry=268435457) at /build/reproducible-path/xfsprogs-6.16.0/db/metadump.c:2181

Smoking gun:

numrecs=numrecs@entry=268435457

268435457 = 2^28 + 1

>         is_meta = false
>         btype = <optimized out>
>         i = <optimized out>
>         o = <optimized out>
>         op = <optimized out>
>         s = <optimized out>
>         c = <optimized out>
>         cp = <optimized out>
>         f = <optimized out>
>         last = <optimized out>
>         agno = <optimized out>
>         agbno = <optimized out>
>         rval = <optimized out>
> #3  0x000055c36404e042 in process_exinode (dip=0x55c37aec3e00, whichfork=0) at /build/reproducible-path/xfsprogs-6.16.0/db/metadump.c:2421
>         max_nex = <optimized out>
>         nex = 268435457

Yup, that's the problem.

The inode is in extent format, which means the extent records are in
the inode data fork area, which is about 300 bytes max for a 512
byte inode. IOWs, it can hold about 12 BMBT records. The BMBT
records are in the on-disk inode buffer, as is the disk inode @dip.

Look at the address of dip:  0x55c37aec3e00
The address of the BMBT rec: 0x55c47aec3eb0

Now lok at what BMBT record convert_extent() is trying to access:

process_bmbt_reclist()
{
.....
	convert_extent(&rp[numrecs - 1], &o, &s, &c, &f);
.....

Yeah, that inode buffer isn't 268 million bmbt recrods long....

So there must be a bounds checking bug in process_exinode():

static int
process_exinode(
        struct xfs_dinode       *dip,
        int                     whichfork)
{
        xfs_extnum_t            max_nex = xfs_iext_max_nextents(
                        xfs_dinode_has_large_extent_counts(dip), whichfork);
        xfs_extnum_t            nex = xfs_dfork_nextents(dip, whichfork);
        int                     used = nex * sizeof(struct xfs_bmbt_rec);

        if (nex > max_nex || used > XFS_DFORK_SIZE(dip, mp, whichfork)) {
                if (metadump.show_warnings)
                        print_warning("bad number of extents %llu in inode %lld",
                                (unsigned long long)nex,
                                (long long)metadump.cur_ino);
                return 1;
        }

Can you spot it?

Hint: ((2^28 + 1) * 2^4) - 1 as an int is?

-Dave.
-- 
Dave Chinner
david@fromorbit.com

  reply	other threads:[~2025-09-26  9:39 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <f9Etb2La9b1KOT-5VdCdf6cd10olyT-FsRb8AZh8HNI1D4Czb610tw4BE15cNrEhY5OiXDGS7xR6R1trRyn1LA==@protonmail.internalid>
2025-07-25 11:27 ` xfs_metadump segmentation fault on large fs - xfsprogs 6.1 hubert .
2025-07-26  3:51   ` Carlos Maiolino
2025-08-01 13:51     ` hubert .
2025-08-18 15:56       ` hubert .
2025-08-25  7:51         ` Carlos Maiolino
2025-08-27 10:51           ` hubert .
2025-09-26  9:04             ` hubert .
2025-09-26  9:39               ` Dave Chinner [this message]
2025-09-26 13:45                 ` Carlos Maiolino
2025-09-27 23:22                   ` Dave Chinner
2025-09-28  6:11                     ` Carlos Maiolino
2025-09-30  9:22                       ` Dave Chinner
2025-11-03  9:23                         ` hubert .
2025-11-03 10:18                           ` Carlos Maiolino

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=aNZfRuIVgIOiP6Qp@dread.disaster.area \
    --to=david@fromorbit.com \
    --cc=cem@kernel.org \
    --cc=hubjin657@outlook.com \
    --cc=linux-xfs@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.