Skip to content

Commit

Permalink
Fix mount permission issue
Browse files Browse the repository at this point in the history
Signed-off-by: Umer Saleem <[email protected]>
  • Loading branch information
usaleem-ix committed Sep 30, 2024
1 parent eecb1bc commit 63e5c1c
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 2 deletions.
4 changes: 2 additions & 2 deletions contrib/initramfs/scripts/zfs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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=""
Expand Down
93 changes: 93 additions & 0 deletions module/os/linux/zfs/zfs_ctldir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,68 @@ exportfs_flush(void)
(void) call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
}

/*
* Returns the path in char format for given struct path. Uses
* d_path exported by kernel to convert struct path to char
* format. Returns the correct path for mountpoints and chroot
* environments.
*
* If chroot environment has directories that are mounted with
* --bind or --rbind flag, d_path returns the complete path inside
* chroot environment but does not return the absolute path, i.e.
* the path to chroot environment is missing.
*/
static int
get_root_path(struct path *path, char *buff, int len)
{
char *path_buffer, *path_ptr;
int path_len, error = 0;

path_get(path);
path_buffer = kmem_zalloc(len, KM_SLEEP);
path_ptr = d_path(path, path_buffer, len);
if (IS_ERR(path_ptr)) {
error = SET_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(path);
return (error);
}

/*
* Returns if the current process root is chrooted or not.
*/
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);
while (d_mountpoint(gl_root.dentry) && follow_down_one(&gl_root))
;

get_fs_root(curr->fs, &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
Expand Down Expand Up @@ -1122,6 +1184,37 @@ zfsctl_snapshot_mount(struct path *path, int flags)
if (error)
goto error;

if (is_current_chrooted() == 0) {
/*
* Current process is not in chroot context
*/
if (zfsvfs->z_vfs->vfs_mntpoint != NULL) {
char *m = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
struct path mnt_path;
mnt_path.mnt = path->mnt;
mnt_path.dentry = path->mnt->mnt_root;

/*
* Get path to current mountpoint
*/
error = get_root_path(&mnt_path, m, MAXPATHLEN);
if (error != 0) {
kmem_free(m, MAXPATHLEN);
goto error;
}

/*
* If current mnountpoint and vfs_mntpoint are not same,
* store current mountpoint in vfs_mntpoint.
*/
if (strcmp(zfsvfs->z_vfs->vfs_mntpoint, m) != 0) {
kmem_strfree(zfsvfs->z_vfs->vfs_mntpoint);
zfsvfs->z_vfs->vfs_mntpoint = kmem_strdup(m);
}
kmem_free(m, MAXPATHLEN);
}
}

/*
* 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
Expand Down

0 comments on commit 63e5c1c

Please sign in to comment.