diff --git a/SOURCES/0001-xfsdump-Revert-xfsdump-handle-bind-mount-targets.patch b/SOURCES/0001-xfsdump-Revert-xfsdump-handle-bind-mount-targets.patch new file mode 100644 index 0000000..2a2656f --- /dev/null +++ b/SOURCES/0001-xfsdump-Revert-xfsdump-handle-bind-mount-targets.patch @@ -0,0 +1,66 @@ +From 3b71c7f1f5a1dd45712d7de1139290d0a8cf03c4 Mon Sep 17 00:00:00 2001 +From: Gao Xiang +Date: Thu, 3 Feb 2022 12:42:30 -0500 +Subject: [PATCH 1/2] xfsdump: Revert "xfsdump: handle bind mount targets" + +Bind mount mntpnts will be forbided in the next commits +instead since it's not the real rootdir. + +This cannot be reverted cleanly due to several cleanup +patches, but the logic is reverted equivalently. + +This reverts commit 25195ebf107dc81b1b7cea1476764950e1d6cc9d. + +Fixes: 25195ebf107d ("xfsdump: handle bind mount targets") +Cc: Eric Sandeen +Signed-off-by: Gao Xiang +Reviewed-by: Eric Sandeen +Signed-off-by: Eric Sandeen +--- + +Index: xfsdump-3.1.8/dump/content.c +=================================================================== +--- xfsdump-3.1.8.orig/dump/content.c ++++ xfsdump-3.1.8/dump/content.c +@@ -1382,17 +1382,11 @@ baseuuidbypass: + } + + /* figure out the ino for the root directory of the fs +- * and get its xfs_bstat_t for inomap_build(). This could +- * be a bind mount; don't ask for the mount point inode, +- * find the actual lowest inode number in the filesystem. ++ * and get its xfs_bstat_t for inomap_build() + */ + { + stat64_t rootstat; +- xfs_ino_t lastino = 0; +- int ocount = 0; +- xfs_fsop_bulkreq_t bulkreq; + +- /* Get the inode of the mount point */ + rval = fstat64( sc_fsfd, &rootstat ); + if ( rval ) { + mlog( MLOG_NORMAL, _( +@@ -1404,21 +1398,11 @@ baseuuidbypass: + ( xfs_bstat_t * )calloc( 1, sizeof( xfs_bstat_t )); + assert( sc_rootxfsstatp ); + +- /* Get the first valid (i.e. root) inode in this fs */ +- bulkreq.lastip = (__u64 *)&lastino; +- bulkreq.icount = 1; +- bulkreq.ubuffer = sc_rootxfsstatp; +- bulkreq.ocount = &ocount; +- if (ioctl(sc_fsfd, XFS_IOC_FSBULKSTAT, &bulkreq) < 0) { ++ if (bigstat_one(sc_fsfd, rootstat.st_ino, sc_rootxfsstatp) < 0) { + mlog( MLOG_ERROR, + _("failed to get bulkstat information for root inode\n")); + return BOOL_FALSE; + } +- +- if (sc_rootxfsstatp->bs_ino != rootstat.st_ino) +- mlog ( MLOG_NORMAL | MLOG_NOTE, +- _("root ino %lld differs from mount dir ino %lld, bind mount?\n"), +- sc_rootxfsstatp->bs_ino, rootstat.st_ino); + } + + /* alloc a file system handle, to be used with the jdm_open() diff --git a/SOURCES/0002-xfsdump-intercept-bind-mount-targets.patch b/SOURCES/0002-xfsdump-intercept-bind-mount-targets.patch new file mode 100644 index 0000000..90eb495 --- /dev/null +++ b/SOURCES/0002-xfsdump-intercept-bind-mount-targets.patch @@ -0,0 +1,100 @@ +From 0717c1cdfeaedc98df8af97b5ab110830e176a5b Mon Sep 17 00:00:00 2001 +From: Gao Xiang +Date: Thu, 3 Feb 2022 12:42:30 -0500 +Subject: [PATCH 2/2] xfsdump: intercept bind mount targets + +It's a bit strange pointing at some non-root bind mount target and +then actually dumping from the actual root dir instead. + +Therefore, instead of searching for the root dir of the filesystem, +just intercept all bind mount targets by checking whose ino # of +".." is itself with getdents. + +Fixes: 25195ebf107d ("xfsdump: handle bind mount targets") +Cc: Eric Sandeen +Signed-off-by: Gao Xiang +[sandeen: add explanatory comment to new function] +Reviewed-by: Eric Sandeen +Signed-off-by: Eric Sandeen +--- + +Index: xfsdump-3.1.8/dump/content.c +=================================================================== +--- xfsdump-3.1.8.orig/dump/content.c ++++ xfsdump-3.1.8/dump/content.c +@@ -511,6 +511,60 @@ static bool_t create_inv_session( + ix_t subtreecnt, + size_t strmix); + ++/* ++ * Verify that we are asked to dump from the root of the filesystem; ++ * test this by checking whether the inode number we've been given matches ++ * the inode number for this directory's ".." ++ */ ++static bool_t ++check_rootdir(int fd, ++ xfs_ino_t ino) ++{ ++ struct dirent *gdp; ++ size_t gdsz; ++ bool_t found = BOOL_FALSE; ++ ++ gdsz = sizeof(struct dirent) + NAME_MAX + 1; ++ if (gdsz < GETDENTSBUF_SZ_MIN) ++ gdsz = GETDENTSBUF_SZ_MIN; ++ gdp = (struct dirent *)calloc(1, gdsz); ++ assert(gdp); ++ ++ while (1) { ++ struct dirent *p; ++ int nread; ++ ++ nread = getdents_wrap(fd, (char *)gdp, gdsz); ++ /* ++ * negative count indicates something very bad happened; ++ * try to gracefully end this dir. ++ */ ++ if (nread < 0) { ++ mlog(MLOG_NORMAL | MLOG_WARNING, ++_("unable to read dirents for directory ino %llu: %s\n"), ++ ino, strerror(errno)); ++ break; ++ } ++ ++ /* no more directory entries: break; */ ++ if (!nread) ++ break; ++ ++ for (p = gdp; nread > 0; ++ nread -= (int)p->d_reclen, ++ assert(nread >= 0), ++ p = (struct dirent *)((char *)p + p->d_reclen)) { ++ if (!strcmp(p->d_name, "..")) { ++ if (p->d_ino == ino) ++ found = BOOL_TRUE; ++ break; ++ } ++ } ++ } ++ free(gdp); ++ return found; ++} ++ + bool_t + content_init( int argc, + char *argv[ ], +@@ -1394,6 +1448,14 @@ baseuuidbypass: + mntpnt ); + return BOOL_FALSE; + } ++ ++ if (!check_rootdir(sc_fsfd, rootstat.st_ino)) { ++ mlog(MLOG_ERROR, ++_("%s is not the root of the filesystem (bind mount?) - use primary mountpoint\n"), ++ mntpnt); ++ return BOOL_FALSE; ++ } ++ + sc_rootxfsstatp = + ( xfs_bstat_t * )calloc( 1, sizeof( xfs_bstat_t )); + assert( sc_rootxfsstatp ); diff --git a/SPECS/xfsdump.spec b/SPECS/xfsdump.spec index e8e5823..dadc861 100644 --- a/SPECS/xfsdump.spec +++ b/SPECS/xfsdump.spec @@ -1,13 +1,15 @@ Summary: Administrative utilities for the XFS filesystem Name: xfsdump Version: 3.1.7 -Release: 1%{?dist} +Release: 2%{?dist} # Licensing based on generic "GNU GENERAL PUBLIC LICENSE" # in source, with no mention of version. License: GPL+ Group: System Environment/Base URL: http://oss.sgi.com/projects/xfs/ Source0: https://www.kernel.org/pub/linux/utils/fs/xfs/%{name}/%{name}-%{version}.tar.xz +Patch0: 0001-xfsdump-Revert-xfsdump-handle-bind-mount-targets.patch +Patch1: 0002-xfsdump-intercept-bind-mount-targets.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: libtool, gettext, gawk BuildRequires: xfsprogs-devel, libuuid-devel, libattr-devel ncurses-devel @@ -32,6 +34,8 @@ subtrees may be restored from full or partial backups. %prep %setup -q +%patch0 -p1 +%patch1 -p1 %build %configure @@ -61,6 +65,9 @@ rm -rf $RPM_BUILD_ROOT %{_sbindir}/* %changelog +* Fri Nov 03 2017 Eric Sandeen 3.1.7-2 +- Fix bind mount vs root inode problems (#1698057) + * Fri Nov 03 2017 Eric Sandeen 3.1.7-1 - Rebase to build against current RHEL7 xfsprogs headers - Fix race condition between lseek() and read()/write() (#1086532)