From: Darrick J. Wong Date: Sun, 22 Feb 2026 22:41:16 +0000 (-0800) Subject: xfs_healer: validate that repair fds point to the monitored fs X-Git-Tag: v7.0.0~37 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c2425375f293f624233c26b457c5e6b96b65b8b7;p=xfsprogs-dev.git xfs_healer: validate that repair fds point to the monitored fs 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" Reviewed-by: Christoph Hellwig --- diff --git a/healer/fsrepair.c b/healer/fsrepair.c index 9f8c128e..002e5e78 100644 --- a/healer/fsrepair.c +++ b/healer/fsrepair.c @@ -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"), diff --git a/healer/weakhandle.c b/healer/weakhandle.c index 358c553f..7b8cef0a 100644 --- a/healer/weakhandle.c +++ b/healer/weakhandle.c @@ -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; diff --git a/healer/xfs_healer.h b/healer/xfs_healer.h index 96e146f2..c6692375 100644 --- a/healer/xfs_healer.h +++ b/healer/xfs_healer.h @@ -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);