libmount: switch namespace when appropriate

Signed-off-by: Vaclav Dolezal <vdolezal@redhat.com>
This commit is contained in:
Vaclav Dolezal 2018-04-11 15:52:52 +02:00 committed by Karel Zak
parent 65ca7b5a9b
commit cddd2eaa27
4 changed files with 241 additions and 19 deletions

View File

@ -213,6 +213,8 @@ int mnt_context_reset_status(struct libmnt_context *cxt)
static int context_init_paths(struct libmnt_context *cxt, int writable) static int context_init_paths(struct libmnt_context *cxt, int writable)
{ {
struct libmnt_ns *ns_old;
assert(cxt); assert(cxt);
#ifdef USE_LIBMOUNT_SUPPORT_MTAB #ifdef USE_LIBMOUNT_SUPPORT_MTAB
@ -233,6 +235,10 @@ static int context_init_paths(struct libmnt_context *cxt, int writable)
cxt->mtab_writable = 0; cxt->mtab_writable = 0;
ns_old = mnt_context_switch_target_ns(cxt);
if (!ns_old)
return -MNT_ERR_NAMESPACE;
#ifdef USE_LIBMOUNT_SUPPORT_MTAB #ifdef USE_LIBMOUNT_SUPPORT_MTAB
mnt_has_regular_mtab(&cxt->mtab_path, &cxt->mtab_writable); mnt_has_regular_mtab(&cxt->mtab_path, &cxt->mtab_writable);
if (!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 */ /* use /run/mount/utab if /etc/mtab is useless */
mnt_has_regular_utab(&cxt->utab_path, &cxt->utab_writable); 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; cxt->flags |= MNT_FL_TABPATHS_CHECKED;
return 0; 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) int mnt_context_get_fstab(struct libmnt_context *cxt, struct libmnt_table **tb)
{ {
struct libmnt_ns *ns_old;
if (!cxt) if (!cxt)
return -EINVAL; return -EINVAL;
if (!cxt->fstab) { if (!cxt->fstab) {
@ -1044,8 +1055,17 @@ int mnt_context_get_fstab(struct libmnt_context *cxt, struct libmnt_table **tb)
return -ENOMEM; return -ENOMEM;
if (cxt->table_errcb) if (cxt->table_errcb)
mnt_table_set_parser_errcb(cxt->fstab, 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)); mnt_table_set_cache(cxt->fstab, mnt_context_get_cache(cxt));
rc = mnt_table_parse_fstab(cxt->fstab, NULL); rc = mnt_table_parse_fstab(cxt->fstab, NULL);
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
if (rc) if (rc)
return 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 mnt_context_get_mtab(struct libmnt_context *cxt, struct libmnt_table **tb)
{ {
int rc = 0;
struct libmnt_ns *ns_old = NULL;
if (!cxt) if (!cxt)
return -EINVAL; return -EINVAL;
if (!cxt->mtab) { 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); context_init_paths(cxt, 0);
cxt->mtab = mnt_new_table(); cxt->mtab = mnt_new_table();
if (!cxt->mtab) if (!cxt->mtab) {
return -ENOMEM; rc = -ENOMEM;
goto end;
}
if (cxt->table_errcb) if (cxt->table_errcb)
mnt_table_set_parser_errcb(cxt->mtab, 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 else
rc = mnt_table_parse_mtab(cxt->mtab, cxt->mtab_path); rc = mnt_table_parse_mtab(cxt->mtab, cxt->mtab_path);
if (rc) if (rc)
return rc; goto end;
} }
if (tb) 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]", DBG(CXT, ul_debugobj(cxt, "mtab requested [nents=%d]",
mnt_table_get_nents(cxt->mtab))); 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; struct libmnt_cache *cache = NULL;
char *cn_tgt = NULL; char *cn_tgt = NULL;
int rc; 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)) if (mnt_context_is_nocanonicalize(cxt))
mnt_context_set_tabfilter(cxt, mtab_filter, (void *) tgt); 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); rc = mnt_context_get_mtab(cxt, mtab);
mnt_context_set_tabfilter(cxt, NULL, NULL); mnt_context_set_tabfilter(cxt, NULL, NULL);
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
if (cn_tgt && !cache) if (cn_tgt && !cache)
free(cn_tgt); free(cn_tgt);
@ -1201,6 +1241,7 @@ int mnt_context_get_table(struct libmnt_context *cxt,
const char *filename, struct libmnt_table **tb) const char *filename, struct libmnt_table **tb)
{ {
int rc; int rc;
struct libmnt_ns *ns_old;
if (!cxt || !tb) if (!cxt || !tb)
return -EINVAL; return -EINVAL;
@ -1212,14 +1253,24 @@ int mnt_context_get_table(struct libmnt_context *cxt,
if (cxt->table_errcb) if (cxt->table_errcb)
mnt_table_set_parser_errcb(*tb, 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); rc = mnt_table_parse_file(*tb, filename);
if (rc) { if (rc) {
mnt_unref_table(*tb); mnt_unref_table(*tb);
return rc; goto end;
} }
mnt_table_set_cache(*tb, mnt_context_get_cache(cxt)); 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; struct libmnt_cache *cache;
const char *t, *v, *src; const char *t, *v, *src;
int rc = 0; int rc = 0;
struct libmnt_ns *ns_old;
assert(cxt); assert(cxt);
assert(cxt->fs); assert(cxt->fs);
@ -1551,6 +1603,10 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt)
DBG(CXT, ul_debugobj(cxt, "srcpath '%s'", src)); 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); cache = mnt_context_get_cache(cxt);
if (!mnt_fs_get_tag(cxt->fs, &t, &v)) { if (!mnt_fs_get_tag(cxt->fs, &t, &v)) {
@ -1573,7 +1629,7 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt)
if (rc) { if (rc) {
DBG(CXT, ul_debugobj(cxt, "failed to prepare srcpath [rc=%d]", rc)); DBG(CXT, ul_debugobj(cxt, "failed to prepare srcpath [rc=%d]", rc));
return rc; goto end;
} }
if (!path) if (!path)
@ -1582,7 +1638,7 @@ int mnt_context_prepare_srcpath(struct libmnt_context *cxt)
if ((cxt->mountflags & (MS_BIND | MS_MOVE | MS_REMOUNT)) if ((cxt->mountflags & (MS_BIND | MS_MOVE | MS_REMOUNT))
|| mnt_fs_is_pseudofs(cxt->fs)) { || mnt_fs_is_pseudofs(cxt->fs)) {
DBG(CXT, ul_debugobj(cxt, "REMOUNT/BIND/MOVE/pseudo FS source: %s", path)); 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)) { if (mnt_context_is_loopdev(cxt)) {
rc = mnt_context_setup_loopdev(cxt); rc = mnt_context_setup_loopdev(cxt);
if (rc) if (rc)
return rc; goto end;
} }
DBG(CXT, ul_debugobj(cxt, "final srcpath '%s'", DBG(CXT, ul_debugobj(cxt, "final srcpath '%s'",
mnt_fs_get_source(cxt->fs))); 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[=<mode>] specified */ /* create a mountpoint if X-mount.mkdir[=<mode>] specified */
@ -1649,6 +1709,7 @@ int mnt_context_prepare_target(struct libmnt_context *cxt)
const char *tgt; const char *tgt;
struct libmnt_cache *cache; struct libmnt_cache *cache;
int rc = 0; int rc = 0;
struct libmnt_ns *ns_old;
assert(cxt); assert(cxt);
assert(cxt->fs); assert(cxt->fs);
@ -1660,6 +1721,10 @@ int mnt_context_prepare_target(struct libmnt_context *cxt)
if (!tgt) if (!tgt)
return 0; return 0;
ns_old = mnt_context_switch_target_ns(cxt);
if (!ns_old)
return -MNT_ERR_NAMESPACE;
/* mkdir target */ /* mkdir target */
if (cxt->action == MNT_ACT_MOUNT if (cxt->action == MNT_ACT_MOUNT
&& !mnt_context_is_restricted(cxt) && !mnt_context_is_restricted(cxt)
@ -1667,8 +1732,11 @@ int mnt_context_prepare_target(struct libmnt_context *cxt)
cxt->user_mountflags & MNT_MS_XFSTABCOMM)) { cxt->user_mountflags & MNT_MS_XFSTABCOMM)) {
rc = mkdir_target(tgt, cxt->fs); 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 */ return rc; /* mkdir or parse error */
}
} }
/* canonicalize the path */ /* canonicalize the path */
@ -1679,6 +1747,9 @@ int mnt_context_prepare_target(struct libmnt_context *cxt)
rc = mnt_fs_set_target(cxt->fs, path); rc = mnt_fs_set_target(cxt->fs, path);
} }
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
if (rc) if (rc)
DBG(CXT, ul_debugobj(cxt, "failed to prepare target '%s'", tgt)); DBG(CXT, ul_debugobj(cxt, "failed to prepare target '%s'", tgt));
else 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 mnt_context_guess_srcpath_fstype(struct libmnt_context *cxt, char **type)
{ {
int rc = 0; int rc = 0;
struct libmnt_ns *ns_old;
const char *dev = mnt_fs_get_srcpath(cxt->fs); const char *dev = mnt_fs_get_srcpath(cxt->fs);
*type = NULL; *type = NULL;
@ -1701,6 +1773,10 @@ int mnt_context_guess_srcpath_fstype(struct libmnt_context *cxt, char **type)
if (!dev) if (!dev)
goto done; goto done;
ns_old = mnt_context_switch_target_ns(cxt);
if (!ns_old)
return -MNT_ERR_NAMESPACE;
if (access(dev, F_OK) == 0) { if (access(dev, F_OK) == 0) {
struct libmnt_cache *cache = mnt_context_get_cache(cxt); struct libmnt_cache *cache = mnt_context_get_cache(cxt);
int ambi = 0; int ambi = 0;
@ -1718,6 +1794,9 @@ int mnt_context_guess_srcpath_fstype(struct libmnt_context *cxt, char **type)
*type = strdup("cifs"); *type = strdup("cifs");
} }
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
done: done:
return rc; 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 search_path[] = FS_SEARCH_PATH; /* from config.h */
char *p = NULL, *path; char *p = NULL, *path;
struct libmnt_ns *ns_old;
assert(cxt); assert(cxt);
assert(cxt->fs); 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)) || mnt_fs_is_swaparea(cxt->fs))
return 0; return 0;
ns_old = mnt_context_switch_origin_ns(cxt);
if (!ns_old)
return -MNT_ERR_NAMESPACE;
path = strtok_r(search_path, ":", &p); path = strtok_r(search_path, ":", &p);
while (path) { while (path) {
char helper[PATH_MAX]; char helper[PATH_MAX];
@ -1824,6 +1908,9 @@ int mnt_context_prepare_helper(struct libmnt_context *cxt, const char *name,
if (rc) if (rc)
continue; continue;
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
free(cxt->helper); free(cxt->helper);
cxt->helper = strdup(helper); cxt->helper = strdup(helper);
if (!cxt->helper) if (!cxt->helper)
@ -1831,6 +1918,8 @@ int mnt_context_prepare_helper(struct libmnt_context *cxt, const char *name,
return 0; return 0;
} }
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return 0; return 0;
} }
@ -1933,6 +2022,8 @@ int mnt_context_prepare_update(struct libmnt_context *cxt)
int mnt_context_update_tabs(struct libmnt_context *cxt) int mnt_context_update_tabs(struct libmnt_context *cxt)
{ {
unsigned long fl; unsigned long fl;
int rc = 0;
struct libmnt_ns *ns_old;
assert(cxt); assert(cxt);
@ -1945,6 +2036,10 @@ int mnt_context_update_tabs(struct libmnt_context *cxt)
return 0; return 0;
} }
ns_old = mnt_context_switch_target_ns(cxt);
if (!ns_old)
return -MNT_ERR_NAMESPACE;
/* check utab update when external helper executed */ /* check utab update when external helper executed */
if (mnt_context_helper_executed(cxt) if (mnt_context_helper_executed(cxt)
&& mnt_context_get_helper_status(cxt) == 0 && 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)) { if (mnt_update_already_done(cxt->update, cxt->lock)) {
DBG(CXT, ul_debugobj(cxt, "don't update: error evaluate or already updated")); DBG(CXT, ul_debugobj(cxt, "don't update: error evaluate or already updated"));
return 0; goto end;
} }
} else if (cxt->helper) { } else if (cxt->helper) {
DBG(CXT, ul_debugobj(cxt, "don't update: external helper")); DBG(CXT, ul_debugobj(cxt, "don't update: external helper"));
return 0; goto end;
} }
if (cxt->syscall_status != 0 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)) { mnt_context_get_helper_status(cxt) == 0)) {
DBG(CXT, ul_debugobj(cxt, "don't update: syscall/helper failed/not called")); DBG(CXT, ul_debugobj(cxt, "don't update: syscall/helper failed/not called"));
return 0; goto end;
} }
fl = mnt_update_get_mflags(cxt->update); 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, mnt_update_force_rdonly(cxt->update,
cxt->mountflags & MS_RDONLY); 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, 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 mnt_context_apply_fstab(struct libmnt_context *cxt)
{ {
int rc = -1, isremount = 0, iscmdbind = 0; int rc = -1, isremount = 0, iscmdbind = 0;
struct libmnt_ns *ns_old;
struct libmnt_table *tab = NULL; struct libmnt_table *tab = NULL;
const char *src = NULL, *tgt = NULL; const char *src = NULL, *tgt = NULL;
unsigned long mflags = 0; unsigned long mflags = 0;
@ -2124,6 +2225,10 @@ int mnt_context_apply_fstab(struct libmnt_context *cxt)
/* let's initialize cxt->fs */ /* let's initialize cxt->fs */
ignore_result( mnt_context_get_fs(cxt) ); ignore_result( mnt_context_get_fs(cxt) );
ns_old = mnt_context_switch_target_ns(cxt);
if (!ns_old)
return -MNT_ERR_NAMESPACE;
/* try fstab */ /* try fstab */
if (cxt->optsmode & MNT_OMODE_FSTAB) { if (cxt->optsmode & MNT_OMODE_FSTAB) {
DBG(CXT, ul_debugobj(cxt, "trying to apply fstab (src=%s, target=%s)", src, tgt)); 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) if (!rc)
rc = apply_table(cxt, tab, MNT_ITER_BACKWARD); rc = apply_table(cxt, tab, MNT_ITER_BACKWARD);
} }
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
if (rc) { if (rc) {
if (!mnt_context_is_restricted(cxt) if (!mnt_context_is_restricted(cxt)
&& tgt && !src && tgt && !src
@ -2477,10 +2586,15 @@ int mnt_context_is_fs_mounted(struct libmnt_context *cxt,
{ {
struct libmnt_table *mtab, *orig; struct libmnt_table *mtab, *orig;
int rc; int rc;
struct libmnt_ns *ns_old;
if (!cxt || !fs || !mounted) if (!cxt || !fs || !mounted)
return -EINVAL; return -EINVAL;
ns_old = mnt_context_switch_target_ns(cxt);
if (!ns_old)
return -MNT_ERR_NAMESPACE;
orig = cxt->mtab; orig = cxt->mtab;
rc = mnt_context_get_mtab(cxt, &mtab); rc = mnt_context_get_mtab(cxt, &mtab);
if (rc == -ENOENT && mnt_fs_streq_target(fs, "/proc") && 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; return rc;
*mounted = mnt_table_is_fs_mounted(mtab, fs); *mounted = mnt_table_is_fs_mounted(mtab, fs);
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return 0; return 0;
} }

View File

@ -89,6 +89,7 @@ is_mounted_same_loopfile(struct libmnt_context *cxt,
struct libmnt_cache *cache; struct libmnt_cache *cache;
const char *bf; const char *bf;
int rc = 0; int rc = 0;
struct libmnt_ns *ns_old;
assert(cxt); assert(cxt);
assert(cxt->fs); assert(cxt->fs);
@ -97,6 +98,10 @@ is_mounted_same_loopfile(struct libmnt_context *cxt,
if (mnt_context_get_mtab(cxt, &tb)) if (mnt_context_get_mtab(cxt, &tb))
return 0; 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", DBG(LOOP, ul_debugobj(cxt, "checking if %s mounted on %s",
backing_file, target)); backing_file, target));
@ -132,6 +137,9 @@ is_mounted_same_loopfile(struct libmnt_context *cxt,
} }
if (rc) if (rc)
DBG(LOOP, ul_debugobj(cxt, "%s already mounted", backing_file)); DBG(LOOP, ul_debugobj(cxt, "%s already mounted", backing_file));
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return rc; return rc;
} }

View File

@ -184,6 +184,7 @@ static int is_option(const char *name, size_t namesz,
static int fix_optstr(struct libmnt_context *cxt) static int fix_optstr(struct libmnt_context *cxt)
{ {
int rc = 0; int rc = 0;
struct libmnt_ns *ns_old;
char *next; char *next;
char *name, *val; char *name, *val;
size_t namesz, valsz; size_t namesz, valsz;
@ -342,9 +343,18 @@ static int fix_optstr(struct libmnt_context *cxt)
goto done; 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); rc = mnt_optstr_fix_user(&fs->user_optstr);
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
}
/* refresh merged optstr */ /* refresh merged optstr */
free(fs->optstr); free(fs->optstr);
fs->optstr = NULL; fs->optstr = NULL;
@ -629,6 +639,9 @@ static int exec_helper(struct libmnt_context *cxt)
if (setuid(getuid()) < 0) if (setuid(getuid()) < 0)
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
if (!mnt_context_switch_origin_ns(cxt))
_exit(EXIT_FAILURE);
type = mnt_fs_get_fstype(cxt->fs); type = mnt_fs_get_fstype(cxt->fs);
args[i++] = cxt->helper; /* 1 */ 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 neg = pattern && strncmp(pattern, "no", 2) == 0;
int rc = -EINVAL; int rc = -EINVAL;
char **filesystems, **fp; char **filesystems, **fp;
struct libmnt_ns *ns_old;
assert(cxt); assert(cxt);
assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); 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 * 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); rc = mnt_get_filesystems(&filesystems, neg ? pattern : NULL);
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
if (rc) if (rc)
return 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 mnt_context_prepare_mount(struct libmnt_context *cxt)
{ {
int rc = -EINVAL; int rc = -EINVAL;
struct libmnt_ns *ns_old;
if (!cxt || !cxt->fs || mnt_fs_is_swaparea(cxt->fs)) if (!cxt || !cxt->fs || mnt_fs_is_swaparea(cxt->fs))
return -EINVAL; return -EINVAL;
@ -947,6 +967,10 @@ int mnt_context_prepare_mount(struct libmnt_context *cxt)
cxt->action = MNT_ACT_MOUNT; 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")); DBG(CXT, ul_debugobj(cxt, "mount: preparing"));
rc = mnt_context_apply_fstab(cxt); 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); rc = mnt_context_prepare_helper(cxt, "mount", NULL);
if (rc) { if (rc) {
DBG(CXT, ul_debugobj(cxt, "mount: preparing failed")); DBG(CXT, ul_debugobj(cxt, "mount: preparing failed"));
return rc; goto end;
} }
cxt->flags |= MNT_FL_PREPARED; cxt->flags |= MNT_FL_PREPARED;
end:
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return rc; return rc;
} }
@ -999,6 +1028,7 @@ int mnt_context_do_mount(struct libmnt_context *cxt)
{ {
const char *type; const char *type;
int res; int res;
struct libmnt_ns *ns_old;
assert(cxt); assert(cxt);
assert(cxt->fs); assert(cxt->fs);
@ -1013,6 +1043,10 @@ int mnt_context_do_mount(struct libmnt_context *cxt)
if (!(cxt->flags & MNT_FL_MOUNTDATA)) if (!(cxt->flags & MNT_FL_MOUNTDATA))
cxt->mountdata = (char *) mnt_fs_get_fs_options(cxt->fs); 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); type = mnt_fs_get_fstype(cxt->fs);
if (type) { if (type) {
if (strchr(type, ',')) if (strchr(type, ','))
@ -1064,6 +1098,8 @@ int mnt_context_do_mount(struct libmnt_context *cxt)
} }
} }
#endif #endif
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return res; return res;
} }
@ -1148,12 +1184,17 @@ int mnt_context_finalize_mount(struct libmnt_context *cxt)
int mnt_context_mount(struct libmnt_context *cxt) int mnt_context_mount(struct libmnt_context *cxt)
{ {
int rc; int rc;
struct libmnt_ns *ns_old;
assert(cxt); assert(cxt);
assert(cxt->fs); assert(cxt->fs);
assert(cxt->helper_exec_status == 1); assert(cxt->helper_exec_status == 1);
assert(cxt->syscall_status == 1); assert(cxt->syscall_status == 1);
ns_old = mnt_context_switch_target_ns(cxt);
if (!ns_old)
return -MNT_ERR_NAMESPACE;
again: again:
rc = mnt_context_prepare_mount(cxt); rc = mnt_context_prepare_mount(cxt);
if (!rc) if (!rc)
@ -1188,6 +1229,8 @@ again:
goto again; goto again;
} }
} }
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return rc; return rc;
} }
@ -1344,6 +1387,11 @@ static int is_shared_tree(struct libmnt_context *cxt, const char *dir)
unsigned long mflags = 0; unsigned long mflags = 0;
char *mnt = NULL, *p; char *mnt = NULL, *p;
int rc = 0; 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) if (!dir)
return 0; return 0;
@ -1365,6 +1413,8 @@ static int is_shared_tree(struct libmnt_context *cxt, const char *dir)
&& (mflags & MS_SHARED); && (mflags & MS_SHARED);
done: done:
free(mnt); free(mnt);
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return rc; return rc;
} }

