]> git-server-git.apps.pok.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs_healer: validate that repair fds point to the monitored fs
authorDarrick J. Wong <djwong@kernel.org>
Sun, 22 Feb 2026 22:41:16 +0000 (14:41 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 9 Apr 2026 22:30:18 +0000 (15:30 -0700)
When xfs_healer reopens a mountpoint to perform a repair, it should
validate that the opened fd points to a file on the same filesystem as
the one being monitored.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
healer/fsrepair.c
healer/weakhandle.c
healer/xfs_healer.h

index 9f8c128e395ebc7ef6d395547589cb504e5bbdc3..002e5e78fcf22ea9f8d90be97be7652afb33f578 100644 (file)
@@ -233,6 +233,22 @@ try_repair_inode(
        return REPAIR_DONE;
 }
 
+/* Make sure the reopened file is on the same fs as the monitor. */
+static bool
+is_same_fs(
+       int                             mnt_fd,
+       void                            *data)
+{
+       struct xfs_health_file_on_monitored_fs hms = {
+               .fd = mnt_fd,
+       };
+       FILE                            *mon_fp = data;
+       int                             ret;
+
+       ret = ioctl(fileno(mon_fp), XFS_IOC_HEALTH_FD_ON_MONITORED_FS, &hms);
+       return ret == 0;
+}
+
 /* Repair a metadata corruption. */
 int
 repair_metadata(
@@ -244,7 +260,7 @@ repair_metadata(
        int                                     repair_fd;
        int                                     ret;
 
-       ret = weakhandle_reopen(ctx->wh, &repair_fd);
+       ret = weakhandle_reopen(ctx->wh, &repair_fd, is_same_fs, ctx->mon_fp);
        if (ret) {
                fprintf(stderr, "%s: %s: %s\n", ctx->mntpoint,
                                _("cannot open filesystem to repair"),
index 358c553f883f3d72d57463ab57c5c495e7475482..7b8cef0a63f97198eb2d0d417062ffe6d35ee3c7 100644 (file)
@@ -79,7 +79,9 @@ static int
 weakhandle_reopen_from(
        struct weakhandle       *wh,
        const char              *path,
-       int                     *fd)
+       int                     *fd,
+       weakhandle_fd_t         is_acceptable,
+       void                    *data)
 {
        void                    *hanp;
        size_t                  hlen;
@@ -101,6 +103,11 @@ weakhandle_reopen_from(
                goto out_handle;
        }
 
+       if (is_acceptable && !is_acceptable(mnt_fd, data)) {
+               errno = ESTALE;
+               goto out_handle;
+       }
+
        free_handle(hanp, hlen);
        *fd = mnt_fd;
        return 0;
@@ -116,7 +123,9 @@ out_mntfd:
 int
 weakhandle_reopen(
        struct weakhandle       *wh,
-       int                     *fd)
+       int                     *fd,
+       weakhandle_fd_t         is_acceptable,
+       void                    *data)
 {
        const size_t            smbuf_size =
                libfrog_statmount_sizeof(PATH_MAX);
@@ -126,7 +135,7 @@ weakhandle_reopen(
        int                     ret;
 
        /* First try reopening using the original mountpoint */
-       ret = weakhandle_reopen_from(wh, wh->mntpoint, fd);
+       ret = weakhandle_reopen_from(wh, wh->mntpoint, fd, is_acceptable, data);
        if (!ret)
                return 0;
 
@@ -140,7 +149,8 @@ weakhandle_reopen(
                        STATMOUNT_MNT_POINT, smbuf, smbuf_size);
        if (ret || !(smbuf->mask & STATMOUNT_MNT_POINT))
                goto fallback;
-       ret = weakhandle_reopen_from(wh, smbuf->str + smbuf->mnt_point, fd);
+       ret = weakhandle_reopen_from(wh, smbuf->str + smbuf->mnt_point, fd,
+                       is_acceptable, data);
        if (!ret)
                return 0;
 
@@ -159,7 +169,8 @@ fallback:
                if (strcmp(mnt->mnt_fsname, wh->fsname))
                        continue;
 
-               ret = weakhandle_reopen_from(wh, mnt->mnt_dir, fd);
+               ret = weakhandle_reopen_from(wh, mnt->mnt_dir, fd,
+                               is_acceptable, data);
                if (!ret)
                        break;
        }
@@ -244,7 +255,7 @@ weakhandle_getpath_for(
        fakehandle.ha_fid.fid_ino = ino;
        fakehandle.ha_fid.fid_gen = gen;
 
-       ret = weakhandle_reopen(wh, &mnt_fd);
+       ret = weakhandle_reopen(wh, &mnt_fd, NULL, NULL);
        if (ret)
                return ret;
 
index 96e146f266629aa4464e771086e66ebd581d1677..c6692375dda6bffa632e6cb82743ccf14fa0e60b 100644 (file)
@@ -80,7 +80,9 @@ void run_full_repair(struct healer_ctx *ctx);
 /* weakhandle.c */
 int weakhandle_alloc(int fd, const char *mountpoint, uint64_t mnt_id,
                const char *fsname, struct weakhandle **whp);
-int weakhandle_reopen(struct weakhandle *wh, int *fd);
+typedef bool (*weakhandle_fd_t)(int mnt_fd, void *data);
+int weakhandle_reopen(struct weakhandle *wh, int *fd,
+               weakhandle_fd_t is_acceptable, void *data);
 void weakhandle_free(struct weakhandle **whp);
 int weakhandle_getpath_for(struct weakhandle *wh, uint64_t ino, uint32_t gen,
                char *path, size_t pathlen);