From 93de1c28f4428217a4bacd5e7a7c57bf358d9f2c Mon Sep 17 00:00:00 2001 From: Umer Saleem Date: Tue, 17 Sep 2024 20:59:45 +0500 Subject: [PATCH] Fix mount permission issue Signed-off-by: Umer Saleem --- contrib/initramfs/scripts/zfs | 4 +- module/os/linux/zfs/zfs_ctldir.c | 114 ++++++++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 3 deletions(-) diff --git a/contrib/initramfs/scripts/zfs b/contrib/initramfs/scripts/zfs index 8d54f16bb16b..55de6be1c4dc 100644 --- a/contrib/initramfs/scripts/zfs +++ b/contrib/initramfs/scripts/zfs @@ -345,7 +345,7 @@ mount_fs() # Need the _original_ datasets mountpoint! mountpoint=$(get_fs_value "$fs" mountpoint) - ZFS_CMD="mount -o zfsutil -t zfs" + ZFS_CMD="mount.zfs -o zfsutil" if [ "$mountpoint" = "legacy" ] || [ "$mountpoint" = "none" ]; then # Can't use the mountpoint property. Might be one of our # clones. Check the 'org.zol:mountpoint' property set in @@ -362,7 +362,7 @@ mount_fs() fi # Don't use mount.zfs -o zfsutils for legacy mountpoint if [ "$mountpoint" = "legacy" ]; then - ZFS_CMD="mount -t zfs" + ZFS_CMD="mount.zfs" fi # Last hail-mary: Hope 'rootmnt' is set! mountpoint="" diff --git a/module/os/linux/zfs/zfs_ctldir.c b/module/os/linux/zfs/zfs_ctldir.c index e042116333fb..65dc5db3c17b 100644 --- a/module/os/linux/zfs/zfs_ctldir.c +++ b/module/os/linux/zfs/zfs_ctldir.c @@ -1049,6 +1049,62 @@ exportfs_flush(void) (void) call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); } +static int +get_root_path(struct path *path,char *buff, int len) +{ + struct path p; + char *path_buffer, *path_ptr; + int path_len, error = 0; + + if (path == NULL) + get_fs_root(current->fs, &p); + else + p = *path; + + path_get(&p); + path_buffer = kmem_zalloc(len, KM_SLEEP); + path_ptr = d_path(&p, path_buffer, len); + if (IS_ERR(path_ptr)) { + error = -PTR_ERR(path_ptr); + goto out; + } + path_len = path_buffer + len - 1 - path_ptr; + if (path_len > len) { + error = SET_ERROR(EFAULT); + goto out; + } + memcpy(buff, path_ptr, path_len); + buff[path_len] = '\0'; + +out: + kmem_free(path_buffer, len); + path_put(&p); + return (error); +} + +static int +is_current_chrooted(void) +{ + struct task_struct *curr = current, *global = &init_task; + struct path gl_root; + struct path cr_root; + int chrooted; + + get_fs_root(global->fs, &gl_root); + path_get(&gl_root); + while (d_mountpoint(gl_root.dentry) && follow_down_one(&gl_root)) + ; + + get_fs_root(curr->fs, &cr_root); + path_get(&cr_root); + chrooted = !path_equal(&cr_root, &gl_root); + + path_put(&cr_root); + path_put(&gl_root); + + return (chrooted); +} + /* * Attempt to unmount a snapshot by making a call to user space. * There is no assurance that this can or will succeed, is just a @@ -1100,7 +1156,7 @@ zfsctl_snapshot_mount(struct path *path, int flags) zfsvfs_t *zfsvfs; zfsvfs_t *snap_zfsvfs; zfs_snapentry_t *se; - char *full_name, *full_path; + char *full_name, *full_path, *root_path; char *argv[] = { "/usr/bin/env", "mount", "-i", "-t", "zfs", "-n", NULL, NULL, NULL }; char *envp[] = { NULL }; @@ -1116,12 +1172,67 @@ zfsctl_snapshot_mount(struct path *path, int flags) full_name = kmem_zalloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP); full_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP); + root_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP); error = zfsctl_snapshot_name(zfsvfs, dname(dentry), ZFS_MAX_DATASET_NAME_LEN, full_name); if (error) goto error; +// if (get_current_root_path(root_path, MAXPATHLEN) == 0) { +// if (is_current_chrooted() == 0) { +// zfs_dbgmsg("current process is not chrooted"); +// if (zfsvfs->z_vfs->vfs_mntpoint != NULL && +// strncmp(zfsvfs->z_vfs->vfs_mntpoint, "/root", +// 5) == 0 && strcmp(root_path, "/") == 0) { +// zfs_dbgmsg("zfsvfs->z_vfs->vfs_mntpoint is: %s", +// zfsvfs->z_vfs->vfs_mntpoint); +// zfs_dbgmsg("d_path returns for current fs root: %s", +// root_path); +// zfs_dbgmsg("this is propbably root filesystem"); +// memmove(zfsvfs->z_vfs->vfs_mntpoint, +// zfsvfs->z_vfs->vfs_mntpoint + 5, +// strlen(zfsvfs->z_vfs->vfs_mntpoint) - 4); +// zfs_dbgmsg("reset zfsvfs->z_vfs->vfs_mntpoint to: %s", +// zfsvfs->z_vfs->vfs_mntpoint); +// } +// } else if (is_current_chrooted()) { +// zfs_dbgmsg("Current process is in chroot context"); +// } +// } + error = get_root_path(NULL, root_path, MAXPATHLEN); + if (error) + goto error; + + if (is_current_chrooted() == 0) { + zfs_dbgmsg("current process is not chrooted"); + if (zfsvfs->z_vfs->vfs_mntpoint != NULL) { + char *mntpt = kmem_zalloc(MAXPATHLEN, KM_SLEEP); + struct path mnt_path; + mnt_path.mnt = path->mnt; + mnt_path.dentry = path->mnt->mnt_root; + if (get_root_path(&mnt_path, mntpt, MAXPATHLEN) != 0) { + kmem_free(mntpt, MAXPATHLEN); + goto error; + } + if (strcmp(zfsvfs->z_vfs->vfs_mntpoint, mntpt) != 0) { + zfs_dbgmsg("vfs_mntpoint and mntpt are not same"); + zfs_dbgmsg("vfs_mntpoint: %s mntpt: %s", + zfsvfs->z_vfs->vfs_mntpoint, mntpt); + + kmem_strfree(zfsvfs->z_vfs->vfs_mntpoint); + zfsvfs->z_vfs->vfs_mntpoint = kmem_strdup(mntpt); + + zfs_dbgmsg("vfs_mntpoint now set to: %s", + zfsvfs->z_vfs->vfs_mntpoint); + } else { + zfs_dbgmsg("vfs_mntpoint and mntpt are same"); + } + } + } else { + zfs_dbgmsg("Current process is in chroot context"); + } + /* * Construct a mount point path from sb of the ctldir inode and dirent * name, instead of from d_path(), so that chroot'd process doesn't fail @@ -1199,6 +1310,7 @@ zfsctl_snapshot_mount(struct path *path, int flags) error: kmem_free(full_name, ZFS_MAX_DATASET_NAME_LEN); kmem_free(full_path, MAXPATHLEN); + kmem_free(root_path, MAXPATHLEN); zfs_exit(zfsvfs, FTAG);