View File

@ -51,6 +51,7 @@ int mnt_context_find_umount_fs(struct libmnt_context *cxt,
struct libmnt_fs **pfs) struct libmnt_fs **pfs)
{ {
int rc; int rc;
struct libmnt_ns *ns_old;
struct libmnt_table *mtab = NULL; struct libmnt_table *mtab = NULL;
struct libmnt_fs *fs; struct libmnt_fs *fs;
char *loopdev = NULL; char *loopdev = NULL;
@ -100,6 +101,10 @@ int mnt_context_find_umount_fs(struct libmnt_context *cxt,
return 1; return 1;
} }
ns_old = mnt_context_switch_target_ns(cxt);
if (!ns_old)
return -MNT_ERR_NAMESPACE;
try_loopdev: try_loopdev:
fs = mnt_table_find_target(mtab, tgt, MNT_ITER_BACKWARD); fs = mnt_table_find_target(mtab, tgt, MNT_ITER_BACKWARD);
if (!fs && mnt_context_is_swapmatch(cxt)) { if (!fs && mnt_context_is_swapmatch(cxt)) {
@ -159,12 +164,16 @@ try_loopdev:
if (pfs) if (pfs)
*pfs = fs; *pfs = fs;
free(loopdev); 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) : DBG(CXT, ul_debugobj(cxt, "umount fs: %s", fs ? mnt_fs_get_target(fs) :
"<not found>")); "<not found>"));
return fs ? 0 : 1; return fs ? 0 : 1;
err: err:
free(loopdev); free(loopdev);
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return rc; return rc;
} }
@ -488,12 +497,20 @@ static int evaluate_permissions(struct libmnt_context *cxt)
char *curr_user; char *curr_user;
char *mtab_user = NULL; char *mtab_user = NULL;
size_t sz; size_t sz;
struct libmnt_ns *ns_old;
DBG(CXT, ul_debugobj(cxt, DBG(CXT, ul_debugobj(cxt,
"umount: checking user=<username> from mtab")); "umount: checking user=<username> from mtab"));
ns_old = mnt_context_switch_origin_ns(cxt);
if (!ns_old)
return -MNT_ERR_NAMESPACE;
curr_user = mnt_get_username(getuid()); curr_user = mnt_get_username(getuid());
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
if (!curr_user) { if (!curr_user) {
DBG(CXT, ul_debugobj(cxt, "umount %s: cannot " DBG(CXT, ul_debugobj(cxt, "umount %s: cannot "
"convert %d to username", tgt, getuid())); "convert %d to username", tgt, getuid()));
@ -558,6 +575,9 @@ static int exec_helper(struct libmnt_context *cxt)
if (setuid(getuid()) < 0) if (setuid(getuid()) < 0)
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
if (!mnt_context_switch_origin_ns(cxt))
_exit(EXIT_FAILURE);
type = mnt_fs_get_fstype(cxt->fs); type = mnt_fs_get_fstype(cxt->fs);
args[i++] = cxt->helper; /* 1 */ 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 mnt_context_prepare_umount(struct libmnt_context *cxt)
{ {
int rc; int rc;
struct libmnt_ns *ns_old;
if (!cxt || !cxt->fs || mnt_fs_is_swaparea(cxt->fs)) if (!cxt || !cxt->fs || mnt_fs_is_swaparea(cxt->fs))
return -EINVAL; return -EINVAL;
@ -804,6 +825,10 @@ int mnt_context_prepare_umount(struct libmnt_context *cxt)
cxt->helper = NULL; cxt->helper = NULL;
cxt->action = MNT_ACT_UMOUNT; 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); rc = lookup_umount_fs(cxt);
if (!rc) if (!rc)
rc = mnt_context_merge_mflags(cxt); rc = mnt_context_merge_mflags(cxt);
@ -837,6 +862,10 @@ int mnt_context_prepare_umount(struct libmnt_context *cxt)
return rc; return rc;
} }
cxt->flags |= MNT_FL_PREPARED; cxt->flags |= MNT_FL_PREPARED;
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return rc; 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 mnt_context_do_umount(struct libmnt_context *cxt)
{ {
int rc; int rc;
struct libmnt_ns *ns_old;
assert(cxt); assert(cxt);
assert(cxt->fs); assert(cxt->fs);
@ -870,9 +900,13 @@ int mnt_context_do_umount(struct libmnt_context *cxt)
assert((cxt->action == MNT_ACT_UMOUNT)); assert((cxt->action == MNT_ACT_UMOUNT));
assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); 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); rc = do_umount(cxt);
if (rc) if (rc)
return rc; goto end;
if (mnt_context_get_status(cxt) && !mnt_context_is_fake(cxt)) { 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); cxt->mountflags, NULL, cxt->fs);
} }
} }
end:
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return rc; return rc;
} }
@ -951,6 +989,7 @@ int mnt_context_finalize_umount(struct libmnt_context *cxt)
int mnt_context_umount(struct libmnt_context *cxt) int mnt_context_umount(struct libmnt_context *cxt)
{ {
int rc; int rc;
struct libmnt_ns *ns_old;
assert(cxt); assert(cxt);
assert(cxt->fs); 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))); 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); rc = mnt_context_prepare_umount(cxt);
if (!rc) if (!rc)
rc = mnt_context_prepare_update(cxt); rc = mnt_context_prepare_update(cxt);
@ -966,6 +1009,10 @@ int mnt_context_umount(struct libmnt_context *cxt)
rc = mnt_context_do_umount(cxt); rc = mnt_context_do_umount(cxt);
if (!rc) if (!rc)
rc = mnt_context_update_tabs(cxt); rc = mnt_context_update_tabs(cxt);
if (!mnt_context_switch_ns(cxt, ns_old))
return -MNT_ERR_NAMESPACE;
return rc; return rc;
} }