mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 10:37:35 +03:00
Validate mountpoint on path-based unmount using statx
Use statx to verify that path-based unmounts proceed only if the mountpoint reported by statx matches the MNTTAB entry reported by libzfs, aborting the operation if they differ. Align `zfs umount /path` behavior with `zfs umount dataset`. Reviewed-by: Alexander Motin <mav@FreeBSD.org> Signed-off-by: Ameer Hamza <ahamza@ixsystems.com> Closes #17481
This commit is contained in:
@@ -85,13 +85,21 @@ _sol_getmntent(FILE *fp, struct mnttab *mgetp)
|
||||
}
|
||||
|
||||
static int
|
||||
getextmntent_impl(FILE *fp, struct extmnttab *mp)
|
||||
getextmntent_impl(FILE *fp, struct extmnttab *mp, uint64_t *mnt_id)
|
||||
{
|
||||
int ret;
|
||||
struct stat64 st;
|
||||
|
||||
*mnt_id = 0;
|
||||
ret = _sol_getmntent(fp, (struct mnttab *)mp);
|
||||
if (ret == 0) {
|
||||
#ifdef HAVE_STATX_MNT_ID
|
||||
struct statx stx;
|
||||
if (statx(AT_FDCWD, mp->mnt_mountp,
|
||||
AT_STATX_SYNC_AS_STAT | AT_SYMLINK_NOFOLLOW,
|
||||
STATX_MNT_ID, &stx) == 0 && (stx.stx_mask & STATX_MNT_ID))
|
||||
*mnt_id = stx.stx_mnt_id;
|
||||
#endif
|
||||
if (stat64(mp->mnt_mountp, &st) != 0) {
|
||||
mp->mnt_major = 0;
|
||||
mp->mnt_minor = 0;
|
||||
@@ -110,6 +118,12 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf)
|
||||
struct stat64 st;
|
||||
FILE *fp;
|
||||
int match;
|
||||
boolean_t have_mnt_id = B_FALSE;
|
||||
uint64_t target_mnt_id = 0;
|
||||
uint64_t entry_mnt_id;
|
||||
#ifdef HAVE_STATX_MNT_ID
|
||||
struct statx stx;
|
||||
#endif
|
||||
|
||||
if (strlen(path) >= MAXPATHLEN) {
|
||||
(void) fprintf(stderr, "invalid object; pathname too long\n");
|
||||
@@ -128,6 +142,13 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_STATX_MNT_ID
|
||||
if (statx(AT_FDCWD, path, AT_STATX_SYNC_AS_STAT | AT_SYMLINK_NOFOLLOW,
|
||||
STATX_MNT_ID, &stx) == 0 && (stx.stx_mask & STATX_MNT_ID)) {
|
||||
have_mnt_id = B_TRUE;
|
||||
target_mnt_id = stx.stx_mnt_id;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((fp = fopen(MNTTAB, "re")) == NULL) {
|
||||
(void) fprintf(stderr, "cannot open %s\n", MNTTAB);
|
||||
@@ -139,12 +160,15 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf)
|
||||
*/
|
||||
|
||||
match = 0;
|
||||
while (getextmntent_impl(fp, entry) == 0) {
|
||||
if (makedev(entry->mnt_major, entry->mnt_minor) ==
|
||||
statbuf->st_dev) {
|
||||
match = 1;
|
||||
break;
|
||||
while (getextmntent_impl(fp, entry, &entry_mnt_id) == 0) {
|
||||
if (have_mnt_id) {
|
||||
match = (entry_mnt_id == target_mnt_id);
|
||||
} else {
|
||||
match = makedev(entry->mnt_major, entry->mnt_minor) ==
|
||||
statbuf->st_dev;
|
||||
}
|
||||
if (match)
|
||||
break;
|
||||
}
|
||||
(void) fclose(fp);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user