summaryrefslogtreecommitdiffstats
path: root/libmount/src/context_umount.c
diff options
context:
space:
mode:
authorRian Hunter2018-10-13 04:48:47 +0200
committerKarel Zak2018-11-30 10:25:04 +0100
commit5fea669e9ef0a08804f72bb40f859f239f68c30a (patch)
tree6f920941074f13cddf044613bd9fb7fa2ad7e076 /libmount/src/context_umount.c
parentlib/canonicalize: do restricted canonicalize in a subprocess (diff)
downloadkernel-qcow2-util-linux-5fea669e9ef0a08804f72bb40f859f239f68c30a.tar.gz
kernel-qcow2-util-linux-5fea669e9ef0a08804f72bb40f859f239f68c30a.tar.xz
kernel-qcow2-util-linux-5fea669e9ef0a08804f72bb40f859f239f68c30a.zip
libmount: Support unmount FUSE mounts
FUSE mounts don't need an fstab entry to be unmounted. This checks if a mount is a FUSE mount before checking for the fstab entry, and if so returns success. [kzak@redhat.com: - use libmount tools for mount options - use namespace switches - cleanup code The requirement is user=<username> or user_id=<uid> in /proc/self/mountinfo for fuse filesystem. The logic is the same as for user= mount options, but in this case it is not maintained by libmount in userspace, but by fuse FS in kernel.] Co-Author: Karel Zak <kzak@redhat.com> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libmount/src/context_umount.c')
-rw-r--r--libmount/src/context_umount.c82
1 files changed, 81 insertions, 1 deletions
diff --git a/libmount/src/context_umount.c b/libmount/src/context_umount.c
index d72f5ccd0..03c55ff61 100644
--- a/libmount/src/context_umount.c
+++ b/libmount/src/context_umount.c
@@ -388,6 +388,75 @@ static int prepare_helper_from_options(struct libmnt_context *cxt,
return rc;
}
+static int is_fuse_usermount(struct libmnt_context *cxt, int *errsv)
+{
+ struct libmnt_ns *ns_old;
+ const char *type = mnt_fs_get_fstype(cxt->fs);
+ const char *optstr;
+ char *user = NULL, *user_id = NULL, *curr_user = NULL;
+ size_t sz;
+ uid_t uid;
+ int ok = 0;
+
+ *errsv = 0;
+
+ if (!type)
+ return 0;
+
+ if (strcmp(type, "fuse") != 0 &&
+ strcmp(type, "fuseblk") != 0 &&
+ strncmp(type, "fuse.", 5) != 0 &&
+ strncmp(type, "fuseblk.", 8) != 0)
+ return 0;
+
+ /* get user= or user_id= from mtab/mountinfo */
+ optstr = mnt_fs_get_user_options(cxt->fs);
+ if (!optstr)
+ return 0;
+
+ if (mnt_optstr_get_option(optstr, "user", &user, &sz) != 0 &&
+ mnt_optstr_get_option(optstr, "user_id", &user_id, &sz) != 0)
+ return 0;
+
+ if (sz == 0 || (user == NULL && user_id == NULL))
+ return 0;
+
+ /* get current user */
+ ns_old = mnt_context_switch_origin_ns(cxt);
+ if (!ns_old) {
+ *errsv = -MNT_ERR_NAMESPACE;
+ return 0;
+ }
+
+ uid = getuid();
+ if (user)
+ curr_user = mnt_get_username(uid);
+
+ if (!mnt_context_switch_ns(cxt, ns_old)) {
+ *errsv = -MNT_ERR_NAMESPACE;
+ return 0;
+ }
+
+ if (user && !curr_user) {
+ DBG(CXT, ul_debugobj(cxt, "umount (fuse): cannot "
+ "convert %d to username", uid));
+ return 0;
+ }
+
+ if (user)
+ ok = strncmp(curr_user, user, sz) == 0;
+
+ else if (user_id) {
+ char uidstr[sizeof(stringify_value(ULONG_MAX))];
+ snprintf(uidstr, sizeof(uidstr), "%lu", (unsigned long) uid);
+
+ ok = strncmp(user_id, uidstr, sz) == 0;
+ }
+
+ free(curr_user);
+ return ok;
+}
+
/*
* Note that cxt->fs contains relevant mtab entry!
*/
@@ -396,7 +465,7 @@ static int evaluate_permissions(struct libmnt_context *cxt)
struct libmnt_table *fstab;
unsigned long u_flags = 0;
const char *tgt, *src, *optstr;
- int rc, ok = 0;
+ int rc = 0, ok = 0;
struct libmnt_fs *fs;
assert(cxt);
@@ -425,6 +494,17 @@ static int evaluate_permissions(struct libmnt_context *cxt)
}
/*
+ * Check if this is a fuse mount for the current user,
+ * if so then unmounting is allowed
+ */
+ if (is_fuse_usermount(cxt, &rc)) {
+ DBG(CXT, ul_debugobj(cxt, "fuse user mount, umount is allowed"));
+ return 0;
+ }
+ if (rc)
+ return rc;
+
+ /*
* User mounts have to be in /etc/fstab
*/
rc = mnt_context_get_fstab(cxt, &fstab);