diff options
-rw-r--r-- | .SRCINFO | 2 | ||||
-rw-r--r-- | 0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch | 3277 | ||||
-rw-r--r-- | PKGBUILD | 10 |
3 files changed, 1 insertions, 3288 deletions
@@ -16,8 +16,6 @@ pkgbase = util-linux-nosystemd-minimal-git source = pam-su source = 60-rfkill.rules source = util-linux.sysusers - source = 0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch - sha256sums = SKIP sha256sums = SKIP sha256sums = SKIP sha256sums = SKIP diff --git a/0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch b/0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch deleted file mode 100644 index a4377ece4dfd..000000000000 --- a/0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch +++ /dev/null @@ -1,3277 +0,0 @@ -diff -Nuar -uar a/libmount/src/context_mount.c b/libmount/src/context_mount.c ---- a/libmount/src/context_mount.c 2020-11-13 22:00:15.000000000 +1100 -+++ b/libmount/src/context_mount.c 2020-12-21 12:32:20.836075130 +1100 -@@ -38,37 +38,37 @@ - */ - struct libmnt_addmount *mnt_new_addmount(void) - { -- struct libmnt_addmount *ad = calloc(1, sizeof(*ad)); -- if (!ad) -- return NULL; -+ struct libmnt_addmount *ad = calloc(1, sizeof(*ad)); -+ if (!ad) -+ return NULL; - -- INIT_LIST_HEAD(&ad->mounts); -- return ad; -+ INIT_LIST_HEAD(&ad->mounts); -+ return ad; - } - - void mnt_free_addmount(struct libmnt_addmount *ad) - { -- if (!ad) -- return; -- list_del(&ad->mounts); -- free(ad); -+ if (!ad) -+ return; -+ list_del(&ad->mounts); -+ free(ad); - } - - static int mnt_context_append_additional_mount(struct libmnt_context *cxt, -- struct libmnt_addmount *ad) -+ struct libmnt_addmount *ad) - { -- assert(cxt); -- assert(ad); -+ assert(cxt); -+ assert(ad); - -- if (!list_empty(&ad->mounts)) -- return -EINVAL; -+ if (!list_empty(&ad->mounts)) -+ return -EINVAL; - -- DBG(CXT, ul_debugobj(cxt, -- "mount: add additional flag: 0x%08lx", -- ad->mountflags)); -+ DBG(CXT, ul_debugobj(cxt, -+ "mount: add additional flag: 0x%08lx", -+ ad->mountflags)); - -- list_add_tail(&ad->mounts, &cxt->addmounts); -- return 0; -+ list_add_tail(&ad->mounts, &cxt->addmounts); -+ return 0; - } - - /* -@@ -77,60 +77,60 @@ - */ - static int init_propagation(struct libmnt_context *cxt) - { -- char *name; -- char *opts = (char *) mnt_fs_get_vfs_options(cxt->fs); -- size_t namesz; -- struct libmnt_optmap const *maps[1]; -- int rec_count = 0; -+ char *name; -+ char *opts = (char *) mnt_fs_get_vfs_options(cxt->fs); -+ size_t namesz; -+ struct libmnt_optmap const *maps[1]; -+ int rec_count = 0; - -- if (!opts) -- return 0; -+ if (!opts) -+ return 0; - -- DBG(CXT, ul_debugobj(cxt, "mount: initialize additional propagation mounts")); -+ DBG(CXT, ul_debugobj(cxt, "mount: initialize additional propagation mounts")); - -- maps[0] = mnt_get_builtin_optmap(MNT_LINUX_MAP); -+ maps[0] = mnt_get_builtin_optmap(MNT_LINUX_MAP); - -- while (!mnt_optstr_next_option(&opts, &name, &namesz, NULL, NULL)) { -- const struct libmnt_optmap *ent; -- struct libmnt_addmount *ad; -- int rc; -+ while (!mnt_optstr_next_option(&opts, &name, &namesz, NULL, NULL)) { -+ const struct libmnt_optmap *ent; -+ struct libmnt_addmount *ad; -+ int rc; - -- if (!mnt_optmap_get_entry(maps, 1, name, namesz, &ent) || !ent) -- continue; -+ if (!mnt_optmap_get_entry(maps, 1, name, namesz, &ent) || !ent) -+ continue; - -- DBG(CXT, ul_debugobj(cxt, " checking %s", ent->name)); -+ DBG(CXT, ul_debugobj(cxt, " checking %s", ent->name)); - -- /* Note that MS_REC may be used for more flags, so we have to keep -- * track about number of recursive options to keep the MS_REC in the -- * mountflags if necessary. -- */ -- if (ent->id & MS_REC) -- rec_count++; -+ /* Note that MS_REC may be used for more flags, so we have to keep -+ * track about number of recursive options to keep the MS_REC in the -+ * mountflags if necessary. -+ */ -+ if (ent->id & MS_REC) -+ rec_count++; - -- if (!(ent->id & MS_PROPAGATION)) -- continue; -+ if (!(ent->id & MS_PROPAGATION)) -+ continue; - -- ad = mnt_new_addmount(); -- if (!ad) -- return -ENOMEM; -+ ad = mnt_new_addmount(); -+ if (!ad) -+ return -ENOMEM; - -- ad->mountflags = ent->id; -- DBG(CXT, ul_debugobj(cxt, " adding extra mount(2) call for %s", ent->name)); -- rc = mnt_context_append_additional_mount(cxt, ad); -- if (rc) -- return rc; -+ ad->mountflags = ent->id; -+ DBG(CXT, ul_debugobj(cxt, " adding extra mount(2) call for %s", ent->name)); -+ rc = mnt_context_append_additional_mount(cxt, ad); -+ if (rc) -+ return rc; - -- DBG(CXT, ul_debugobj(cxt, " removing %s from primary mount(2) call", ent->name)); -- cxt->mountflags &= ~ent->id; -+ DBG(CXT, ul_debugobj(cxt, " removing %s from primary mount(2) call", ent->name)); -+ cxt->mountflags &= ~ent->id; - -- if (ent->id & MS_REC) -- rec_count--; -- } -+ if (ent->id & MS_REC) -+ rec_count--; -+ } - -- if (rec_count) -- cxt->mountflags |= MS_REC; -+ if (rec_count) -+ cxt->mountflags |= MS_REC; - -- return 0; -+ return 0; - } - - /* -@@ -139,50 +139,50 @@ - */ - static int init_bind_remount(struct libmnt_context *cxt) - { -- struct libmnt_addmount *ad; -- int rc; -+ struct libmnt_addmount *ad; -+ int rc; - -- assert(cxt); -- assert(cxt->mountflags & MS_BIND); -- assert(!(cxt->mountflags & MS_REMOUNT)); -+ assert(cxt); -+ assert(cxt->mountflags & MS_BIND); -+ assert(!(cxt->mountflags & MS_REMOUNT)); - -- DBG(CXT, ul_debugobj(cxt, "mount: initialize additional ro,bind mount")); -+ DBG(CXT, ul_debugobj(cxt, "mount: initialize additional ro,bind mount")); - -- ad = mnt_new_addmount(); -- if (!ad) -- return -ENOMEM; -+ ad = mnt_new_addmount(); -+ if (!ad) -+ return -ENOMEM; - -- ad->mountflags = cxt->mountflags; -- ad->mountflags |= (MS_REMOUNT | MS_BIND); -+ ad->mountflags = cxt->mountflags; -+ ad->mountflags |= (MS_REMOUNT | MS_BIND); - -- rc = mnt_context_append_additional_mount(cxt, ad); -- if (rc) -- return rc; -+ rc = mnt_context_append_additional_mount(cxt, ad); -+ if (rc) -+ return rc; - -- return 0; -+ return 0; - } - - #if defined(HAVE_LIBSELINUX) || defined(HAVE_SMACK) - struct libmnt_optname { -- const char *name; -- size_t namesz; -+ const char *name; -+ size_t namesz; - }; - --#define DEF_OPTNAME(n) { .name = n, .namesz = sizeof(n) - 1 } --#define DEF_OPTNAME_LAST { .name = NULL } -+#define DEF_OPTNAME(n) { .name = n, .namesz = sizeof(n) - 1 } -+#define DEF_OPTNAME_LAST { .name = NULL } - - static int is_option(const char *name, size_t namesz, -- const struct libmnt_optname *names) -+ const struct libmnt_optname *names) - { -- const struct libmnt_optname *p; -+ const struct libmnt_optname *p; - -- for (p = names; p && p->name; p++) { -- if (p->namesz == namesz -- && strncmp(name, p->name, namesz) == 0) -- return 1; -- } -+ for (p = names; p && p->name; p++) { -+ if (p->namesz == namesz -+ && strncmp(name, p->name, namesz) == 0) -+ return 1; -+ } - -- return 0; -+ return 0; - } - #endif /* HAVE_LIBSELINUX || HAVE_SMACK */ - -@@ -191,194 +191,194 @@ - */ - static int fix_optstr(struct libmnt_context *cxt) - { -- int rc = 0; -- struct libmnt_ns *ns_old; -- char *next; -- char *name, *val; -- size_t namesz, valsz; -- struct libmnt_fs *fs; -+ int rc = 0; -+ struct libmnt_ns *ns_old; -+ char *next; -+ char *name, *val; -+ size_t namesz, valsz; -+ struct libmnt_fs *fs; - #ifdef HAVE_LIBSELINUX -- int se_fix = 0, se_rem = 0; -- static const struct libmnt_optname selinux_options[] = { -- DEF_OPTNAME("context"), -- DEF_OPTNAME("fscontext"), -- DEF_OPTNAME("defcontext"), -- DEF_OPTNAME("rootcontext"), -- DEF_OPTNAME("seclabel"), -- DEF_OPTNAME_LAST -- }; -+ int se_fix = 0, se_rem = 0; -+ static const struct libmnt_optname selinux_options[] = { -+ DEF_OPTNAME("context"), -+ DEF_OPTNAME("fscontext"), -+ DEF_OPTNAME("defcontext"), -+ DEF_OPTNAME("rootcontext"), -+ DEF_OPTNAME("seclabel"), -+ DEF_OPTNAME_LAST -+ }; - #endif - #ifdef HAVE_SMACK -- int sm_rem = 0; -- static const struct libmnt_optname smack_options[] = { -- DEF_OPTNAME("smackfsdef"), -- DEF_OPTNAME("smackfsfloor"), -- DEF_OPTNAME("smackfshat"), -- DEF_OPTNAME("smackfsroot"), -- DEF_OPTNAME("smackfstransmute"), -- DEF_OPTNAME_LAST -- }; -+ int sm_rem = 0; -+ static const struct libmnt_optname smack_options[] = { -+ DEF_OPTNAME("smackfsdef"), -+ DEF_OPTNAME("smackfsfloor"), -+ DEF_OPTNAME("smackfshat"), -+ DEF_OPTNAME("smackfsroot"), -+ DEF_OPTNAME("smackfstransmute"), -+ DEF_OPTNAME_LAST -+ }; - #endif -- assert(cxt); -- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -+ assert(cxt); -+ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); - -- if (!cxt->fs || (cxt->flags & MNT_FL_MOUNTOPTS_FIXED)) -- return 0; -+ if (!cxt->fs || (cxt->flags & MNT_FL_MOUNTOPTS_FIXED)) -+ return 0; - -- fs = cxt->fs; -+ fs = cxt->fs; - -- DBG(CXT, ul_debugobj(cxt, "mount: fixing options, current " -- "vfs: '%s' fs: '%s' user: '%s', optstr: '%s'", -- fs->vfs_optstr, fs->fs_optstr, fs->user_optstr, fs->optstr)); -- -- /* -- * The "user" options is our business (so we can modify the option), -- * the exception is command line for /sbin/mount.<type> helpers. Let's -- * save the original user=<name> to call the helpers with an unchanged -- * "user" setting. -- */ -- if (cxt->user_mountflags & MNT_MS_USER) { -- if (!mnt_optstr_get_option(fs->user_optstr, -- "user", &val, &valsz) && val) { -- cxt->orig_user = strndup(val, valsz); -- if (!cxt->orig_user) { -- rc = -ENOMEM; -- goto done; -- } -- } -- cxt->flags |= MNT_FL_SAVED_USER; -- } -- -- /* -- * Sync mount options with mount flags -- */ -- DBG(CXT, ul_debugobj(cxt, "mount: fixing vfs optstr")); -- rc = mnt_optstr_apply_flags(&fs->vfs_optstr, cxt->mountflags, -- mnt_get_builtin_optmap(MNT_LINUX_MAP)); -- if (rc) -- goto done; -- -- DBG(CXT, ul_debugobj(cxt, "mount: fixing user optstr")); -- rc = mnt_optstr_apply_flags(&fs->user_optstr, cxt->user_mountflags, -- mnt_get_builtin_optmap(MNT_USERSPACE_MAP)); -- if (rc) -- goto done; -- -- if (fs->vfs_optstr && *fs->vfs_optstr == '\0') { -- free(fs->vfs_optstr); -- fs->vfs_optstr = NULL; -- } -- if (fs->user_optstr && *fs->user_optstr == '\0') { -- free(fs->user_optstr); -- fs->user_optstr = NULL; -- } -- if (cxt->mountflags & MS_PROPAGATION) { -- rc = init_propagation(cxt); -- if (rc) -- return rc; -- } -- if ((cxt->mountflags & MS_BIND) -- && (cxt->mountflags & MNT_BIND_SETTABLE) -- && !(cxt->mountflags & MS_REMOUNT)) { -- rc = init_bind_remount(cxt); -- if (rc) -- return rc; -- } -+ DBG(CXT, ul_debugobj(cxt, "mount: fixing options, current " -+ "vfs: '%s' fs: '%s' user: '%s', optstr: '%s'", -+ fs->vfs_optstr, fs->fs_optstr, fs->user_optstr, fs->optstr)); -+ -+ /* -+ * The "user" options is our business (so we can modify the option), -+ * the exception is command line for /sbin/mount.<type> helpers. Let's -+ * save the original user=<name> to call the helpers with an unchanged -+ * "user" setting. -+ */ -+ if (cxt->user_mountflags & MNT_MS_USER) { -+ if (!mnt_optstr_get_option(fs->user_optstr, -+ "user", &val, &valsz) && val) { -+ cxt->orig_user = strndup(val, valsz); -+ if (!cxt->orig_user) { -+ rc = -ENOMEM; -+ goto done; -+ } -+ } -+ cxt->flags |= MNT_FL_SAVED_USER; -+ } -+ -+ /* -+ * Sync mount options with mount flags -+ */ -+ DBG(CXT, ul_debugobj(cxt, "mount: fixing vfs optstr")); -+ rc = mnt_optstr_apply_flags(&fs->vfs_optstr, cxt->mountflags, -+ mnt_get_builtin_optmap(MNT_LINUX_MAP)); -+ if (rc) -+ goto done; -+ -+ DBG(CXT, ul_debugobj(cxt, "mount: fixing user optstr")); -+ rc = mnt_optstr_apply_flags(&fs->user_optstr, cxt->user_mountflags, -+ mnt_get_builtin_optmap(MNT_USERSPACE_MAP)); -+ if (rc) -+ goto done; -+ -+ if (fs->vfs_optstr && *fs->vfs_optstr == '\0') { -+ free(fs->vfs_optstr); -+ fs->vfs_optstr = NULL; -+ } -+ if (fs->user_optstr && *fs->user_optstr == '\0') { -+ free(fs->user_optstr); -+ fs->user_optstr = NULL; -+ } -+ if (cxt->mountflags & MS_PROPAGATION) { -+ rc = init_propagation(cxt); -+ if (rc) -+ return rc; -+ } -+ if ((cxt->mountflags & MS_BIND) -+ && (cxt->mountflags & MNT_BIND_SETTABLE) -+ && !(cxt->mountflags & MS_REMOUNT)) { -+ rc = init_bind_remount(cxt); -+ if (rc) -+ return rc; -+ } - -- next = fs->fs_optstr; -+ next = fs->fs_optstr; - - #ifdef HAVE_LIBSELINUX -- if (!is_selinux_enabled()) -- /* Always remove SELinux garbage if SELinux disabled */ -- se_rem = 1; -- else if (cxt->mountflags & MS_REMOUNT) -- /* -- * Linux kernel < 2.6.39 does not support remount operation -- * with any selinux specific mount options. -- * -- * Kernel 2.6.39 commits: ff36fe2c845cab2102e4826c1ffa0a6ebf487c65 -- * 026eb167ae77244458fa4b4b9fc171209c079ba7 -- * fix this odd behavior, so we don't have to care about it in -- * userspace. -- */ -- se_rem = get_linux_version() < KERNEL_VERSION(2, 6, 39); -- else -- /* For normal mount, contexts are translated */ -- se_fix = 1; -- -- if (!se_rem) { -- /* de-duplicate SELinux options */ -- const struct libmnt_optname *p; -- for (p = selinux_options; p && p->name; p++) -- mnt_optstr_deduplicate_option(&fs->fs_optstr, p->name); -- } -+ if (!is_selinux_enabled()) -+ /* Always remove SELinux garbage if SELinux disabled */ -+ se_rem = 1; -+ else if (cxt->mountflags & MS_REMOUNT) -+ /* -+ * Linux kernel < 2.6.39 does not support remount operation -+ * with any selinux specific mount options. -+ * -+ * Kernel 2.6.39 commits: ff36fe2c845cab2102e4826c1ffa0a6ebf487c65 -+ * 026eb167ae77244458fa4b4b9fc171209c079ba7 -+ * fix this odd behavior, so we don't have to care about it in -+ * userspace. -+ */ -+ se_rem = get_linux_version() < KERNEL_VERSION(2, 6, 39); -+ else -+ /* For normal mount, contexts are translated */ -+ se_fix = 1; -+ -+ if (!se_rem) { -+ /* de-duplicate SELinux options */ -+ const struct libmnt_optname *p; -+ for (p = selinux_options; p && p->name; p++) -+ mnt_optstr_deduplicate_option(&fs->fs_optstr, p->name); -+ } - #endif - #ifdef HAVE_SMACK -- if (access("/sys/fs/smackfs", F_OK) != 0) -- sm_rem = 1; -+ if (access("/sys/fs/smackfs", F_OK) != 0) -+ sm_rem = 1; - #endif -- while (!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) { -+ while (!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) { - -- if (namesz == 3 && !strncmp(name, "uid", 3)) -- rc = mnt_optstr_fix_uid(&fs->fs_optstr, val, valsz, &next); -- else if (namesz == 3 && !strncmp(name, "gid", 3)) -- rc = mnt_optstr_fix_gid(&fs->fs_optstr, val, valsz, &next); -+ if (namesz == 3 && !strncmp(name, "uid", 3)) -+ rc = mnt_optstr_fix_uid(&fs->fs_optstr, val, valsz, &next); -+ else if (namesz == 3 && !strncmp(name, "gid", 3)) -+ rc = mnt_optstr_fix_gid(&fs->fs_optstr, val, valsz, &next); - #ifdef HAVE_LIBSELINUX -- else if ((se_rem || se_fix) -- && is_option(name, namesz, selinux_options)) { -+ else if ((se_rem || se_fix) -+ && is_option(name, namesz, selinux_options)) { - -- if (se_rem) { -- /* remove context= option */ -- next = name; -- rc = mnt_optstr_remove_option_at(&fs->fs_optstr, -- name, -- val ? val + valsz : -- name + namesz); -- } else if (se_fix && val && valsz) -- /* translate selinux contexts */ -- rc = mnt_optstr_fix_secontext(&fs->fs_optstr, -- val, valsz, &next); -- } -+ if (se_rem) { -+ /* remove context= option */ -+ next = name; -+ rc = mnt_optstr_remove_option_at(&fs->fs_optstr, -+ name, -+ val ? val + valsz : -+ name + namesz); -+ } else if (se_fix && val && valsz) -+ /* translate selinux contexts */ -+ rc = mnt_optstr_fix_secontext(&fs->fs_optstr, -+ val, valsz, &next); -+ } - #endif - #ifdef HAVE_SMACK -- else if (sm_rem && is_option(name, namesz, smack_options)) { -+ else if (sm_rem && is_option(name, namesz, smack_options)) { - -- next = name; -- rc = mnt_optstr_remove_option_at(&fs->fs_optstr, -- name, -- val ? val + valsz : name + namesz); -- } -+ next = name; -+ rc = mnt_optstr_remove_option_at(&fs->fs_optstr, -+ name, -+ val ? val + valsz : name + namesz); -+ } - #endif -- if (rc) -- goto done; -- } -- -- -- if (!rc && mnt_context_is_restricted(cxt) && (cxt->user_mountflags & MNT_MS_USER)) { -- ns_old = mnt_context_switch_origin_ns(cxt); -- if (!ns_old) -- return -MNT_ERR_NAMESPACE; -- -- rc = mnt_optstr_fix_user(&fs->user_optstr); -- -- if (!mnt_context_switch_ns(cxt, ns_old)) -- return -MNT_ERR_NAMESPACE; -- } -- -- /* refresh merged optstr */ -- free(fs->optstr); -- fs->optstr = NULL; -- fs->optstr = mnt_fs_strdup_options(fs); -+ if (rc) -+ goto done; -+ } -+ -+ -+ if (!rc && mnt_context_is_restricted(cxt) && (cxt->user_mountflags & MNT_MS_USER)) { -+ ns_old = mnt_context_switch_origin_ns(cxt); -+ if (!ns_old) -+ return -MNT_ERR_NAMESPACE; -+ -+ rc = mnt_optstr_fix_user(&fs->user_optstr); -+ -+ if (!mnt_context_switch_ns(cxt, ns_old)) -+ return -MNT_ERR_NAMESPACE; -+ } -+ -+ /* refresh merged optstr */ -+ free(fs->optstr); -+ fs->optstr = NULL; -+ fs->optstr = mnt_fs_strdup_options(fs); - done: -- cxt->flags |= MNT_FL_MOUNTOPTS_FIXED; -+ cxt->flags |= MNT_FL_MOUNTOPTS_FIXED; - -- DBG(CXT, ul_debugobj(cxt, "fixed options [rc=%d]: " -- "vfs: '%s' fs: '%s' user: '%s', optstr: '%s'", rc, -- fs->vfs_optstr, fs->fs_optstr, fs->user_optstr, fs->optstr)); -- -- if (rc) -- rc = -MNT_ERR_MOUNTOPT; -- return rc; -+ DBG(CXT, ul_debugobj(cxt, "fixed options [rc=%d]: " -+ "vfs: '%s' fs: '%s' user: '%s', optstr: '%s'", rc, -+ fs->vfs_optstr, fs->fs_optstr, fs->user_optstr, fs->optstr)); -+ -+ if (rc) -+ rc = -MNT_ERR_MOUNTOPT; -+ return rc; - } - - /* -@@ -387,74 +387,74 @@ - */ - static int generate_helper_optstr(struct libmnt_context *cxt, char **optstr) - { -- struct libmnt_optmap const *maps[2]; -- char *next, *name, *val; -- size_t namesz, valsz; -- int rc = 0; -- -- assert(cxt); -- assert(cxt->fs); -- assert(optstr); -- -- DBG(CXT, ul_debugobj(cxt, "mount: generate helper mount options")); -- -- *optstr = mnt_fs_strdup_options(cxt->fs); -- if (!*optstr) -- return -ENOMEM; -- -- if ((cxt->user_mountflags & MNT_MS_USER) || -- (cxt->user_mountflags & MNT_MS_USERS)) { -- /* -- * This is unnecessary for real user-mounts as mount.<type> -- * helpers always have to follow fstab rather than mount -- * options on the command line. -- * -- * However, if you call mount.<type> as root, then the helper follows -- * the command line. If there is (for example) "user,exec" in fstab, -- * then we have to manually append the "exec" back to the options -- * string, because there is nothing like MS_EXEC (we only have -- * MS_NOEXEC in mount flags and we don't care about the original -- * mount string in libmount for VFS options). -- */ -- if (!(cxt->mountflags & MS_NOEXEC)) -- mnt_optstr_append_option(optstr, "exec", NULL); -- if (!(cxt->mountflags & MS_NOSUID)) -- mnt_optstr_append_option(optstr, "suid", NULL); -- if (!(cxt->mountflags & MS_NODEV)) -- mnt_optstr_append_option(optstr, "dev", NULL); -- if (!(cxt->mountflags & MS_NOSYMFOLLOW)) -- mnt_optstr_append_option(optstr, "symfollow", NULL); -- } -- -- -- if (cxt->flags & MNT_FL_SAVED_USER) -- rc = mnt_optstr_set_option(optstr, "user", cxt->orig_user); -- if (rc) -- goto err; -- -- /* remove userspace options with MNT_NOHLPS flag */ -- maps[0] = mnt_get_builtin_optmap(MNT_USERSPACE_MAP); -- maps[1] = mnt_get_builtin_optmap(MNT_LINUX_MAP); -- next = *optstr; -- -- while (!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) { -- const struct libmnt_optmap *ent; -- -- mnt_optmap_get_entry(maps, 2, name, namesz, &ent); -- if (ent && ent->id && (ent->mask & MNT_NOHLPS)) { -- next = name; -- rc = mnt_optstr_remove_option_at(optstr, name, -- val ? val + valsz : name + namesz); -- if (rc) -- goto err; -- } -- } -+ struct libmnt_optmap const *maps[2]; -+ char *next, *name, *val; -+ size_t namesz, valsz; -+ int rc = 0; -+ -+ assert(cxt); -+ assert(cxt->fs); -+ assert(optstr); -+ -+ DBG(CXT, ul_debugobj(cxt, "mount: generate helper mount options")); -+ -+ *optstr = mnt_fs_strdup_options(cxt->fs); -+ if (!*optstr) -+ return -ENOMEM; -+ -+ if ((cxt->user_mountflags & MNT_MS_USER) || -+ (cxt->user_mountflags & MNT_MS_USERS)) { -+ /* -+ * This is unnecessary for real user-mounts as mount.<type> -+ * helpers always have to follow fstab rather than mount -+ * options on the command line. -+ * -+ * However, if you call mount.<type> as root, then the helper follows -+ * the command line. If there is (for example) "user,exec" in fstab, -+ * then we have to manually append the "exec" back to the options -+ * string, because there is nothing like MS_EXEC (we only have -+ * MS_NOEXEC in mount flags and we don't care about the original -+ * mount string in libmount for VFS options). -+ * -+ * This use-case makes sense for MS_SECURE flags only (see -++ * mnt_optstr_get_flags() and mnt_context_merge_mflags()). -+ */ -+ if (!(cxt->mountflags & MS_NOEXEC)) -+ mnt_optstr_append_option(optstr, "exec", NULL); -+ if (!(cxt->mountflags & MS_NOSUID)) -+ mnt_optstr_append_option(optstr, "suid", NULL); -+ if (!(cxt->mountflags & MS_NODEV)) -+ mnt_optstr_append_option(optstr, "dev", NULL); -+ } -+ -+ if (cxt->flags & MNT_FL_SAVED_USER) -+ rc = mnt_optstr_set_option(optstr, "user", cxt->orig_user); -+ if (rc) -+ goto err; -+ -+ /* remove userspace options with MNT_NOHLPS flag */ -+ maps[0] = mnt_get_builtin_optmap(MNT_USERSPACE_MAP); -+ maps[1] = mnt_get_builtin_optmap(MNT_LINUX_MAP); -+ next = *optstr; -+ -+ while (!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) { -+ const struct libmnt_optmap *ent; -+ -+ mnt_optmap_get_entry(maps, 2, name, namesz, &ent); -+ if (ent && ent->id && (ent->mask & MNT_NOHLPS)) { -+ next = name; -+ rc = mnt_optstr_remove_option_at(optstr, name, -+ val ? val + valsz : name + namesz); -+ if (rc) -+ goto err; -+ } -+ } - -- return rc; -+ return rc; - err: -- free(*optstr); -- *optstr = NULL; -- return rc; -+ free(*optstr); -+ *optstr = NULL; -+ return rc; - } - - /* -@@ -466,95 +466,95 @@ - */ - static int evaluate_permissions(struct libmnt_context *cxt) - { -- unsigned long u_flags = 0; -+ unsigned long u_flags = 0; - -- assert(cxt); -- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -+ assert(cxt); -+ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); - -- if (!cxt->fs) -- return 0; -+ if (!cxt->fs) -+ return 0; - -- DBG(CXT, ul_debugobj(cxt, "mount: evaluating permissions")); -- -- mnt_context_get_user_mflags(cxt, &u_flags); -- -- if (!mnt_context_is_restricted(cxt)) { -- /* -- * superuser mount -- */ -- cxt->user_mountflags &= ~MNT_MS_OWNER; -- cxt->user_mountflags &= ~MNT_MS_GROUP; -- } else { -- /* -- * user mount -- */ -- if (!mnt_context_tab_applied(cxt)) -- { -- DBG(CXT, ul_debugobj(cxt, "perms: fstab not applied, ignore user mount")); -- return -EPERM; -- } -- -- /* -- * MS_OWNERSECURE and MS_SECURE mount options are already -- * applied by mnt_optstr_get_flags() in mnt_context_merge_mflags() -- * if "user" (but no user=<name> !) options is set. -- * -- * Let's ignore all user=<name> (if <name> is set) requests. -- */ -- if (cxt->user_mountflags & MNT_MS_USER) { -- size_t valsz = 0; -- -- if (!mnt_optstr_get_option(cxt->fs->user_optstr, -- "user", NULL, &valsz) && valsz) { -- -- DBG(CXT, ul_debugobj(cxt, "perms: user=<name> detected, ignore")); -- cxt->user_mountflags &= ~MNT_MS_USER; -- } -- } -- -- /* -- * MS_OWNER: Allow owners to mount when fstab contains the -- * owner option. Note that this should never be used in a high -- * security environment, but may be useful to give people at -- * the console the possibility of mounting a floppy. MS_GROUP: -- * Allow members of device group to mount. (Martin Dickopp) -- */ -- if (u_flags & (MNT_MS_OWNER | MNT_MS_GROUP)) { -- struct stat sb; -- struct libmnt_cache *cache = NULL; -- char *xsrc = NULL; -- const char *srcpath = mnt_fs_get_srcpath(cxt->fs); -- -- if (!srcpath) { /* Ah... source is TAG */ -- cache = mnt_context_get_cache(cxt); -- xsrc = mnt_resolve_spec( -- mnt_context_get_source(cxt), -- cache); -- srcpath = xsrc; -- } -- if (!srcpath) { -- DBG(CXT, ul_debugobj(cxt, "perms: src undefined")); -- return -EPERM; -- } -- -- if (strncmp(srcpath, "/dev/", 5) == 0 && -- stat(srcpath, &sb) == 0 && -- (((u_flags & MNT_MS_OWNER) && getuid() == sb.st_uid) || -- ((u_flags & MNT_MS_GROUP) && mnt_in_group(sb.st_gid)))) -- -- cxt->user_mountflags |= MNT_MS_USER; -- -- if (!cache) -- free(xsrc); -- } -- -- if (!(cxt->user_mountflags & (MNT_MS_USER | MNT_MS_USERS))) { -- DBG(CXT, ul_debugobj(cxt, "permissions evaluation ends with -EPERMS")); -- return -EPERM; -- } -- } -+ DBG(CXT, ul_debugobj(cxt, "mount: evaluating permissions")); -+ -+ mnt_context_get_user_mflags(cxt, &u_flags); -+ -+ if (!mnt_context_is_restricted(cxt)) { -+ /* -+ * superuser mount -+ */ -+ cxt->user_mountflags &= ~MNT_MS_OWNER; -+ cxt->user_mountflags &= ~MNT_MS_GROUP; -+ } else { -+ /* -+ * user mount -+ */ -+ if (!mnt_context_tab_applied(cxt)) -+ { -+ DBG(CXT, ul_debugobj(cxt, "perms: fstab not applied, ignore user mount")); -+ return -EPERM; -+ } -+ -+ /* -+ * MS_OWNERSECURE and MS_SECURE mount options are already -+ * applied by mnt_optstr_get_flags() in mnt_context_merge_mflags() -+ * if "user" (but no user=<name> !) options is set. -+ * -+ * Let's ignore all user=<name> (if <name> is set) requests. -+ */ -+ if (cxt->user_mountflags & MNT_MS_USER) { -+ size_t valsz = 0; -+ -+ if (!mnt_optstr_get_option(cxt->fs->user_optstr, -+ "user", NULL, &valsz) && valsz) { -+ -+ DBG(CXT, ul_debugobj(cxt, "perms: user=<name> detected, ignore")); -+ cxt->user_mountflags &= ~MNT_MS_USER; -+ } -+ } -+ -+ /* -+ * MS_OWNER: Allow owners to mount when fstab contains the -+ * owner option. Note that this should never be used in a high -+ * security environment, but may be useful to give people at -+ * the console the possibility of mounting a floppy. MS_GROUP: -+ * Allow members of device group to mount. (Martin Dickopp) -+ */ -+ if (u_flags & (MNT_MS_OWNER | MNT_MS_GROUP)) { -+ struct stat sb; -+ struct libmnt_cache *cache = NULL; -+ char *xsrc = NULL; -+ const char *srcpath = mnt_fs_get_srcpath(cxt->fs); -+ -+ if (!srcpath) { /* Ah... source is TAG */ -+ cache = mnt_context_get_cache(cxt); -+ xsrc = mnt_resolve_spec( -+ mnt_context_get_source(cxt), -+ cache); -+ srcpath = xsrc; -+ } -+ if (!srcpath) { -+ DBG(CXT, ul_debugobj(cxt, "perms: src undefined")); -+ return -EPERM; -+ } -+ -+ if (strncmp(srcpath, "/dev/", 5) == 0 && -+ stat(srcpath, &sb) == 0 && -+ (((u_flags & MNT_MS_OWNER) && getuid() == sb.st_uid) || -+ ((u_flags & MNT_MS_GROUP) && mnt_in_group(sb.st_gid)))) -+ -+ cxt->user_mountflags |= MNT_MS_USER; -+ -+ if (!cache) -+ free(xsrc); -+ } -+ -+ if (!(cxt->user_mountflags & (MNT_MS_USER | MNT_MS_USERS))) { -+ DBG(CXT, ul_debugobj(cxt, "permissions evaluation ends with -EPERMS")); -+ return -EPERM; -+ } -+ } - -- return 0; -+ return 0; - } - - /* -@@ -568,191 +568,191 @@ - */ - int mnt_context_mount_setopt(struct libmnt_context *cxt, int c, char *arg) - { -- int rc = -EINVAL; -+ int rc = -EINVAL; - -- assert(cxt); -- assert(cxt->action == MNT_ACT_MOUNT); -+ assert(cxt); -+ assert(cxt->action == MNT_ACT_MOUNT); - -- switch(c) { -- case 'f': -- rc = mnt_context_enable_fake(cxt, TRUE); -- break; -- case 'n': -- rc = mnt_context_disable_mtab(cxt, TRUE); -- break; -- case 'r': -- rc = mnt_context_append_options(cxt, "ro"); -- break; -- case 'v': -- rc = mnt_context_enable_verbose(cxt, TRUE); -- break; -- case 'w': -- rc = mnt_context_append_options(cxt, "rw"); -- break; -- case 'o': -- if (arg) -- rc = mnt_context_append_options(cxt, arg); -- break; -- case 's': -- rc = mnt_context_enable_sloppy(cxt, TRUE); -- break; -- case 't': -- if (arg) -- rc = mnt_context_set_fstype(cxt, arg); -- break; -- case 'N': -- if (arg) -- rc = mnt_context_set_target_ns(cxt, arg); -- break; -- default: -- return 1; -- } -+ switch(c) { -+ case 'f': -+ rc = mnt_context_enable_fake(cxt, TRUE); -+ break; -+ case 'n': -+ rc = mnt_context_disable_mtab(cxt, TRUE); -+ break; -+ case 'r': -+ rc = mnt_context_append_options(cxt, "ro"); -+ break; -+ case 'v': -+ rc = mnt_context_enable_verbose(cxt, TRUE); -+ break; -+ case 'w': -+ rc = mnt_context_append_options(cxt, "rw"); -+ break; -+ case 'o': -+ if (arg) -+ rc = mnt_context_append_options(cxt, arg); -+ break; -+ case 's': -+ rc = mnt_context_enable_sloppy(cxt, TRUE); -+ break; -+ case 't': -+ if (arg) -+ rc = mnt_context_set_fstype(cxt, arg); -+ break; -+ case 'N': -+ if (arg) -+ rc = mnt_context_set_target_ns(cxt, arg); -+ break; -+ default: -+ return 1; -+ } - -- return rc; -+ return rc; - } - - static int exec_helper(struct libmnt_context *cxt) - { -- char *o = NULL, *namespace = NULL; -- struct libmnt_ns *ns_tgt = mnt_context_get_target_ns(cxt); -- int rc; -- pid_t pid; -- -- assert(cxt); -- assert(cxt->fs); -- assert(cxt->helper); -- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -- -- DBG(CXT, ul_debugobj(cxt, "mount: executing helper %s", cxt->helper)); -- -- rc = generate_helper_optstr(cxt, &o); -- if (rc) -- return -EINVAL; -- -- if (ns_tgt->fd != -1 -- && asprintf(&namespace, "/proc/%i/fd/%i", -- getpid(), ns_tgt->fd) == -1) { -- free(o); -- return -ENOMEM; -- } -- -- DBG_FLUSH; -- -- pid = fork(); -- switch (pid) { -- case 0: -- { -- const char *args[14], *type; -- int i = 0; -- -- if (setgid(getgid()) < 0) -- _exit(EXIT_FAILURE); -- -- if (setuid(getuid()) < 0) -- _exit(EXIT_FAILURE); -- -- if (!mnt_context_switch_origin_ns(cxt)) -- _exit(EXIT_FAILURE); -- -- type = mnt_fs_get_fstype(cxt->fs); -- -- args[i++] = cxt->helper; /* 1 */ -- args[i++] = mnt_fs_get_srcpath(cxt->fs);/* 2 */ -- args[i++] = mnt_fs_get_target(cxt->fs); /* 3 */ -- -- if (mnt_context_is_sloppy(cxt)) -- args[i++] = "-s"; /* 4 */ -- if (mnt_context_is_fake(cxt)) -- args[i++] = "-f"; /* 5 */ -- if (mnt_context_is_nomtab(cxt)) -- args[i++] = "-n"; /* 6 */ -- if (mnt_context_is_verbose(cxt)) -- args[i++] = "-v"; /* 7 */ -- if (o) { -- args[i++] = "-o"; /* 8 */ -- args[i++] = o; /* 9 */ -- } -- if (type -- && strchr(type, '.') -- && !endswith(cxt->helper, type)) { -- args[i++] = "-t"; /* 10 */ -- args[i++] = type; /* 11 */ -- } -- if (namespace) { -- args[i++] = "-N"; /* 11 */ -- args[i++] = namespace; /* 12 */ -- } -- args[i] = NULL; /* 13 */ -- for (i = 0; args[i]; i++) -- DBG(CXT, ul_debugobj(cxt, "argv[%d] = \"%s\"", -- i, args[i])); -- DBG_FLUSH; -- execv(cxt->helper, (char * const *) args); -- _exit(EXIT_FAILURE); -- } -- default: -- { -- int st; -- -- if (waitpid(pid, &st, 0) == (pid_t) -1) { -- cxt->helper_status = -1; -- rc = -errno; -- } else { -- cxt->helper_status = WIFEXITED(st) ? WEXITSTATUS(st) : -1; -- cxt->helper_exec_status = rc = 0; -- } -- DBG(CXT, ul_debugobj(cxt, "%s executed [status=%d, rc=%d%s]", -- cxt->helper, -- cxt->helper_status, rc, -- rc ? " waitpid failed" : "")); -- break; -- } -- -- case -1: -- cxt->helper_exec_status = rc = -errno; -- DBG(CXT, ul_debugobj(cxt, "fork() failed")); -- break; -- } -+ char *o = NULL, *namespace = NULL; -+ struct libmnt_ns *ns_tgt = mnt_context_get_target_ns(cxt); -+ int rc; -+ pid_t pid; -+ -+ assert(cxt); -+ assert(cxt->fs); -+ assert(cxt->helper); -+ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -+ -+ DBG(CXT, ul_debugobj(cxt, "mount: executing helper %s", cxt->helper)); -+ -+ rc = generate_helper_optstr(cxt, &o); -+ if (rc) -+ return -EINVAL; -+ -+ if (ns_tgt->fd != -1 -+ && asprintf(&namespace, "/proc/%i/fd/%i", -+ getpid(), ns_tgt->fd) == -1) { -+ free(o); -+ return -ENOMEM; -+ } -+ -+ DBG_FLUSH; -+ -+ pid = fork(); -+ switch (pid) { -+ case 0: -+ { -+ const char *args[14], *type; -+ int i = 0; -+ -+ if (setgid(getgid()) < 0) -+ _exit(EXIT_FAILURE); -+ -+ if (setuid(getuid()) < 0) -+ _exit(EXIT_FAILURE); -+ -+ if (!mnt_context_switch_origin_ns(cxt)) -+ _exit(EXIT_FAILURE); -+ -+ type = mnt_fs_get_fstype(cxt->fs); -+ -+ args[i++] = cxt->helper; /* 1 */ -+ args[i++] = mnt_fs_get_srcpath(cxt->fs);/* 2 */ -+ args[i++] = mnt_fs_get_target(cxt->fs); /* 3 */ -+ -+ if (mnt_context_is_sloppy(cxt)) -+ args[i++] = "-s"; /* 4 */ -+ if (mnt_context_is_fake(cxt)) -+ args[i++] = "-f"; /* 5 */ -+ if (mnt_context_is_nomtab(cxt)) -+ args[i++] = "-n"; /* 6 */ -+ if (mnt_context_is_verbose(cxt)) -+ args[i++] = "-v"; /* 7 */ -+ if (o) { -+ args[i++] = "-o"; /* 8 */ -+ args[i++] = o; /* 9 */ -+ } -+ if (type -+ && strchr(type, '.') -+ && !endswith(cxt->helper, type)) { -+ args[i++] = "-t"; /* 10 */ -+ args[i++] = type; /* 11 */ -+ } -+ if (namespace) { -+ args[i++] = "-N"; /* 11 */ -+ args[i++] = namespace; /* 12 */ -+ } -+ args[i] = NULL; /* 13 */ -+ for (i = 0; args[i]; i++) -+ DBG(CXT, ul_debugobj(cxt, "argv[%d] = \"%s\"", -+ i, args[i])); -+ DBG_FLUSH; -+ execv(cxt->helper, (char * const *) args); -+ _exit(EXIT_FAILURE); -+ } -+ default: -+ { -+ int st; -+ -+ if (waitpid(pid, &st, 0) == (pid_t) -1) { -+ cxt->helper_status = -1; -+ rc = -errno; -+ } else { -+ cxt->helper_status = WIFEXITED(st) ? WEXITSTATUS(st) : -1; -+ cxt->helper_exec_status = rc = 0; -+ } -+ DBG(CXT, ul_debugobj(cxt, "%s executed [status=%d, rc=%d%s]", -+ cxt->helper, -+ cxt->helper_status, rc, -+ rc ? " waitpid failed" : "")); -+ break; -+ } -+ -+ case -1: -+ cxt->helper_exec_status = rc = -errno; -+ DBG(CXT, ul_debugobj(cxt, "fork() failed")); -+ break; -+ } - -- free(o); -- return rc; -+ free(o); -+ return rc; - } - - static int do_mount_additional(struct libmnt_context *cxt, -- const char *target, -- unsigned long flags, -- int *syserr) --{ -- struct list_head *p; -- -- assert(cxt); -- assert(target); -- -- if (syserr) -- *syserr = 0; -- -- list_for_each(p, &cxt->addmounts) { -- int rc; -- struct libmnt_addmount *ad = -- list_entry(p, struct libmnt_addmount, mounts); -- -- DBG(CXT, ul_debugobj(cxt, "mount(2) changing flag: 0x%08lx %s", -- ad->mountflags, -- ad->mountflags & MS_REC ? " (recursive)" : "")); -- -- rc = mount("none", target, NULL, -- ad->mountflags | (flags & MS_SILENT), NULL); -- if (rc) { -- if (syserr) -- *syserr = -errno; -- DBG(CXT, ul_debugobj(cxt, -- "mount(2) failed [errno=%d %m]", -- errno)); -- return rc; -- } -- } -+ const char *target, -+ unsigned long flags, -+ int *syserr) -+{ -+ struct list_head *p; -+ -+ assert(cxt); -+ assert(target); -+ -+ if (syserr) -+ *syserr = 0; -+ -+ list_for_each(p, &cxt->addmounts) { -+ int rc; -+ struct libmnt_addmount *ad = -+ list_entry(p, struct libmnt_addmount, mounts); -+ -+ DBG(CXT, ul_debugobj(cxt, "mount(2) changing flag: 0x%08lx %s", -+ ad->mountflags, -+ ad->mountflags & MS_REC ? " (recursive)" : "")); -+ -+ rc = mount("none", target, NULL, -+ ad->mountflags | (flags & MS_SILENT), NULL); -+ if (rc) { -+ if (syserr) -+ *syserr = -errno; -+ DBG(CXT, ul_debugobj(cxt, -+ "mount(2) failed [errno=%d %m]", -+ errno)); -+ return rc; -+ } -+ } - -- return 0; -+ return 0; - } - - /* -@@ -765,193 +765,193 @@ - */ - static int do_mount(struct libmnt_context *cxt, const char *try_type) - { -- int rc = 0; -- const char *src, *target, *type; -- unsigned long flags; -- -- assert(cxt); -- assert(cxt->fs); -- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -- -- if (try_type && !cxt->helper) { -- rc = mnt_context_prepare_helper(cxt, "mount", try_type); -- if (rc) -- return rc; -- } -- -- flags = cxt->mountflags; -- src = mnt_fs_get_srcpath(cxt->fs); -- target = mnt_fs_get_target(cxt->fs); -- -- if (cxt->helper) { -- rc = exec_helper(cxt); -- -- if (mnt_context_helper_executed(cxt) -- && mnt_context_get_helper_status(cxt) == 0 -- && !list_empty(&cxt->addmounts) -- && do_mount_additional(cxt, target, flags, NULL)) -- -- return -MNT_ERR_APPLYFLAGS; -- return rc; -- } -- -- if (!target) -- return -EINVAL; -- if (!src) { -- /* unnecessary, should be already resolved in -- * mnt_context_prepare_srcpath(), but to be sure... */ -- DBG(CXT, ul_debugobj(cxt, "WARNING: source is NULL -- using \"none\"!")); -- src = "none"; -- } -- type = try_type ? : mnt_fs_get_fstype(cxt->fs); -- -- if (try_type) -- flags |= MS_SILENT; -- -- DBG(CXT, ul_debugobj(cxt, "%smount(2) " -- "[source=%s, target=%s, type=%s, " -- " mountflags=0x%08lx, mountdata=%s]", -- mnt_context_is_fake(cxt) ? "(FAKE) " : "", -- src, target, type, -- flags, cxt->mountdata ? "yes" : "<none>")); -- -- if (mnt_context_is_fake(cxt)) { -- /* -- * fake -- */ -- cxt->syscall_status = 0; -- -- } else if (mnt_context_propagation_only(cxt)) { -- /* -- * propagation flags *only* -- */ -- if (do_mount_additional(cxt, target, flags, &cxt->syscall_status)) -- return -MNT_ERR_APPLYFLAGS; -- } else { -- /* -- * regular mount -- */ -- if (mount(src, target, type, flags, cxt->mountdata)) { -- cxt->syscall_status = -errno; -- DBG(CXT, ul_debugobj(cxt, "mount(2) failed [errno=%d %m]", -- -cxt->syscall_status)); -- return -cxt->syscall_status; -- } -- DBG(CXT, ul_debugobj(cxt, " success")); -- cxt->syscall_status = 0; -- -- /* -- * additional mounts for extra propagation flags -- */ -- if (!list_empty(&cxt->addmounts) -- && do_mount_additional(cxt, target, flags, NULL)) { -- -- /* TODO: call umount? */ -- return -MNT_ERR_APPLYFLAGS; -- } -- } -- -- if (try_type && cxt->update) { -- struct libmnt_fs *fs = mnt_update_get_fs(cxt->update); -- if (fs) -- rc = mnt_fs_set_fstype(fs, try_type); -- } -+ int rc = 0; -+ const char *src, *target, *type; -+ unsigned long flags; -+ -+ assert(cxt); -+ assert(cxt->fs); -+ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -+ -+ if (try_type && !cxt->helper) { -+ rc = mnt_context_prepare_helper(cxt, "mount", try_type); -+ if (rc) -+ return rc; -+ } -+ -+ flags = cxt->mountflags; -+ src = mnt_fs_get_srcpath(cxt->fs); -+ target = mnt_fs_get_target(cxt->fs); -+ -+ if (cxt->helper) { -+ rc = exec_helper(cxt); -+ -+ if (mnt_context_helper_executed(cxt) -+ && mnt_context_get_helper_status(cxt) == 0 -+ && !list_empty(&cxt->addmounts) -+ && do_mount_additional(cxt, target, flags, NULL)) -+ -+ return -MNT_ERR_APPLYFLAGS; -+ return rc; -+ } -+ -+ if (!target) -+ return -EINVAL; -+ if (!src) { -+ /* unnecessary, should be already resolved in -+ * mnt_context_prepare_srcpath(), but to be sure... */ -+ DBG(CXT, ul_debugobj(cxt, "WARNING: source is NULL -- using \"none\"!")); -+ src = "none"; -+ } -+ type = try_type ? : mnt_fs_get_fstype(cxt->fs); -+ -+ if (try_type) -+ flags |= MS_SILENT; -+ -+ DBG(CXT, ul_debugobj(cxt, "%smount(2) " -+ "[source=%s, target=%s, type=%s, " -+ " mountflags=0x%08lx, mountdata=%s]", -+ mnt_context_is_fake(cxt) ? "(FAKE) " : "", -+ src, target, type, -+ flags, cxt->mountdata ? "yes" : "<none>")); -+ -+ if (mnt_context_is_fake(cxt)) { -+ /* -+ * fake -+ */ -+ cxt->syscall_status = 0; -+ -+ } else if (mnt_context_propagation_only(cxt)) { -+ /* -+ * propagation flags *only* -+ */ -+ if (do_mount_additional(cxt, target, flags, &cxt->syscall_status)) -+ return -MNT_ERR_APPLYFLAGS; -+ } else { -+ /* -+ * regular mount -+ */ -+ if (mount(src, target, type, flags, cxt->mountdata)) { -+ cxt->syscall_status = -errno; -+ DBG(CXT, ul_debugobj(cxt, "mount(2) failed [errno=%d %m]", -+ -cxt->syscall_status)); -+ return -cxt->syscall_status; -+ } -+ DBG(CXT, ul_debugobj(cxt, " success")); -+ cxt->syscall_status = 0; -+ -+ /* -+ * additional mounts for extra propagation flags -+ */ -+ if (!list_empty(&cxt->addmounts) -+ && do_mount_additional(cxt, target, flags, NULL)) { -+ -+ /* TODO: call umount? */ -+ return -MNT_ERR_APPLYFLAGS; -+ } -+ } -+ -+ if (try_type && cxt->update) { -+ struct libmnt_fs *fs = mnt_update_get_fs(cxt->update); -+ if (fs) -+ rc = mnt_fs_set_fstype(fs, try_type); -+ } - -- return rc; -+ return rc; - } - - /* try mount(2) for all items in comma separated list of the filesystem @types */ - static int do_mount_by_types(struct libmnt_context *cxt, const char *types) - { -- int rc = -EINVAL; -- char *p, *p0; -+ int rc = -EINVAL; -+ char *p, *p0; - -- assert(cxt); -- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -+ assert(cxt); -+ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); - -- DBG(CXT, ul_debugobj(cxt, "trying to mount by FS list '%s'", types)); -+ DBG(CXT, ul_debugobj(cxt, "trying to mount by FS list '%s'", types)); - -- p0 = p = strdup(types); -- if (!p) -- return -ENOMEM; -- do { -- char *autotype = NULL; -- char *end = strchr(p, ','); -- -- if (end) -- *end = '\0'; -- -- DBG(CXT, ul_debugobj(cxt, "-->trying '%s'", p)); -- -- /* Let's support things like "udf,iso9660,auto" */ -- if (strcmp(p, "auto") == 0) { -- rc = mnt_context_guess_srcpath_fstype(cxt, &autotype); -- if (rc) { -- DBG(CXT, ul_debugobj(cxt, "failed to guess FS type [rc=%d]", rc)); -- free(p0); -- free(autotype); -- return rc; -- } -- p = autotype; -- DBG(CXT, ul_debugobj(cxt, " --> '%s'", p)); -- } -- -- if (p) -- rc = do_mount(cxt, p); -- p = end ? end + 1 : NULL; -- free(autotype); -- } while (!mnt_context_get_status(cxt) && p); -+ p0 = p = strdup(types); -+ if (!p) -+ return -ENOMEM; -+ do { -+ char *autotype = NULL; -+ char *end = strchr(p, ','); -+ -+ if (end) -+ *end = '\0'; -+ -+ DBG(CXT, ul_debugobj(cxt, "-->trying '%s'", p)); -+ -+ /* Let's support things like "udf,iso9660,auto" */ -+ if (strcmp(p, "auto") == 0) { -+ rc = mnt_context_guess_srcpath_fstype(cxt, &autotype); -+ if (rc) { -+ DBG(CXT, ul_debugobj(cxt, "failed to guess FS type [rc=%d]", rc)); -+ free(p0); -+ free(autotype); -+ return rc; -+ } -+ p = autotype; -+ DBG(CXT, ul_debugobj(cxt, " --> '%s'", p)); -+ } -+ -+ if (p) -+ rc = do_mount(cxt, p); -+ p = end ? end + 1 : NULL; -+ free(autotype); -+ } while (!mnt_context_get_status(cxt) && p); - -- free(p0); -- return rc; -+ free(p0); -+ return rc; - } - - - static int do_mount_by_pattern(struct libmnt_context *cxt, const char *pattern) - { -- int neg = pattern && strncmp(pattern, "no", 2) == 0; -- int rc = -EINVAL; -- char **filesystems, **fp; -- struct libmnt_ns *ns_old; -- -- assert(cxt); -- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -- -- /* -- * Use the pattern as list of the filesystems -- */ -- if (!neg && pattern) { -- DBG(CXT, ul_debugobj(cxt, "use FS pattern as FS list")); -- return do_mount_by_types(cxt, pattern); -- } -- -- DBG(CXT, ul_debugobj(cxt, "trying to mount by FS pattern '%s'", pattern)); -- -- /* -- * Apply pattern to /etc/filesystems and /proc/filesystems -- */ -- ns_old = mnt_context_switch_origin_ns(cxt); -- if (!ns_old) -- return -MNT_ERR_NAMESPACE; -- rc = mnt_get_filesystems(&filesystems, neg ? pattern : NULL); -- if (!mnt_context_switch_ns(cxt, ns_old)) -- return -MNT_ERR_NAMESPACE; -- if (rc) -- return rc; -- -- if (filesystems == NULL) -- return -MNT_ERR_NOFSTYPE; -- -- for (fp = filesystems; *fp; fp++) { -- rc = do_mount(cxt, *fp); -- if (mnt_context_get_status(cxt)) -- break; -- if (mnt_context_get_syscall_errno(cxt) != EINVAL && -- mnt_context_get_syscall_errno(cxt) != ENODEV) -- break; -- } -- mnt_free_filesystems(filesystems); -- return rc; -+ int neg = pattern && strncmp(pattern, "no", 2) == 0; -+ int rc = -EINVAL; -+ char **filesystems, **fp; -+ struct libmnt_ns *ns_old; -+ -+ assert(cxt); -+ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -+ -+ /* -+ * Use the pattern as list of the filesystems -+ */ -+ if (!neg && pattern) { -+ DBG(CXT, ul_debugobj(cxt, "use FS pattern as FS list")); -+ return do_mount_by_types(cxt, pattern); -+ } -+ -+ DBG(CXT, ul_debugobj(cxt, "trying to mount by FS pattern '%s'", pattern)); -+ -+ /* -+ * Apply pattern to /etc/filesystems and /proc/filesystems -+ */ -+ ns_old = mnt_context_switch_origin_ns(cxt); -+ if (!ns_old) -+ return -MNT_ERR_NAMESPACE; -+ rc = mnt_get_filesystems(&filesystems, neg ? pattern : NULL); -+ if (!mnt_context_switch_ns(cxt, ns_old)) -+ return -MNT_ERR_NAMESPACE; -+ if (rc) -+ return rc; -+ -+ if (filesystems == NULL) -+ return -MNT_ERR_NOFSTYPE; -+ -+ for (fp = filesystems; *fp; fp++) { -+ rc = do_mount(cxt, *fp); -+ if (mnt_context_get_status(cxt)) -+ break; -+ if (mnt_context_get_syscall_errno(cxt) != EINVAL && -+ mnt_context_get_syscall_errno(cxt) != ENODEV) -+ break; -+ } -+ mnt_free_filesystems(filesystems); -+ return rc; - } - - /** -@@ -964,53 +964,53 @@ - */ - int mnt_context_prepare_mount(struct libmnt_context *cxt) - { -- int rc = -EINVAL; -- struct libmnt_ns *ns_old; -+ int rc = -EINVAL; -+ struct libmnt_ns *ns_old; - -- if (!cxt || !cxt->fs || mnt_fs_is_swaparea(cxt->fs)) -- return -EINVAL; -- if (!mnt_fs_get_source(cxt->fs) && !mnt_fs_get_target(cxt->fs)) -- return -EINVAL; -- if (cxt->flags & MNT_FL_PREPARED) -- return 0; -- -- assert(cxt->helper_exec_status == 1); -- assert(cxt->syscall_status == 1); -- -- cxt->action = MNT_ACT_MOUNT; -- -- ns_old = mnt_context_switch_target_ns(cxt); -- if (!ns_old) -- return -MNT_ERR_NAMESPACE; -- -- DBG(CXT, ul_debugobj(cxt, "mount: preparing")); -- -- rc = mnt_context_apply_fstab(cxt); -- if (!rc) -- rc = mnt_context_merge_mflags(cxt); -- if (!rc) -- rc = evaluate_permissions(cxt); -- if (!rc) -- rc = fix_optstr(cxt); -- if (!rc) -- rc = mnt_context_prepare_srcpath(cxt); -- if (!rc) -- rc = mnt_context_guess_fstype(cxt); -- if (!rc) -- rc = mnt_context_prepare_target(cxt); -- if (!rc) -- rc = mnt_context_prepare_helper(cxt, "mount", NULL); -- if (rc) { -- DBG(CXT, ul_debugobj(cxt, "mount: preparing failed")); -- goto end; -- } -- cxt->flags |= MNT_FL_PREPARED; -+ if (!cxt || !cxt->fs || mnt_fs_is_swaparea(cxt->fs)) -+ return -EINVAL; -+ if (!mnt_fs_get_source(cxt->fs) && !mnt_fs_get_target(cxt->fs)) -+ return -EINVAL; -+ if (cxt->flags & MNT_FL_PREPARED) -+ return 0; -+ -+ assert(cxt->helper_exec_status == 1); -+ assert(cxt->syscall_status == 1); -+ -+ cxt->action = MNT_ACT_MOUNT; -+ -+ ns_old = mnt_context_switch_target_ns(cxt); -+ if (!ns_old) -+ return -MNT_ERR_NAMESPACE; -+ -+ DBG(CXT, ul_debugobj(cxt, "mount: preparing")); -+ -+ rc = mnt_context_apply_fstab(cxt); -+ if (!rc) -+ rc = mnt_context_merge_mflags(cxt); -+ if (!rc) -+ rc = evaluate_permissions(cxt); -+ if (!rc) -+ rc = fix_optstr(cxt); -+ if (!rc) -+ rc = mnt_context_prepare_srcpath(cxt); -+ if (!rc) -+ rc = mnt_context_guess_fstype(cxt); -+ if (!rc) -+ rc = mnt_context_prepare_target(cxt); -+ if (!rc) -+ rc = mnt_context_prepare_helper(cxt, "mount", NULL); -+ if (rc) { -+ DBG(CXT, ul_debugobj(cxt, "mount: preparing failed")); -+ goto end; -+ } -+ cxt->flags |= MNT_FL_PREPARED; - - end: -- if (!mnt_context_switch_ns(cxt, ns_old)) -- return -MNT_ERR_NAMESPACE; -+ if (!mnt_context_switch_ns(cxt, ns_old)) -+ return -MNT_ERR_NAMESPACE; - -- return rc; -+ return rc; - } - - /** -@@ -1038,87 +1038,87 @@ - */ - int mnt_context_do_mount(struct libmnt_context *cxt) - { -- const char *type; -- int res; -- struct libmnt_ns *ns_old; -- -- assert(cxt); -- assert(cxt->fs); -- assert(cxt->helper_exec_status == 1); -- assert(cxt->syscall_status == 1); -- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -- assert((cxt->flags & MNT_FL_PREPARED)); -- assert((cxt->action == MNT_ACT_MOUNT)); -- -- DBG(CXT, ul_debugobj(cxt, "mount: do mount")); -- -- if (!(cxt->flags & MNT_FL_MOUNTDATA)) -- cxt->mountdata = (char *) mnt_fs_get_fs_options(cxt->fs); -- -- ns_old = mnt_context_switch_target_ns(cxt); -- if (!ns_old) -- return -MNT_ERR_NAMESPACE; -- -- type = mnt_fs_get_fstype(cxt->fs); -- if (type) { -- if (strchr(type, ',')) -- /* this only happens if fstab contains a list of filesystems */ -- res = do_mount_by_types(cxt, type); -- else -- res = do_mount(cxt, NULL); -- } else -- res = do_mount_by_pattern(cxt, cxt->fstype_pattern); -+ const char *type; -+ int res; -+ struct libmnt_ns *ns_old; -+ -+ assert(cxt); -+ assert(cxt->fs); -+ assert(cxt->helper_exec_status == 1); -+ assert(cxt->syscall_status == 1); -+ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -+ assert((cxt->flags & MNT_FL_PREPARED)); -+ assert((cxt->action == MNT_ACT_MOUNT)); -+ -+ DBG(CXT, ul_debugobj(cxt, "mount: do mount")); -+ -+ if (!(cxt->flags & MNT_FL_MOUNTDATA)) -+ cxt->mountdata = (char *) mnt_fs_get_fs_options(cxt->fs); -+ -+ ns_old = mnt_context_switch_target_ns(cxt); -+ if (!ns_old) -+ return -MNT_ERR_NAMESPACE; -+ -+ type = mnt_fs_get_fstype(cxt->fs); -+ if (type) { -+ if (strchr(type, ',')) -+ /* this only happens if fstab contains a list of filesystems */ -+ res = do_mount_by_types(cxt, type); -+ else -+ res = do_mount(cxt, NULL); -+ } else -+ res = do_mount_by_pattern(cxt, cxt->fstype_pattern); - - #ifdef USE_LIBMOUNT_SUPPORT_MTAB -- if (mnt_context_get_status(cxt) -- && !mnt_context_is_fake(cxt) -- && !cxt->helper -- && mnt_context_mtab_writable(cxt)) { -- -- int is_rdonly = -1; -- -- DBG(CXT, ul_debugobj(cxt, "checking for RDONLY mismatch")); -- -- /* -- * Mounted by mount(2), do some post-mount checks -- * -- * Kernel can be used to use MS_RDONLY for bind mounts, but the -- * read-only request could be silently ignored. Check it to -- * avoid 'ro' in mtab and 'rw' in /proc/mounts. -- */ -- if ((cxt->mountflags & MS_BIND) -- && (cxt->mountflags & MS_RDONLY)) { -- -- if (is_rdonly < 0) -- is_rdonly = mnt_is_readonly(mnt_context_get_target(cxt)); -- if (!is_rdonly) -- mnt_context_set_mflags(cxt, cxt->mountflags & ~MS_RDONLY); -- } -- -- -- /* Kernel can silently add MS_RDONLY flag when mounting file -- * system that does not have write support. Check this to avoid -- * 'ro' in /proc/mounts and 'rw' in mtab. -- */ -- if (!(cxt->mountflags & (MS_RDONLY | MS_MOVE)) -- && !mnt_context_propagation_only(cxt)) { -- -- if (is_rdonly < 0) -- is_rdonly = mnt_is_readonly(mnt_context_get_target(cxt)); -- if (is_rdonly) -- mnt_context_set_mflags(cxt, cxt->mountflags | MS_RDONLY); -- } -- } -+ if (mnt_context_get_status(cxt) -+ && !mnt_context_is_fake(cxt) -+ && !cxt->helper -+ && mnt_context_mtab_writable(cxt)) { -+ -+ int is_rdonly = -1; -+ -+ DBG(CXT, ul_debugobj(cxt, "checking for RDONLY mismatch")); -+ -+ /* -+ * Mounted by mount(2), do some post-mount checks -+ * -+ * Kernel can be used to use MS_RDONLY for bind mounts, but the -+ * read-only request could be silently ignored. Check it to -+ * avoid 'ro' in mtab and 'rw' in /proc/mounts. -+ */ -+ if ((cxt->mountflags & MS_BIND) -+ && (cxt->mountflags & MS_RDONLY)) { -+ -+ if (is_rdonly < 0) -+ is_rdonly = mnt_is_readonly(mnt_context_get_target(cxt)); -+ if (!is_rdonly) -+ mnt_context_set_mflags(cxt, cxt->mountflags & ~MS_RDONLY); -+ } -+ -+ -+ /* Kernel can silently add MS_RDONLY flag when mounting file -+ * system that does not have write support. Check this to avoid -+ * 'ro' in /proc/mounts and 'rw' in mtab. -+ */ -+ if (!(cxt->mountflags & (MS_RDONLY | MS_MOVE)) -+ && !mnt_context_propagation_only(cxt)) { -+ -+ if (is_rdonly < 0) -+ is_rdonly = mnt_is_readonly(mnt_context_get_target(cxt)); -+ if (is_rdonly) -+ mnt_context_set_mflags(cxt, cxt->mountflags | MS_RDONLY); -+ } -+ } - #endif - -- /* Cleanup will be immediate on failure, and deferred to umount on success */ -- if (mnt_context_is_veritydev(cxt)) -- mnt_context_deferred_delete_veritydev(cxt); -+ /* Cleanup will be immediate on failure, and deferred to umount on success */ -+ if (mnt_context_is_veritydev(cxt)) -+ mnt_context_deferred_delete_veritydev(cxt); - -- if (!mnt_context_switch_ns(cxt, ns_old)) -- return -MNT_ERR_NAMESPACE; -+ if (!mnt_context_switch_ns(cxt, ns_old)) -+ return -MNT_ERR_NAMESPACE; - -- return res; -+ return res; - } - - /* -@@ -1128,27 +1128,27 @@ - */ - static struct libmnt_fs *get_already_mounted_source(struct libmnt_context *cxt) - { -- const char *src; -- struct libmnt_table *tb; -+ const char *src; -+ struct libmnt_table *tb; - -- assert(cxt); -+ assert(cxt); - -- src = mnt_fs_get_srcpath(cxt->fs); -+ src = mnt_fs_get_srcpath(cxt->fs); - -- if (src && mnt_context_get_mtab(cxt, &tb) == 0) { -- struct libmnt_iter itr; -- struct libmnt_fs *fs; -- -- mnt_reset_iter(&itr, MNT_ITER_FORWARD); -- while (mnt_table_next_fs(tb, &itr, &fs) == 0) { -- const char *s = mnt_fs_get_srcpath(fs), -- *t = mnt_fs_get_target(fs); -- -- if (t && s && mnt_fs_streq_srcpath(fs, src)) -- return fs; -- } -- } -- return NULL; -+ if (src && mnt_context_get_mtab(cxt, &tb) == 0) { -+ struct libmnt_iter itr; -+ struct libmnt_fs *fs; -+ -+ mnt_reset_iter(&itr, MNT_ITER_FORWARD); -+ while (mnt_table_next_fs(tb, &itr, &fs) == 0) { -+ const char *s = mnt_fs_get_srcpath(fs), -+ *t = mnt_fs_get_target(fs); -+ -+ if (t && s && mnt_fs_streq_srcpath(fs, src)) -+ return fs; -+ } -+ } -+ return NULL; - } - - /* -@@ -1157,10 +1157,10 @@ - */ - static int is_source_already_rdonly(struct libmnt_context *cxt) - { -- struct libmnt_fs *fs = get_already_mounted_source(cxt); -- const char *opts = fs ? mnt_fs_get_fs_options(fs) : NULL; -+ struct libmnt_fs *fs = get_already_mounted_source(cxt); -+ const char *opts = fs ? mnt_fs_get_fs_options(fs) : NULL; - -- return opts && mnt_optstr_get_option(opts, "ro", NULL, NULL) == 0; -+ return opts && mnt_optstr_get_option(opts, "ro", NULL, NULL) == 0; - } - - /** -@@ -1174,17 +1174,17 @@ - */ - int mnt_context_finalize_mount(struct libmnt_context *cxt) - { -- int rc; -+ int rc; - -- assert(cxt); -- assert(cxt->fs); -- assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -- assert((cxt->flags & MNT_FL_PREPARED)); -- -- rc = mnt_context_prepare_update(cxt); -- if (!rc) -- rc = mnt_context_update_tabs(cxt); -- return rc; -+ assert(cxt); -+ assert(cxt->fs); -+ assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); -+ assert((cxt->flags & MNT_FL_PREPARED)); -+ -+ rc = mnt_context_prepare_update(cxt); -+ if (!rc) -+ rc = mnt_context_update_tabs(cxt); -+ return rc; - } - - /** -@@ -1195,9 +1195,9 @@ - * - * This is similar to: - * -- * mnt_context_prepare_mount(cxt); -- * mnt_context_do_mount(cxt); -- * mnt_context_finalize_mount(cxt); -+ * mnt_context_prepare_mount(cxt); -+ * mnt_context_do_mount(cxt); -+ * mnt_context_finalize_mount(cxt); - * - * See also mnt_context_disable_helpers(). - * -@@ -1232,7 +1232,7 @@ - * rc = mnt_context_get_excode(cxt, rc, buf, sizeof(buf)); - * if (buf) - * warnx(_("%s: %s"), mnt_context_get_target(cxt), buf); -- * return rc; // MNT_EX_* -+ * return rc; // MNT_EX_* - * </programlisting> - * </informalexample> - * -@@ -1242,58 +1242,58 @@ - */ - int mnt_context_mount(struct libmnt_context *cxt) - { -- int rc; -- struct libmnt_ns *ns_old; -+ int rc; -+ struct libmnt_ns *ns_old; - -- assert(cxt); -- assert(cxt->fs); -- assert(cxt->helper_exec_status == 1); -- assert(cxt->syscall_status == 1); -- -- ns_old = mnt_context_switch_target_ns(cxt); -- if (!ns_old) -- return -MNT_ERR_NAMESPACE; -+ assert(cxt); -+ assert(cxt->fs); -+ assert(cxt->helper_exec_status == 1); -+ assert(cxt->syscall_status == 1); -+ -+ ns_old = mnt_context_switch_target_ns(cxt); -+ if (!ns_old) -+ return -MNT_ERR_NAMESPACE; - - again: -- rc = mnt_context_prepare_mount(cxt); -- if (!rc) -- rc = mnt_context_prepare_update(cxt); -- if (!rc) -- rc = mnt_context_do_mount(cxt); -- if (!rc) -- rc = mnt_context_update_tabs(cxt); -- -- /* -- * Read-only device or already read-only mounted FS. -- * Try mount the filesystem read-only. -- */ -- if ((rc == -EROFS && !mnt_context_syscall_called(cxt)) /* before syscall; rdonly loopdev */ -- || mnt_context_get_syscall_errno(cxt) == EROFS /* syscall failed with EROFS */ -- || mnt_context_get_syscall_errno(cxt) == EACCES /* syscall failed with EACCES */ -- || (mnt_context_get_syscall_errno(cxt) == EBUSY /* already ro-mounted FS */ -- && is_source_already_rdonly(cxt))) -- { -- unsigned long mflags = 0; -- -- mnt_context_get_mflags(cxt, &mflags); -- -- if (!(mflags & MS_RDONLY) /* not yet RDONLY */ -- && !(mflags & MS_REMOUNT) /* not remount */ -- && !(mflags & MS_BIND) /* not bin mount */ -- && !mnt_context_is_rwonly_mount(cxt)) { /* no explicit read-write */ -- -- assert(!(cxt->flags & MNT_FL_FORCED_RDONLY)); -- DBG(CXT, ul_debugobj(cxt, "write-protected source, trying RDONLY.")); -- -- mnt_context_reset_status(cxt); -- mnt_context_set_mflags(cxt, mflags | MS_RDONLY); -- cxt->flags |= MNT_FL_FORCED_RDONLY; -- goto again; -- } -- } -- if (!mnt_context_switch_ns(cxt, ns_old)) -- return -MNT_ERR_NAMESPACE; -- return rc; -+ rc = mnt_context_prepare_mount(cxt); -+ if (!rc) -+ rc = mnt_context_prepare_update(cxt); -+ if (!rc) -+ rc = mnt_context_do_mount(cxt); -+ if (!rc) -+ rc = mnt_context_update_tabs(cxt); -+ -+ /* -+ * Read-only device or already read-only mounted FS. -+ * Try mount the filesystem read-only. -+ */ -+ if ((rc == -EROFS && !mnt_context_syscall_called(cxt)) /* before syscall; rdonly loopdev */ -+ || mnt_context_get_syscall_errno(cxt) == EROFS /* syscall failed with EROFS */ -+ || mnt_context_get_syscall_errno(cxt) == EACCES /* syscall failed with EACCES */ -+ || (mnt_context_get_syscall_errno(cxt) == EBUSY /* already ro-mounted FS */ -+ && is_source_already_rdonly(cxt))) -+ { -+ unsigned long mflags = 0; -+ -+ mnt_context_get_mflags(cxt, &mflags); -+ -+ if (!(mflags & MS_RDONLY) /* not yet RDONLY */ -+ && !(mflags & MS_REMOUNT) /* not remount */ -+ && !(mflags & MS_BIND) /* not bin mount */ -+ && !mnt_context_is_rwonly_mount(cxt)) { /* no explicit read-write */ -+ -+ assert(!(cxt->flags & MNT_FL_FORCED_RDONLY)); -+ DBG(CXT, ul_debugobj(cxt, "write-protected source, trying RDONLY.")); -+ -+ mnt_context_reset_status(cxt); -+ mnt_context_set_mflags(cxt, mflags | MS_RDONLY); -+ cxt->flags |= MNT_FL_FORCED_RDONLY; -+ goto again; -+ } -+ } -+ if (!mnt_context_switch_ns(cxt, ns_old)) -+ return -MNT_ERR_NAMESPACE; -+ return rc; - } - - /** -@@ -1308,8 +1308,8 @@ - * mnt_context_get_fstab()). See also mnt_context_set_fstab(). - * - * You can filter out filesystems by: -- * mnt_context_set_options_pattern() to simulate mount -a -O pattern -- * mnt_context_set_fstype_pattern() to simulate mount -a -t pattern -+ * mnt_context_set_options_pattern() to simulate mount -a -O pattern -+ * mnt_context_set_fstype_pattern() to simulate mount -a -t pattern - * - * If the filesystem is already mounted or does not match defined criteria, - * then the mnt_context_next_mount() function returns zero, but the @ignored is -@@ -1328,129 +1328,129 @@ - * 1 at the end of the list. - */ - int mnt_context_next_mount(struct libmnt_context *cxt, -- struct libmnt_iter *itr, -- struct libmnt_fs **fs, -- int *mntrc, -- int *ignored) --{ -- struct libmnt_table *fstab, *mtab; -- const char *o, *tgt; -- int rc, mounted = 0; -- -- if (ignored) -- *ignored = 0; -- if (mntrc) -- *mntrc = 0; -- -- if (!cxt || !fs || !itr) -- return -EINVAL; -- -- rc = mnt_context_get_fstab(cxt, &fstab); -- if (rc) -- return rc; -- -- rc = mnt_table_next_fs(fstab, itr, fs); -- if (rc != 0) -- return rc; /* more filesystems (or error) */ -- -- o = mnt_fs_get_user_options(*fs); -- tgt = mnt_fs_get_target(*fs); -- -- DBG(CXT, ul_debugobj(cxt, "next-mount: trying %s", tgt)); -- -- /* ignore swap */ -- if (mnt_fs_is_swaparea(*fs) || -- -- /* ignore root filesystem */ -- (tgt && (strcmp(tgt, "/") == 0 || strcmp(tgt, "root") == 0)) || -- -- /* ignore noauto filesystems */ -- (o && mnt_optstr_get_option(o, "noauto", NULL, NULL) == 0) || -- -- /* ignore filesystems which don't match options patterns */ -- (cxt->fstype_pattern && !mnt_fs_match_fstype(*fs, -- cxt->fstype_pattern)) || -- -- /* ignore filesystems which don't match type patterns */ -- (cxt->optstr_pattern && !mnt_fs_match_options(*fs, -- cxt->optstr_pattern))) { -- if (ignored) -- *ignored = 1; -- DBG(CXT, ul_debugobj(cxt, "next-mount: not-match " -- "[fstype: %s, t-pattern: %s, options: %s, O-pattern: %s]", -- mnt_fs_get_fstype(*fs), -- cxt->fstype_pattern, -- mnt_fs_get_options(*fs), -- cxt->optstr_pattern)); -- return 0; -- } -- -- /* ignore already mounted filesystems */ -- rc = mnt_context_is_fs_mounted(cxt, *fs, &mounted); -- if (rc) -- return rc; -- if (mounted) { -- if (ignored) -- *ignored = 2; -- return 0; -- } -- -- /* Save mount options, etc. -- this is effective for the first -- * mnt_context_next_mount() call only. Make sure that cxt has not set -- * source, target or fstype. -- */ -- if (!mnt_context_has_template(cxt)) { -- mnt_context_set_source(cxt, NULL); -- mnt_context_set_target(cxt, NULL); -- mnt_context_set_fstype(cxt, NULL); -- mnt_context_save_template(cxt); -- } -- -- /* reset context, but protect mtab */ -- mtab = cxt->mtab; -- cxt->mtab = NULL; -- mnt_reset_context(cxt); -- cxt->mtab = mtab; -- -- if (mnt_context_is_fork(cxt)) { -- rc = mnt_fork_context(cxt); -- if (rc) -- return rc; /* fork error */ -- -- if (mnt_context_is_parent(cxt)) { -- return 0; /* parent */ -- } -- } -- -- /* -- * child or non-forked -- */ -- -- /* copy stuff from fstab to context */ -- rc = mnt_context_apply_fs(cxt, *fs); -- if (!rc) { -- /* -- * "-t <pattern>" is used to filter out fstab entries, but for ordinary -- * mount operation -t means "-t <type>". We have to zeroize the pattern -- * to avoid misinterpretation. -- */ -- char *pattern = cxt->fstype_pattern; -- cxt->fstype_pattern = NULL; -- -- rc = mnt_context_mount(cxt); -- -- cxt->fstype_pattern = pattern; -- -- if (mntrc) -- *mntrc = rc; -- } -- -- if (mnt_context_is_child(cxt)) { -- DBG(CXT, ul_debugobj(cxt, "next-mount: child exit [rc=%d]", rc)); -- DBG_FLUSH; -- _exit(rc); -- } -- return 0; -+ struct libmnt_iter *itr, -+ struct libmnt_fs **fs, -+ int *mntrc, -+ int *ignored) -+{ -+ struct libmnt_table *fstab, *mtab; -+ const char *o, *tgt; -+ int rc, mounted = 0; -+ -+ if (ignored) -+ *ignored = 0; -+ if (mntrc) -+ *mntrc = 0; -+ -+ if (!cxt || !fs || !itr) -+ return -EINVAL; -+ -+ rc = mnt_context_get_fstab(cxt, &fstab); -+ if (rc) -+ return rc; -+ -+ rc = mnt_table_next_fs(fstab, itr, fs); -+ if (rc != 0) -+ return rc; /* more filesystems (or error) */ -+ -+ o = mnt_fs_get_user_options(*fs); -+ tgt = mnt_fs_get_target(*fs); -+ -+ DBG(CXT, ul_debugobj(cxt, "next-mount: trying %s", tgt)); -+ -+ /* ignore swap */ -+ if (mnt_fs_is_swaparea(*fs) || -+ -+ /* ignore root filesystem */ -+ (tgt && (strcmp(tgt, "/") == 0 || strcmp(tgt, "root") == 0)) || -+ -+ /* ignore noauto filesystems */ -+ (o && mnt_optstr_get_option(o, "noauto", NULL, NULL) == 0) || -+ -+ /* ignore filesystems which don't match options patterns */ -+ (cxt->fstype_pattern && !mnt_fs_match_fstype(*fs, -+ cxt->fstype_pattern)) || -+ -+ /* ignore filesystems which don't match type patterns */ -+ (cxt->optstr_pattern && !mnt_fs_match_options(*fs, -+ cxt->optstr_pattern))) { -+ if (ignored) -+ *ignored = 1; -+ DBG(CXT, ul_debugobj(cxt, "next-mount: not-match " -+ "[fstype: %s, t-pattern: %s, options: %s, O-pattern: %s]", -+ mnt_fs_get_fstype(*fs), -+ cxt->fstype_pattern, -+ mnt_fs_get_options(*fs), -+ cxt->optstr_pattern)); -+ return 0; -+ } -+ -+ /* ignore already mounted filesystems */ -+ rc = mnt_context_is_fs_mounted(cxt, *fs, &mounted); -+ if (rc) -+ return rc; -+ if (mounted) { -+ if (ignored) -+ *ignored = 2; -+ return 0; -+ } -+ -+ /* Save mount options, etc. -- this is effective for the first -+ * mnt_context_next_mount() call only. Make sure that cxt has not set -+ * source, target or fstype. -+ */ -+ if (!mnt_context_has_template(cxt)) { -+ mnt_context_set_source(cxt, NULL); -+ mnt_context_set_target(cxt, NULL); -+ mnt_context_set_fstype(cxt, NULL); -+ mnt_context_save_template(cxt); -+ } -+ -+ /* reset context, but protect mtab */ -+ mtab = cxt->mtab; -+ cxt->mtab = NULL; -+ mnt_reset_context(cxt); -+ cxt->mtab = mtab; -+ -+ if (mnt_context_is_fork(cxt)) { -+ rc = mnt_fork_context(cxt); -+ if (rc) -+ return rc; /* fork error */ -+ -+ if (mnt_context_is_parent(cxt)) { -+ return 0; /* parent */ -+ } -+ } -+ -+ /* -+ * child or non-forked -+ */ -+ -+ /* copy stuff from fstab to context */ -+ rc = mnt_context_apply_fs(cxt, *fs); -+ if (!rc) { -+ /* -+ * "-t <pattern>" is used to filter out fstab entries, but for ordinary -+ * mount operation -t means "-t <type>". We have to zeroize the pattern -+ * to avoid misinterpretation. -+ */ -+ char *pattern = cxt->fstype_pattern; -+ cxt->fstype_pattern = NULL; -+ -+ rc = mnt_context_mount(cxt); -+ -+ cxt->fstype_pattern = pattern; -+ -+ if (mntrc) -+ *mntrc = rc; -+ } -+ -+ if (mnt_context_is_child(cxt)) { -+ DBG(CXT, ul_debugobj(cxt, "next-mount: child exit [rc=%d]", rc)); -+ DBG_FLUSH; -+ _exit(rc); -+ } -+ return 0; - } - - -@@ -1466,8 +1466,8 @@ - * mnt_context_get_mtab()). - * - * You can filter out filesystems by: -- * mnt_context_set_options_pattern() to simulate mount -a -O pattern -- * mnt_context_set_fstype_pattern() to simulate mount -a -t pattern -+ * mnt_context_set_options_pattern() to simulate mount -a -O pattern -+ * mnt_context_set_fstype_pattern() to simulate mount -a -t pattern - * - * If the filesystem does not match defined criteria, then the - * mnt_context_next_remount() function returns zero, but the @ignored is -@@ -1492,89 +1492,89 @@ - * Since: 2.34 - */ - int mnt_context_next_remount(struct libmnt_context *cxt, -- struct libmnt_iter *itr, -- struct libmnt_fs **fs, -- int *mntrc, -- int *ignored) --{ -- struct libmnt_table *mtab; -- const char *tgt; -- int rc; -- -- if (ignored) -- *ignored = 0; -- if (mntrc) -- *mntrc = 0; -- -- if (!cxt || !fs || !itr) -- return -EINVAL; -- -- rc = mnt_context_get_mtab(cxt, &mtab); -- if (rc) -- return rc; -- -- rc = mnt_table_next_fs(mtab, itr, fs); -- if (rc != 0) -- return rc; /* more filesystems (or error) */ -- -- tgt = mnt_fs_get_target(*fs); -- -- DBG(CXT, ul_debugobj(cxt, "next-remount: trying %s", tgt)); -- -- /* ignore filesystems which don't match options patterns */ -- if ((cxt->fstype_pattern && !mnt_fs_match_fstype(*fs, -- cxt->fstype_pattern)) || -- -- /* ignore filesystems which don't match type patterns */ -- (cxt->optstr_pattern && !mnt_fs_match_options(*fs, -- cxt->optstr_pattern))) { -- if (ignored) -- *ignored = 1; -- DBG(CXT, ul_debugobj(cxt, "next-remount: not-match " -- "[fstype: %s, t-pattern: %s, options: %s, O-pattern: %s]", -- mnt_fs_get_fstype(*fs), -- cxt->fstype_pattern, -- mnt_fs_get_options(*fs), -- cxt->optstr_pattern)); -- return 0; -- } -- -- /* Save mount options, etc. -- this is effective for the first -- * mnt_context_next_remount() call only. Make sure that cxt has not set -- * source, target or fstype. -- */ -- if (!mnt_context_has_template(cxt)) { -- mnt_context_set_source(cxt, NULL); -- mnt_context_set_target(cxt, NULL); -- mnt_context_set_fstype(cxt, NULL); -- mnt_context_save_template(cxt); -- } -- -- /* restore original, but protect mtab */ -- cxt->mtab = NULL; -- mnt_reset_context(cxt); -- cxt->mtab = mtab; -- -- rc = mnt_context_set_target(cxt, tgt); -- if (!rc) { -- /* -- * "-t <pattern>" is used to filter out fstab entries, but for ordinary -- * mount operation -t means "-t <type>". We have to zeroize the pattern -- * to avoid misinterpretation. -- */ -- char *pattern = cxt->fstype_pattern; -- cxt->fstype_pattern = NULL; -- -- rc = mnt_context_mount(cxt); -- -- cxt->fstype_pattern = pattern; -- -- if (mntrc) -- *mntrc = rc; -- rc = 0; -- } -+ struct libmnt_iter *itr, -+ struct libmnt_fs **fs, -+ int *mntrc, -+ int *ignored) -+{ -+ struct libmnt_table *mtab; -+ const char *tgt; -+ int rc; -+ -+ if (ignored) -+ *ignored = 0; -+ if (mntrc) -+ *mntrc = 0; -+ -+ if (!cxt || !fs || !itr) -+ return -EINVAL; -+ -+ rc = mnt_context_get_mtab(cxt, &mtab); -+ if (rc) -+ return rc; -+ -+ rc = mnt_table_next_fs(mtab, itr, fs); -+ if (rc != 0) -+ return rc; /* more filesystems (or error) */ -+ -+ tgt = mnt_fs_get_target(*fs); -+ -+ DBG(CXT, ul_debugobj(cxt, "next-remount: trying %s", tgt)); -+ -+ /* ignore filesystems which don't match options patterns */ -+ if ((cxt->fstype_pattern && !mnt_fs_match_fstype(*fs, -+ cxt->fstype_pattern)) || -+ -+ /* ignore filesystems which don't match type patterns */ -+ (cxt->optstr_pattern && !mnt_fs_match_options(*fs, -+ cxt->optstr_pattern))) { -+ if (ignored) -+ *ignored = 1; -+ DBG(CXT, ul_debugobj(cxt, "next-remount: not-match " -+ "[fstype: %s, t-pattern: %s, options: %s, O-pattern: %s]", -+ mnt_fs_get_fstype(*fs), -+ cxt->fstype_pattern, -+ mnt_fs_get_options(*fs), -+ cxt->optstr_pattern)); -+ return 0; -+ } -+ -+ /* Save mount options, etc. -- this is effective for the first -+ * mnt_context_next_remount() call only. Make sure that cxt has not set -+ * source, target or fstype. -+ */ -+ if (!mnt_context_has_template(cxt)) { -+ mnt_context_set_source(cxt, NULL); -+ mnt_context_set_target(cxt, NULL); -+ mnt_context_set_fstype(cxt, NULL); -+ mnt_context_save_template(cxt); -+ } -+ -+ /* restore original, but protect mtab */ -+ cxt->mtab = NULL; -+ mnt_reset_context(cxt); -+ cxt->mtab = mtab; -+ -+ rc = mnt_context_set_target(cxt, tgt); -+ if (!rc) { -+ /* -+ * "-t <pattern>" is used to filter out fstab entries, but for ordinary -+ * mount operation -t means "-t <type>". We have to zeroize the pattern -+ * to avoid misinterpretation. -+ */ -+ char *pattern = cxt->fstype_pattern; -+ cxt->fstype_pattern = NULL; -+ -+ rc = mnt_context_mount(cxt); -+ -+ cxt->fstype_pattern = pattern; -+ -+ if (mntrc) -+ *mntrc = rc; -+ rc = 0; -+ } - -- return rc; -+ return rc; - } - - /* -@@ -1582,354 +1582,354 @@ - */ - static int is_shared_tree(struct libmnt_context *cxt, const char *dir) - { -- struct libmnt_table *tb = NULL; -- struct libmnt_fs *fs; -- unsigned long mflags = 0; -- char *mnt = NULL, *p; -- int rc = 0; -- struct libmnt_ns *ns_old; -- -- ns_old = mnt_context_switch_target_ns(cxt); -- if (!ns_old) -- return -MNT_ERR_NAMESPACE; -- -- if (!dir) -- return 0; -- if (mnt_context_get_mtab(cxt, &tb) || !tb) -- goto done; -- -- mnt = strdup(dir); -- if (!mnt) -- goto done; -- p = strrchr(mnt, '/'); -- if (!p) -- goto done; -- if (p > mnt) -- *p = '\0'; -- fs = mnt_table_find_mountpoint(tb, mnt, MNT_ITER_BACKWARD); -- -- rc = fs && mnt_fs_is_kernel(fs) -- && mnt_fs_get_propagation(fs, &mflags) == 0 -- && (mflags & MS_SHARED); -+ struct libmnt_table *tb = NULL; -+ struct libmnt_fs *fs; -+ unsigned long mflags = 0; -+ char *mnt = NULL, *p; -+ int rc = 0; -+ struct libmnt_ns *ns_old; -+ -+ ns_old = mnt_context_switch_target_ns(cxt); -+ if (!ns_old) -+ return -MNT_ERR_NAMESPACE; -+ -+ if (!dir) -+ return 0; -+ if (mnt_context_get_mtab(cxt, &tb) || !tb) -+ goto done; -+ -+ mnt = strdup(dir); -+ if (!mnt) -+ goto done; -+ p = strrchr(mnt, '/'); -+ if (!p) -+ goto done; -+ if (p > mnt) -+ *p = '\0'; -+ fs = mnt_table_find_mountpoint(tb, mnt, MNT_ITER_BACKWARD); -+ -+ rc = fs && mnt_fs_is_kernel(fs) -+ && mnt_fs_get_propagation(fs, &mflags) == 0 -+ && (mflags & MS_SHARED); - done: -- free(mnt); -- if (!mnt_context_switch_ns(cxt, ns_old)) -- return -MNT_ERR_NAMESPACE; -- return rc; -+ free(mnt); -+ if (!mnt_context_switch_ns(cxt, ns_old)) -+ return -MNT_ERR_NAMESPACE; -+ return rc; - } - - int mnt_context_get_mount_excode( -- struct libmnt_context *cxt, -- int rc, -- char *buf, -- size_t bufsz) --{ -- int syserr; -- struct stat st; -- unsigned long uflags = 0, mflags = 0; -- -- int restricted = mnt_context_is_restricted(cxt); -- const char *tgt = mnt_context_get_target(cxt); -- const char *src = mnt_context_get_source(cxt); -- -- if (mnt_context_helper_executed(cxt)) { -- /* -- * /sbin/mount.<type> called, return status -- */ -- if (rc == -MNT_ERR_APPLYFLAGS && buf) -- snprintf(buf, bufsz, _("WARNING: failed to apply propagation flags")); -- -- return mnt_context_get_helper_status(cxt); -- } -- -- if (rc == 0 && mnt_context_get_status(cxt) == 1) { -- /* -- * Libmount success && syscall success. -- */ -- if (buf && mnt_context_forced_rdonly(cxt)) -- snprintf(buf, bufsz, _("WARNING: source write-protected, mounted read-only")); -- return MNT_EX_SUCCESS; -- } -- -- mnt_context_get_mflags(cxt, &mflags); /* mount(2) flags */ -- mnt_context_get_user_mflags(cxt, &uflags); /* userspace flags */ -- -- if (!mnt_context_syscall_called(cxt)) { -- /* -- * libmount errors (extra library checks) -- */ -- switch (rc) { -- case -EPERM: -- if (buf) -- snprintf(buf, bufsz, _("operation permitted for root only")); -- return MNT_EX_USAGE; -- case -EBUSY: -- if (buf) -- snprintf(buf, bufsz, _("%s is already mounted"), src); -- return MNT_EX_USAGE; -- case -MNT_ERR_NOFSTAB: -- if (!buf) -- return MNT_EX_USAGE; -- if (mnt_context_is_swapmatch(cxt)) -- snprintf(buf, bufsz, _("can't find in %s"), -- mnt_get_fstab_path()); -- else if (tgt) -- snprintf(buf, bufsz, _("can't find mount point in %s"), -- mnt_get_fstab_path()); -- else if (src) -- snprintf(buf, bufsz, _("can't find mount source %s in %s"), -- src, mnt_get_fstab_path()); -- return MNT_EX_USAGE; -- case -MNT_ERR_AMBIFS: -- if (buf) -- snprintf(buf, bufsz, _("more filesystems detected on %s; use -t <type> or wipefs(8)"), src); -- return MNT_EX_USAGE; -- case -MNT_ERR_NOFSTYPE: -- if (buf) -- snprintf(buf, bufsz, restricted ? -- _("failed to determine filesystem type") : -- _("no filesystem type specified")); -- return MNT_EX_USAGE; -- case -MNT_ERR_NOSOURCE: -- if (uflags & MNT_MS_NOFAIL) -- return MNT_EX_SUCCESS; -- if (buf) { -- if (src) -- snprintf(buf, bufsz, _("can't find %s"), src); -- else -- snprintf(buf, bufsz, _("no mount source specified")); -- } -- return MNT_EX_USAGE; -- case -MNT_ERR_MOUNTOPT: -- if (buf) -- snprintf(buf, bufsz, errno ? -- _("failed to parse mount options: %m") : -- _("failed to parse mount options")); -- return MNT_EX_USAGE; -- case -MNT_ERR_LOOPDEV: -- if (buf) -- snprintf(buf, bufsz, _("failed to setup loop device for %s"), src); -- return MNT_EX_FAIL; -- case -MNT_ERR_LOOPOVERLAP: -- if (buf) -- snprintf(buf, bufsz, _("overlapping loop device exists for %s"), src); -- return MNT_EX_FAIL; -- case -MNT_ERR_LOCK: -- if (buf) -- snprintf(buf, bufsz, _("locking failed")); -- return MNT_EX_FILEIO; -- case -MNT_ERR_NAMESPACE: -- if (buf) -- snprintf(buf, bufsz, _("failed to switch namespace")); -- return MNT_EX_SYSERR; -- default: -- return mnt_context_get_generic_excode(rc, buf, bufsz, _("mount failed: %m")); -- } -- -- } else if (mnt_context_get_syscall_errno(cxt) == 0) { -- /* -- * mount(2) syscall success, but something else failed -- * (probably error in mtab processing). -- */ -- if (rc == -MNT_ERR_LOCK) { -- if (buf) -- snprintf(buf, bufsz, _("filesystem was mounted, but failed to update userspace mount table")); -- return MNT_EX_FILEIO; -- } -- -- if (rc == -MNT_ERR_NAMESPACE) { -- if (buf) -- snprintf(buf, bufsz, _("filesystem was mounted, but failed to switch namespace back")); -- return MNT_EX_SYSERR; -- -- } -- -- if (rc < 0) -- return mnt_context_get_generic_excode(rc, buf, bufsz, -- _("filesystem was mounted, but any subsequent operation failed: %m")); -- -- return MNT_EX_SOFTWARE; /* internal error */ -- -- } -- -- /* -- * mount(2) errors -- */ -- syserr = mnt_context_get_syscall_errno(cxt); -- -- -- switch(syserr) { -- case EPERM: -- if (!buf) -- break; -- if (geteuid() == 0) { -- if (mnt_stat_mountpoint(tgt, &st) || !S_ISDIR(st.st_mode)) -- snprintf(buf, bufsz, _("mount point is not a directory")); -- else -- snprintf(buf, bufsz, _("permission denied")); -- } else -- snprintf(buf, bufsz, _("must be superuser to use mount")); -- break; -- -- case EBUSY: -- if (!buf) -- break; -- if (mflags & MS_REMOUNT) { -- snprintf(buf, bufsz, _("mount point is busy")); -- break; -- } -- if (src) { -- struct libmnt_fs *fs = get_already_mounted_source(cxt); -- -- if (fs && mnt_fs_get_target(fs)) -- snprintf(buf, bufsz, _("%s already mounted on %s"), -- src, mnt_fs_get_target(fs)); -- } -- if (!*buf) -- snprintf(buf, bufsz, _("%s already mounted or mount point busy"), src); -- break; -- case ENOENT: -- if (tgt && mnt_lstat_mountpoint(tgt, &st)) { -- if (buf) -- snprintf(buf, bufsz, _("mount point does not exist")); -- } else if (tgt && mnt_stat_mountpoint(tgt, &st)) { -- if (buf) -- snprintf(buf, bufsz, _("mount point is a symbolic link to nowhere")); -- } else if (src && stat(src, &st)) { -- if (uflags & MNT_MS_NOFAIL) -- return MNT_EX_SUCCESS; -- if (buf) -- snprintf(buf, bufsz, _("special device %s does not exist"), src); -- } else if (buf) { -- errno = syserr; -- snprintf(buf, bufsz, _("mount(2) system call failed: %m")); -- } -- break; -- -- case ENOTDIR: -- if (mnt_stat_mountpoint(tgt, &st) || ! S_ISDIR(st.st_mode)) { -- if (buf) -- snprintf(buf, bufsz, _("mount point is not a directory")); -- } else if (src && stat(src, &st) && errno == ENOTDIR) { -- if (uflags & MNT_MS_NOFAIL) -- return MNT_EX_SUCCESS; -- if (buf) -- snprintf(buf, bufsz, _("special device %s does not exist " -- "(a path prefix is not a directory)"), src); -- } else if (buf) { -- errno = syserr; -- snprintf(buf, bufsz, _("mount(2) system call failed: %m")); -- } -- break; -- -- case EINVAL: -- if (!buf) -- break; -- if (mflags & MS_REMOUNT) -- snprintf(buf, bufsz, _("mount point not mounted or bad option")); -- else if (rc == -MNT_ERR_APPLYFLAGS) -- snprintf(buf, bufsz, _("not mount point or bad option")); -- else if ((mflags & MS_MOVE) && is_shared_tree(cxt, src)) -- snprintf(buf, bufsz, -- _("bad option; moving a mount " -- "residing under a shared mount is unsupported")); -- else if (mnt_fs_is_netfs(mnt_context_get_fs(cxt))) -- snprintf(buf, bufsz, -- _("bad option; for several filesystems (e.g. nfs, cifs) " -- "you might need a /sbin/mount.<type> helper program")); -- else -- snprintf(buf, bufsz, -- _("wrong fs type, bad option, bad superblock on %s, " -- "missing codepage or helper program, or other error"), -- src); -- break; -- -- case EMFILE: -- if (buf) -- snprintf(buf, bufsz, _("mount table full")); -- break; -- -- case EIO: -- if (buf) -- snprintf(buf, bufsz, _("can't read superblock on %s"), src); -- break; -- -- case ENODEV: -- if (!buf) -- break; -- if (mnt_context_get_fstype(cxt)) -- snprintf(buf, bufsz, _("unknown filesystem type '%s'"), -- mnt_context_get_fstype(cxt)); -- else -- snprintf(buf, bufsz, _("unknown filesystem type")); -- break; -- -- case ENOTBLK: -- if (uflags & MNT_MS_NOFAIL) -- return MNT_EX_SUCCESS; -- if (!buf) -- break; -- if (src && stat(src, &st)) -- snprintf(buf, bufsz, _("%s is not a block device, and stat(2) fails?"), src); -- else if (src && S_ISBLK(st.st_mode)) -- snprintf(buf, bufsz, -- _("the kernel does not recognize %s as a block device; " -- "maybe \"modprobe driver\" is necessary"), src); -- else if (src && S_ISREG(st.st_mode)) -- snprintf(buf, bufsz, _("%s is not a block device; try \"-o loop\""), src); -- else -- snprintf(buf, bufsz, _("%s is not a block device"), src); -- break; -- -- case ENXIO: -- if (uflags & MNT_MS_NOFAIL) -- return MNT_EX_SUCCESS; -- if (buf) -- snprintf(buf, bufsz, _("%s is not a valid block device"), src); -- break; -- -- case EACCES: -- case EROFS: -- if (!buf) -- break; -- if (mflags & MS_RDONLY) -- snprintf(buf, bufsz, _("cannot mount %s read-only"), src); -- else if (mnt_context_is_rwonly_mount(cxt)) -- snprintf(buf, bufsz, _("%s is write-protected but explicit read-write mode requested"), src); -- else if (mflags & MS_REMOUNT) -- snprintf(buf, bufsz, _("cannot remount %s read-write, is write-protected"), src); -- else if (mflags & MS_BIND) -- snprintf(buf, bufsz, _("bind %s failed"), src); -- else { -- errno = syserr; -- snprintf(buf, bufsz, _("mount(2) system call failed: %m")); -- } -- break; -- -- case ENOMEDIUM: -- if (uflags & MNT_MS_NOFAIL) -- return MNT_EX_SUCCESS; -- if (buf) -- snprintf(buf, bufsz, _("no medium found on %s"), src); -- break; -- -- case EBADMSG: -- /* Bad CRC for classic filesystems (e.g. extN or XFS) */ -- if (buf && src && stat(src, &st) == 0 -- && (S_ISBLK(st.st_mode) || S_ISREG(st.st_mode))) { -- snprintf(buf, bufsz, _("cannot mount; probably corrupted filesystem on %s"), src); -- break; -- } -- /* fallthrough */ -- -- default: -- if (buf) { -- errno = syserr; -- snprintf(buf, bufsz, _("mount(2) system call failed: %m")); -- } -- break; -- } -+ struct libmnt_context *cxt, -+ int rc, -+ char *buf, -+ size_t bufsz) -+{ -+ int syserr; -+ struct stat st; -+ unsigned long uflags = 0, mflags = 0; -+ -+ int restricted = mnt_context_is_restricted(cxt); -+ const char *tgt = mnt_context_get_target(cxt); -+ const char *src = mnt_context_get_source(cxt); -+ -+ if (mnt_context_helper_executed(cxt)) { -+ /* -+ * /sbin/mount.<type> called, return status -+ */ -+ if (rc == -MNT_ERR_APPLYFLAGS && buf) -+ snprintf(buf, bufsz, _("WARNING: failed to apply propagation flags")); -+ -+ return mnt_context_get_helper_status(cxt); -+ } -+ -+ if (rc == 0 && mnt_context_get_status(cxt) == 1) { -+ /* -+ * Libmount success && syscall success. -+ */ -+ if (buf && mnt_context_forced_rdonly(cxt)) -+ snprintf(buf, bufsz, _("WARNING: source write-protected, mounted read-only")); -+ return MNT_EX_SUCCESS; -+ } -+ -+ mnt_context_get_mflags(cxt, &mflags); /* mount(2) flags */ -+ mnt_context_get_user_mflags(cxt, &uflags); /* userspace flags */ -+ -+ if (!mnt_context_syscall_called(cxt)) { -+ /* -+ * libmount errors (extra library checks) -+ */ -+ switch (rc) { -+ case -EPERM: -+ if (buf) -+ snprintf(buf, bufsz, _("operation permitted for root only")); -+ return MNT_EX_USAGE; -+ case -EBUSY: -+ if (buf) -+ snprintf(buf, bufsz, _("%s is already mounted"), src); -+ return MNT_EX_USAGE; -+ case -MNT_ERR_NOFSTAB: -+ if (!buf) -+ return MNT_EX_USAGE; -+ if (mnt_context_is_swapmatch(cxt)) -+ snprintf(buf, bufsz, _("can't find in %s"), -+ mnt_get_fstab_path()); -+ else if (tgt) -+ snprintf(buf, bufsz, _("can't find mount point in %s"), -+ mnt_get_fstab_path()); -+ else if (src) -+ snprintf(buf, bufsz, _("can't find mount source %s in %s"), -+ src, mnt_get_fstab_path()); -+ return MNT_EX_USAGE; -+ case -MNT_ERR_AMBIFS: -+ if (buf) -+ snprintf(buf, bufsz, _("more filesystems detected on %s; use -t <type> or wipefs(8)"), src); -+ return MNT_EX_USAGE; -+ case -MNT_ERR_NOFSTYPE: -+ if (buf) -+ snprintf(buf, bufsz, restricted ? -+ _("failed to determine filesystem type") : -+ _("no filesystem type specified")); -+ return MNT_EX_USAGE; -+ case -MNT_ERR_NOSOURCE: -+ if (uflags & MNT_MS_NOFAIL) -+ return MNT_EX_SUCCESS; -+ if (buf) { -+ if (src) -+ snprintf(buf, bufsz, _("can't find %s"), src); -+ else -+ snprintf(buf, bufsz, _("no mount source specified")); -+ } -+ return MNT_EX_USAGE; -+ case -MNT_ERR_MOUNTOPT: -+ if (buf) -+ snprintf(buf, bufsz, errno ? -+ _("failed to parse mount options: %m") : -+ _("failed to parse mount options")); -+ return MNT_EX_USAGE; -+ case -MNT_ERR_LOOPDEV: -+ if (buf) -+ snprintf(buf, bufsz, _("failed to setup loop device for %s"), src); -+ return MNT_EX_FAIL; -+ case -MNT_ERR_LOOPOVERLAP: -+ if (buf) -+ snprintf(buf, bufsz, _("overlapping loop device exists for %s"), src); -+ return MNT_EX_FAIL; -+ case -MNT_ERR_LOCK: -+ if (buf) -+ snprintf(buf, bufsz, _("locking failed")); -+ return MNT_EX_FILEIO; -+ case -MNT_ERR_NAMESPACE: -+ if (buf) -+ snprintf(buf, bufsz, _("failed to switch namespace")); -+ return MNT_EX_SYSERR; -+ default: -+ return mnt_context_get_generic_excode(rc, buf, bufsz, _("mount failed: %m")); -+ } -+ -+ } else if (mnt_context_get_syscall_errno(cxt) == 0) { -+ /* -+ * mount(2) syscall success, but something else failed -+ * (probably error in mtab processing). -+ */ -+ if (rc == -MNT_ERR_LOCK) { -+ if (buf) -+ snprintf(buf, bufsz, _("filesystem was mounted, but failed to update userspace mount table")); -+ return MNT_EX_FILEIO; -+ } -+ -+ if (rc == -MNT_ERR_NAMESPACE) { -+ if (buf) -+ snprintf(buf, bufsz, _("filesystem was mounted, but failed to switch namespace back")); -+ return MNT_EX_SYSERR; -+ -+ } -+ -+ if (rc < 0) -+ return mnt_context_get_generic_excode(rc, buf, bufsz, -+ _("filesystem was mounted, but any subsequent operation failed: %m")); -+ -+ return MNT_EX_SOFTWARE; /* internal error */ -+ -+ } -+ -+ /* -+ * mount(2) errors -+ */ -+ syserr = mnt_context_get_syscall_errno(cxt); -+ -+ -+ switch(syserr) { -+ case EPERM: -+ if (!buf) -+ break; -+ if (geteuid() == 0) { -+ if (mnt_stat_mountpoint(tgt, &st) || !S_ISDIR(st.st_mode)) -+ snprintf(buf, bufsz, _("mount point is not a directory")); -+ else -+ snprintf(buf, bufsz, _("permission denied")); -+ } else -+ snprintf(buf, bufsz, _("must be superuser to use mount")); -+ break; -+ -+ case EBUSY: -+ if (!buf) -+ break; -+ if (mflags & MS_REMOUNT) { -+ snprintf(buf, bufsz, _("mount point is busy")); -+ break; -+ } -+ if (src) { -+ struct libmnt_fs *fs = get_already_mounted_source(cxt); -+ -+ if (fs && mnt_fs_get_target(fs)) -+ snprintf(buf, bufsz, _("%s already mounted on %s"), -+ src, mnt_fs_get_target(fs)); -+ } -+ if (!*buf) -+ snprintf(buf, bufsz, _("%s already mounted or mount point busy"), src); -+ break; -+ case ENOENT: -+ if (tgt && mnt_lstat_mountpoint(tgt, &st)) { -+ if (buf) -+ snprintf(buf, bufsz, _("mount point does not exist")); -+ } else if (tgt && mnt_stat_mountpoint(tgt, &st)) { -+ if (buf) -+ snprintf(buf, bufsz, _("mount point is a symbolic link to nowhere")); -+ } else if (src && stat(src, &st)) { -+ if (uflags & MNT_MS_NOFAIL) -+ return MNT_EX_SUCCESS; -+ if (buf) -+ snprintf(buf, bufsz, _("special device %s does not exist"), src); -+ } else if (buf) { -+ errno = syserr; -+ snprintf(buf, bufsz, _("mount(2) system call failed: %m")); -+ } -+ break; -+ -+ case ENOTDIR: -+ if (mnt_stat_mountpoint(tgt, &st) || ! S_ISDIR(st.st_mode)) { -+ if (buf) -+ snprintf(buf, bufsz, _("mount point is not a directory")); -+ } else if (src && stat(src, &st) && errno == ENOTDIR) { -+ if (uflags & MNT_MS_NOFAIL) -+ return MNT_EX_SUCCESS; -+ if (buf) -+ snprintf(buf, bufsz, _("special device %s does not exist " -+ "(a path prefix is not a directory)"), src); -+ } else if (buf) { -+ errno = syserr; -+ snprintf(buf, bufsz, _("mount(2) system call failed: %m")); -+ } -+ break; -+ -+ case EINVAL: -+ if (!buf) -+ break; -+ if (mflags & MS_REMOUNT) -+ snprintf(buf, bufsz, _("mount point not mounted or bad option")); -+ else if (rc == -MNT_ERR_APPLYFLAGS) -+ snprintf(buf, bufsz, _("not mount point or bad option")); -+ else if ((mflags & MS_MOVE) && is_shared_tree(cxt, src)) -+ snprintf(buf, bufsz, -+ _("bad option; moving a mount " -+ "residing under a shared mount is unsupported")); -+ else if (mnt_fs_is_netfs(mnt_context_get_fs(cxt))) -+ snprintf(buf, bufsz, -+ _("bad option; for several filesystems (e.g. nfs, cifs) " -+ "you might need a /sbin/mount.<type> helper program")); -+ else -+ snprintf(buf, bufsz, -+ _("wrong fs type, bad option, bad superblock on %s, " -+ "missing codepage or helper program, or other error"), -+ src); -+ break; -+ -+ case EMFILE: -+ if (buf) -+ snprintf(buf, bufsz, _("mount table full")); -+ break; -+ -+ case EIO: -+ if (buf) -+ snprintf(buf, bufsz, _("can't read superblock on %s"), src); -+ break; -+ -+ case ENODEV: -+ if (!buf) -+ break; -+ if (mnt_context_get_fstype(cxt)) -+ snprintf(buf, bufsz, _("unknown filesystem type '%s'"), -+ mnt_context_get_fstype(cxt)); -+ else -+ snprintf(buf, bufsz, _("unknown filesystem type")); -+ break; -+ -+ case ENOTBLK: -+ if (uflags & MNT_MS_NOFAIL) -+ return MNT_EX_SUCCESS; -+ if (!buf) -+ break; -+ if (src && stat(src, &st)) -+ snprintf(buf, bufsz, _("%s is not a block device, and stat(2) fails?"), src); -+ else if (src && S_ISBLK(st.st_mode)) -+ snprintf(buf, bufsz, -+ _("the kernel does not recognize %s as a block device; " -+ "maybe \"modprobe driver\" is necessary"), src); -+ else if (src && S_ISREG(st.st_mode)) -+ snprintf(buf, bufsz, _("%s is not a block device; try \"-o loop\""), src); -+ else -+ snprintf(buf, bufsz, _("%s is not a block device"), src); -+ break; -+ -+ case ENXIO: -+ if (uflags & MNT_MS_NOFAIL) -+ return MNT_EX_SUCCESS; -+ if (buf) -+ snprintf(buf, bufsz, _("%s is not a valid block device"), src); -+ break; -+ -+ case EACCES: -+ case EROFS: -+ if (!buf) -+ break; -+ if (mflags & MS_RDONLY) -+ snprintf(buf, bufsz, _("cannot mount %s read-only"), src); -+ else if (mnt_context_is_rwonly_mount(cxt)) -+ snprintf(buf, bufsz, _("%s is write-protected but explicit read-write mode requested"), src); -+ else if (mflags & MS_REMOUNT) -+ snprintf(buf, bufsz, _("cannot remount %s read-write, is write-protected"), src); -+ else if (mflags & MS_BIND) -+ snprintf(buf, bufsz, _("bind %s failed"), src); -+ else { -+ errno = syserr; -+ snprintf(buf, bufsz, _("mount(2) system call failed: %m")); -+ } -+ break; -+ -+ case ENOMEDIUM: -+ if (uflags & MNT_MS_NOFAIL) -+ return MNT_EX_SUCCESS; -+ if (buf) -+ snprintf(buf, bufsz, _("no medium found on %s"), src); -+ break; -+ -+ case EBADMSG: -+ /* Bad CRC for classic filesystems (e.g. extN or XFS) */ -+ if (buf && src && stat(src, &st) == 0 -+ && (S_ISBLK(st.st_mode) || S_ISREG(st.st_mode))) { -+ snprintf(buf, bufsz, _("cannot mount; probably corrupted filesystem on %s"), src); -+ break; -+ } -+ /* fallthrough */ -+ -+ default: -+ if (buf) { -+ errno = syserr; -+ snprintf(buf, bufsz, _("mount(2) system call failed: %m")); -+ } -+ break; -+ } - -- return MNT_EX_FAIL; -+ return MNT_EX_FAIL; - } - @@ -27,8 +27,7 @@ source=("git+https://github.com/karelzak/util-linux.git" 'pam-runuser' 'pam-su' '60-rfkill.rules' - 'util-linux.sysusers' - '0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch') + 'util-linux.sysusers') #--BUILD CONFIGURATION------------------------------------------------------ @@ -47,12 +46,6 @@ pkgver() { git describe --tags | sed 's/-/+/g' } -prepare() { - cd util-linux - - patch -Np1 < ../0001-libmount-don-t-use-symfollow-for-helpers-on-user-mounts.patch -} - #--BUILD CONTROL------------------------------------------------------------ path=( @@ -181,5 +174,4 @@ sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' - 'SKIP' 'SKIP') |