From cddd2eaa27c0c35b1a3bfbe7f76a1c7c1ea46517 Mon Sep 17 00:00:00 2001 From: Vaclav Dolezal Date: Wed, 11 Apr 2018 15:52:52 +0200 Subject: libmount: switch namespace when appropriate Signed-off-by: Vaclav Dolezal --- libmount/src/context.c | 149 ++++++++++++++++++++++++++++++++++++----- libmount/src/context_loopdev.c | 8 +++ libmount/src/context_mount.c | 54 ++++++++++++++- libmount/src/context_umount.c | 49 +++++++++++++- 4 files changed, 241 insertions(+), 19 deletions(-) (limited to 'libmount') diff --git a/libmount/src/context.c b/libmount/src/context.c index fdaa233c1..50ce5ca44 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -213,6 +213,8 @@ int mnt_context_reset_status(struct libmnt_context *cxt) static int context_init_paths(struct libmnt_context *cxt, int writable) { + struct libmnt_ns *ns_old; + assert(cxt); #ifdef USE_LIBMOUNT_SUPPORT_MTAB @@ -233,6 +235,10 @@ static int context_init_paths(struct libmnt_context *cxt, int writable) cxt->mtab_writable = 0; + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + #ifdef USE_LIBMOUNT_SUPPORT_MTAB mnt_has_regular_mtab(&cxt->mtab_path, &cxt->mtab_writable); if (!cxt->mtab_writable) @@ -240,6 +246,9 @@ static int context_init_paths(struct libmnt_context *cxt, int writable) /* use /run/mount/utab if /etc/mtab is useless */ mnt_has_regular_utab(&cxt->utab_path, &cxt->utab_writable); + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + cxt->flags |= MNT_FL_TABPATHS_CHECKED; return 0; } @@ -1034,6 +1043,8 @@ int mnt_context_set_fstab(struct libmnt_context *cxt, struct libmnt_table *tb) */ int mnt_context_get_fstab(struct libmnt_context *cxt, struct libmnt_table **tb) { + struct libmnt_ns *ns_old; + if (!cxt) return -EINVAL; if (!cxt->fstab) { @@ -1044,8 +1055,17 @@ int mnt_context_get_fstab(struct libmnt_context *cxt, struct libmnt_table **tb) return -ENOMEM; if (cxt->table_errcb) mnt_table_set_parser_errcb(cxt->fstab, cxt->table_errcb); + + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + mnt_table_set_cache(cxt->fstab, mnt_context_get_cache(cxt)); rc = mnt_table_parse_fstab(cxt->fstab, NULL); + + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + if (rc) return rc; } @@ -1067,16 +1087,23 @@ int mnt_context_get_fstab(struct libmnt_context *cxt, struct libmnt_table **tb) */ int mnt_context_get_mtab(struct libmnt_context *cxt, struct libmnt_table **tb) { + int rc = 0; + struct libmnt_ns *ns_old = NULL; + if (!cxt) return -EINVAL; if (!cxt->mtab) { - int rc; + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; context_init_paths(cxt, 0); cxt->mtab = mnt_new_table(); - if (!cxt->mtab) - return -ENOMEM; + if (!cxt->mtab) { + rc = -ENOMEM; + goto end; + } if (cxt->table_errcb) mnt_table_set_parser_errcb(cxt->mtab, cxt->table_errcb); @@ -1097,7 +1124,7 @@ int mnt_context_get_mtab(struct libmnt_context *cxt, struct libmnt_table **tb) else rc = mnt_table_parse_mtab(cxt->mtab, cxt->mtab_path); if (rc) - return rc; + goto end; } if (tb) @@ -1105,7 +1132,12 @@ int mnt_context_get_mtab(struct libmnt_context *cxt, struct libmnt_table **tb) DBG(CXT, ul_debugobj(cxt, "mtab requested [nents=%d]", mnt_table_get_nents(cxt->mtab))); - return 0; + +end: + if (ns_old && !mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + + return rc; } /* @@ -1135,6 +1167,11 @@ int mnt_context_get_mtab_for_target(struct libmnt_context *cxt, struct libmnt_cache *cache = NULL; char *cn_tgt = NULL; int rc; + struct libmnt_ns *ns_old; + + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; if (mnt_context_is_nocanonicalize(cxt)) mnt_context_set_tabfilter(cxt, mtab_filter, (void *) tgt); @@ -1149,6 +1186,9 @@ int mnt_context_get_mtab_for_target(struct libmnt_context *cxt, rc = mnt_context_get_mtab(cxt, mtab); mnt_context_set_tabfilter(cxt, NULL, NULL); + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + if (cn_tgt && !cache) free(cn_tgt); @@ -1201,6 +1241,7 @@ int mnt_context_get_table(struct libmnt_context *cxt, const char *filename, struct libmnt_table **tb) { int rc; + struct libmnt_ns *ns_old; if (!cxt || !tb) return -EINVAL; @@ -1212,14 +1253,24 @@ int mnt_context_get_table(struct libmnt_context *cxt, if (cxt->table_errcb) mnt_table_set_parser_errcb(*tb, cxt->table_errcb); + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + rc = mnt_table_parse_file(*tb, filename); + if (rc) { mnt_unref_table(*tb); - return rc; + goto end; } mnt_table_set_cache(*tb, mnt_context_get_cache(cxt)); - return 0; + +end: + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + + return rc; } /** @@ -1530,6 +1581,7 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt) struct libmnt_cache *cache; const char *t, *v, *src; int rc = 0; + struct libmnt_ns *ns_old; assert(cxt); assert(cxt->fs); @@ -1551,6 +1603,10 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt) DBG(CXT, ul_debugobj(cxt, "srcpath '%s'", src)); + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + cache = mnt_context_get_cache(cxt); if (!mnt_fs_get_tag(cxt->fs, &t, &v)) { @@ -1573,7 +1629,7 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt) if (rc) { DBG(CXT, ul_debugobj(cxt, "failed to prepare srcpath [rc=%d]", rc)); - return rc; + goto end; } if (!path) @@ -1582,7 +1638,7 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt) if ((cxt->mountflags & (MS_BIND | MS_MOVE | MS_REMOUNT)) || mnt_fs_is_pseudofs(cxt->fs)) { DBG(CXT, ul_debugobj(cxt, "REMOUNT/BIND/MOVE/pseudo FS source: %s", path)); - return rc; + goto end; } /* @@ -1591,12 +1647,16 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt) if (mnt_context_is_loopdev(cxt)) { rc = mnt_context_setup_loopdev(cxt); if (rc) - return rc; + goto end; } DBG(CXT, ul_debugobj(cxt, "final srcpath '%s'", mnt_fs_get_source(cxt->fs))); - return 0; + +end: + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + return rc; } /* create a mountpoint if X-mount.mkdir[=] specified */ @@ -1649,6 +1709,7 @@ int mnt_context_prepare_target(struct libmnt_context *cxt) const char *tgt; struct libmnt_cache *cache; int rc = 0; + struct libmnt_ns *ns_old; assert(cxt); assert(cxt->fs); @@ -1660,6 +1721,10 @@ int mnt_context_prepare_target(struct libmnt_context *cxt) if (!tgt) return 0; + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + /* mkdir target */ if (cxt->action == MNT_ACT_MOUNT && !mnt_context_is_restricted(cxt) @@ -1667,8 +1732,11 @@ int mnt_context_prepare_target(struct libmnt_context *cxt) cxt->user_mountflags & MNT_MS_XFSTABCOMM)) { rc = mkdir_target(tgt, cxt->fs); - if (rc) + if (rc) { + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; return rc; /* mkdir or parse error */ + } } /* canonicalize the path */ @@ -1679,6 +1747,9 @@ int mnt_context_prepare_target(struct libmnt_context *cxt) rc = mnt_fs_set_target(cxt->fs, path); } + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + if (rc) DBG(CXT, ul_debugobj(cxt, "failed to prepare target '%s'", tgt)); else @@ -1694,6 +1765,7 @@ int mnt_context_prepare_target(struct libmnt_context *cxt) int mnt_context_guess_srcpath_fstype(struct libmnt_context *cxt, char **type) { int rc = 0; + struct libmnt_ns *ns_old; const char *dev = mnt_fs_get_srcpath(cxt->fs); *type = NULL; @@ -1701,6 +1773,10 @@ int mnt_context_guess_srcpath_fstype(struct libmnt_context *cxt, char **type) if (!dev) goto done; + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + if (access(dev, F_OK) == 0) { struct libmnt_cache *cache = mnt_context_get_cache(cxt); int ambi = 0; @@ -1718,6 +1794,9 @@ int mnt_context_guess_srcpath_fstype(struct libmnt_context *cxt, char **type) *type = strdup("cifs"); } + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + done: return rc; } @@ -1779,6 +1858,7 @@ int mnt_context_prepare_helper(struct libmnt_context *cxt, const char *name, { char search_path[] = FS_SEARCH_PATH; /* from config.h */ char *p = NULL, *path; + struct libmnt_ns *ns_old; assert(cxt); assert(cxt->fs); @@ -1797,6 +1877,10 @@ int mnt_context_prepare_helper(struct libmnt_context *cxt, const char *name, || mnt_fs_is_swaparea(cxt->fs)) return 0; + ns_old = mnt_context_switch_origin_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + path = strtok_r(search_path, ":", &p); while (path) { char helper[PATH_MAX]; @@ -1824,6 +1908,9 @@ int mnt_context_prepare_helper(struct libmnt_context *cxt, const char *name, if (rc) continue; + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + free(cxt->helper); cxt->helper = strdup(helper); if (!cxt->helper) @@ -1831,6 +1918,8 @@ int mnt_context_prepare_helper(struct libmnt_context *cxt, const char *name, return 0; } + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; return 0; } @@ -1933,6 +2022,8 @@ int mnt_context_prepare_update(struct libmnt_context *cxt) int mnt_context_update_tabs(struct libmnt_context *cxt) { unsigned long fl; + int rc = 0; + struct libmnt_ns *ns_old; assert(cxt); @@ -1945,6 +2036,10 @@ int mnt_context_update_tabs(struct libmnt_context *cxt) return 0; } + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + /* check utab update when external helper executed */ if (mnt_context_helper_executed(cxt) && mnt_context_get_helper_status(cxt) == 0 @@ -1952,11 +2047,11 @@ int mnt_context_update_tabs(struct libmnt_context *cxt) if (mnt_update_already_done(cxt->update, cxt->lock)) { DBG(CXT, ul_debugobj(cxt, "don't update: error evaluate or already updated")); - return 0; + goto end; } } else if (cxt->helper) { DBG(CXT, ul_debugobj(cxt, "don't update: external helper")); - return 0; + goto end; } if (cxt->syscall_status != 0 @@ -1964,7 +2059,7 @@ int mnt_context_update_tabs(struct libmnt_context *cxt) mnt_context_get_helper_status(cxt) == 0)) { DBG(CXT, ul_debugobj(cxt, "don't update: syscall/helper failed/not called")); - return 0; + goto end; } fl = mnt_update_get_mflags(cxt->update); @@ -1975,7 +2070,12 @@ int mnt_context_update_tabs(struct libmnt_context *cxt) mnt_update_force_rdonly(cxt->update, cxt->mountflags & MS_RDONLY); - return mnt_update_table(cxt->update, cxt->lock); + rc = mnt_update_table(cxt->update, cxt->lock); + +end: + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + return rc; } static int apply_table(struct libmnt_context *cxt, struct libmnt_table *tb, @@ -2063,6 +2163,7 @@ static int apply_table(struct libmnt_context *cxt, struct libmnt_table *tb, int mnt_context_apply_fstab(struct libmnt_context *cxt) { int rc = -1, isremount = 0, iscmdbind = 0; + struct libmnt_ns *ns_old; struct libmnt_table *tab = NULL; const char *src = NULL, *tgt = NULL; unsigned long mflags = 0; @@ -2124,6 +2225,10 @@ int mnt_context_apply_fstab(struct libmnt_context *cxt) /* let's initialize cxt->fs */ ignore_result( mnt_context_get_fs(cxt) ); + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + /* try fstab */ if (cxt->optsmode & MNT_OMODE_FSTAB) { DBG(CXT, ul_debugobj(cxt, "trying to apply fstab (src=%s, target=%s)", src, tgt)); @@ -2143,6 +2248,10 @@ int mnt_context_apply_fstab(struct libmnt_context *cxt) if (!rc) rc = apply_table(cxt, tab, MNT_ITER_BACKWARD); } + + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + if (rc) { if (!mnt_context_is_restricted(cxt) && tgt && !src @@ -2477,10 +2586,15 @@ int mnt_context_is_fs_mounted(struct libmnt_context *cxt, { struct libmnt_table *mtab, *orig; int rc; + struct libmnt_ns *ns_old; if (!cxt || !fs || !mounted) return -EINVAL; + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + orig = cxt->mtab; rc = mnt_context_get_mtab(cxt, &mtab); if (rc == -ENOENT && mnt_fs_streq_target(fs, "/proc") && @@ -2495,6 +2609,9 @@ int mnt_context_is_fs_mounted(struct libmnt_context *cxt, return rc; *mounted = mnt_table_is_fs_mounted(mtab, fs); + + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; return 0; } diff --git a/libmount/src/context_loopdev.c b/libmount/src/context_loopdev.c index b1608dd45..05ff71ae7 100644 --- a/libmount/src/context_loopdev.c +++ b/libmount/src/context_loopdev.c @@ -89,6 +89,7 @@ is_mounted_same_loopfile(struct libmnt_context *cxt, struct libmnt_cache *cache; const char *bf; int rc = 0; + struct libmnt_ns *ns_old; assert(cxt); assert(cxt->fs); @@ -97,6 +98,10 @@ is_mounted_same_loopfile(struct libmnt_context *cxt, if (mnt_context_get_mtab(cxt, &tb)) return 0; + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + DBG(LOOP, ul_debugobj(cxt, "checking if %s mounted on %s", backing_file, target)); @@ -132,6 +137,9 @@ is_mounted_same_loopfile(struct libmnt_context *cxt, } if (rc) DBG(LOOP, ul_debugobj(cxt, "%s already mounted", backing_file)); + + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; return rc; } diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index 572395811..bc3c993bc 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -184,6 +184,7 @@ static int is_option(const char *name, size_t namesz, 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; @@ -342,9 +343,18 @@ static int fix_optstr(struct libmnt_context *cxt) goto done; } - if (!rc && cxt->restricted && (cxt->user_mountflags & MNT_MS_USER)) + + if (!rc && cxt->restricted && (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; @@ -629,6 +639,9 @@ static int exec_helper(struct libmnt_context *cxt) 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 */ @@ -887,6 +900,7 @@ 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)); @@ -904,7 +918,12 @@ static int do_mount_by_pattern(struct libmnt_context *cxt, const char *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; @@ -934,6 +953,7 @@ static int do_mount_by_pattern(struct libmnt_context *cxt, const char *pattern) int mnt_context_prepare_mount(struct libmnt_context *cxt) { int rc = -EINVAL; + struct libmnt_ns *ns_old; if (!cxt || !cxt->fs || mnt_fs_is_swaparea(cxt->fs)) return -EINVAL; @@ -947,6 +967,10 @@ int mnt_context_prepare_mount(struct libmnt_context *cxt) 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); @@ -966,9 +990,14 @@ int mnt_context_prepare_mount(struct libmnt_context *cxt) rc = mnt_context_prepare_helper(cxt, "mount", NULL); if (rc) { DBG(CXT, ul_debugobj(cxt, "mount: preparing failed")); - return rc; + goto end; } cxt->flags |= MNT_FL_PREPARED; + +end: + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + return rc; } @@ -999,6 +1028,7 @@ int mnt_context_do_mount(struct libmnt_context *cxt) { const char *type; int res; + struct libmnt_ns *ns_old; assert(cxt); assert(cxt->fs); @@ -1013,6 +1043,10 @@ int mnt_context_do_mount(struct libmnt_context *cxt) 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, ',')) @@ -1064,6 +1098,8 @@ int mnt_context_do_mount(struct libmnt_context *cxt) } } #endif + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; return res; } @@ -1148,12 +1184,17 @@ int mnt_context_finalize_mount(struct libmnt_context *cxt) int mnt_context_mount(struct libmnt_context *cxt) { 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; + again: rc = mnt_context_prepare_mount(cxt); if (!rc) @@ -1188,6 +1229,8 @@ again: goto again; } } + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; return rc; } @@ -1344,6 +1387,11 @@ static int is_shared_tree(struct libmnt_context *cxt, const char *dir) 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; @@ -1365,6 +1413,8 @@ static int is_shared_tree(struct libmnt_context *cxt, const char *dir) && (mflags & MS_SHARED); done: free(mnt); + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; return rc; } diff --git a/libmount/src/context_umount.c b/libmount/src/context_umount.c index 70628b6cb..b28e6faea 100644 --- a/libmount/src/context_umount.c +++ b/libmount/src/context_umount.c @@ -51,6 +51,7 @@ int mnt_context_find_umount_fs(struct libmnt_context *cxt, struct libmnt_fs **pfs) { int rc; + struct libmnt_ns *ns_old; struct libmnt_table *mtab = NULL; struct libmnt_fs *fs; char *loopdev = NULL; @@ -100,6 +101,10 @@ int mnt_context_find_umount_fs(struct libmnt_context *cxt, return 1; } + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + try_loopdev: fs = mnt_table_find_target(mtab, tgt, MNT_ITER_BACKWARD); if (!fs && mnt_context_is_swapmatch(cxt)) { @@ -159,12 +164,16 @@ try_loopdev: if (pfs) *pfs = fs; free(loopdev); + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; DBG(CXT, ul_debugobj(cxt, "umount fs: %s", fs ? mnt_fs_get_target(fs) : "")); return fs ? 0 : 1; err: free(loopdev); + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; return rc; } @@ -488,12 +497,20 @@ static int evaluate_permissions(struct libmnt_context *cxt) char *curr_user; char *mtab_user = NULL; size_t sz; + struct libmnt_ns *ns_old; DBG(CXT, ul_debugobj(cxt, "umount: checking user= from mtab")); + ns_old = mnt_context_switch_origin_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + curr_user = mnt_get_username(getuid()); + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + if (!curr_user) { DBG(CXT, ul_debugobj(cxt, "umount %s: cannot " "convert %d to username", tgt, getuid())); @@ -558,6 +575,9 @@ static int exec_helper(struct libmnt_context *cxt) 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 */ @@ -789,6 +809,7 @@ static int do_umount(struct libmnt_context *cxt) int mnt_context_prepare_umount(struct libmnt_context *cxt) { int rc; + struct libmnt_ns *ns_old; if (!cxt || !cxt->fs || mnt_fs_is_swaparea(cxt->fs)) return -EINVAL; @@ -804,6 +825,10 @@ int mnt_context_prepare_umount(struct libmnt_context *cxt) cxt->helper = NULL; cxt->action = MNT_ACT_UMOUNT; + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + rc = lookup_umount_fs(cxt); if (!rc) rc = mnt_context_merge_mflags(cxt); @@ -837,6 +862,10 @@ int mnt_context_prepare_umount(struct libmnt_context *cxt) return rc; } cxt->flags |= MNT_FL_PREPARED; + + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + return rc; } @@ -861,6 +890,7 @@ int mnt_context_prepare_umount(struct libmnt_context *cxt) int mnt_context_do_umount(struct libmnt_context *cxt) { int rc; + struct libmnt_ns *ns_old; assert(cxt); assert(cxt->fs); @@ -870,9 +900,13 @@ int mnt_context_do_umount(struct libmnt_context *cxt) assert((cxt->action == MNT_ACT_UMOUNT)); assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + rc = do_umount(cxt); if (rc) - return rc; + goto end; if (mnt_context_get_status(cxt) && !mnt_context_is_fake(cxt)) { /* @@ -897,6 +931,10 @@ int mnt_context_do_umount(struct libmnt_context *cxt) cxt->mountflags, NULL, cxt->fs); } } +end: + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + return rc; } @@ -951,6 +989,7 @@ int mnt_context_finalize_umount(struct libmnt_context *cxt) int mnt_context_umount(struct libmnt_context *cxt) { int rc; + struct libmnt_ns *ns_old; assert(cxt); assert(cxt->fs); @@ -959,6 +998,10 @@ int mnt_context_umount(struct libmnt_context *cxt) DBG(CXT, ul_debugobj(cxt, "umount: %s", mnt_context_get_target(cxt))); + ns_old = mnt_context_switch_target_ns(cxt); + if (!ns_old) + return -MNT_ERR_NAMESPACE; + rc = mnt_context_prepare_umount(cxt); if (!rc) rc = mnt_context_prepare_update(cxt); @@ -966,6 +1009,10 @@ int mnt_context_umount(struct libmnt_context *cxt) rc = mnt_context_do_umount(cxt); if (!rc) rc = mnt_context_update_tabs(cxt); + + if (!mnt_context_switch_ns(cxt, ns_old)) + return -MNT_ERR_NAMESPACE; + return rc; } -- cgit v1.2.3-55-g7522