uint64_t set = 0, clr = 0;
int rc;
+ DBG(HOOK, ul_debugobj(hs, "setting VFS flags"));
+
api = get_sysapi(cxt, hs);
assert(api);
assert(api->fd_tree >= 0);
return rc == 0 ? 0 : -errno;
}
-static int hook_set_propagation(struct libmnt_context *cxt __attribute__((__unused__)),
- const struct libmnt_hookset *hs __attribute__((__unused__)),
+static int hook_set_propagation(struct libmnt_context *cxt,
+ const struct libmnt_hookset *hs,
void *data __attribute__((__unused__)))
{
+ struct libmnt_sysapi *api;
+ struct libmnt_optlist *ol;
+ struct libmnt_iter itr;
+ struct libmnt_opt *opt;
+ int rc = 0;
+
+ DBG(HOOK, ul_debugobj(hs, "setting propagation"));
+
+ ol = mnt_context_get_optlist(cxt);
+ if (!ol)
+ return -ENOMEM;
+
+ api = get_sysapi(cxt, hs);
+ assert(api);
+ assert(api->fd_tree >= 0);
+
+ mnt_reset_iter(&itr, MNT_ITER_FORWARD);
+
+ while (mnt_optlist_next_opt(ol, &itr, &opt) == 0) {
+ const struct libmnt_optmap *map = mnt_opt_get_map(opt);
+ const struct libmnt_optmap *ent = mnt_opt_get_mapent(opt);
+ struct mount_attr attr = { .attr_clr = 0 };
+ unsigned int flgs = AT_EMPTY_PATH;
+
+ if (cxt->map_linux != map)
+ continue;
+ if (mnt_opt_is_external(opt))
+ continue;
+ if (!ent || !ent->id || !(ent->id & MS_PROPAGATION))
+ continue;
+
+ attr.propagation = ent->id & MS_PROPAGATION;
+ if (ent->id & MS_REC)
+ flgs |= AT_RECURSIVE;
+
+ DBG(HOOK, ul_debugobj(hs,
+ "mount_setattr(propagation=0x%08" PRIx64")",
+ (uint64_t) attr.propagation));
+
+ rc = mount_setattr(api->fd_tree, "", flgs, &attr, sizeof(attr));
+ set_syscall_status(cxt, "move_setattr", rc == 0);
+ if (rc != 0)
+ return rc;
+ }
+
return 0;
}
assert(cxt);
assert(hs);
+ DBG(HOOK, ul_debugobj(hs, "initialize API fds"));
+
/* A) tree based operation -- the tree is mount source */
if ((flags & MS_BIND)
|| (flags & MS_MOVE)) {
+ DBG(HOOK, ul_debugobj(hs, " BIND/MOVE"));
path = mnt_fs_get_srcpath(cxt->fs);
if (!path)
return -EINVAL;
/* B) tree based operation -- the tree is mount point */
} else if ((flags & MS_REMOUNT)
|| mnt_context_propagation_only(cxt)) {
+ DBG(HOOK, ul_debugobj(hs, " REMOUNT/propagation"));
path = mnt_fs_get_target(cxt->fs);
if (!path)
return -EINVAL;
if (flags & MS_BIND)
oflg |= OPEN_TREE_CLONE;
- DBG(HOOK, ul_debugobj(hs, "open_tree(%s)", path));
+ DBG(HOOK, ul_debugobj(hs, "open_tree(path=%s, flgs=0x%08lx)", path, oflg));
if (mnt_context_is_fake(cxt))
goto fake;
/* C) FS based operation */
} else {
+ DBG(HOOK, ul_debugobj(hs, " new FS"));
const char *type = mnt_fs_get_fstype(cxt->fs);
if (!type)
hook_attach_target);
/* set propagation (has to be attached to VFS) */
- if (!rc && mnt_optlist_get_propagation(ol) != 0)
+ if (!rc && mnt_optlist_get_propagation(ol))
rc = mnt_context_append_hook(cxt, hs, MNT_STAGE_MOUNT_POST, NULL,
hook_set_propagation);
}
#ifdef UL_HAVE_MOUNT_API
-static inline uint64_t flags_to_attrs(unsigned long flags)
+static inline uint64_t flag_to_attr(unsigned long flag)
{
- uint64_t attrs = 0;
-
- if (flags & MS_RDONLY)
- attrs |= MOUNT_ATTR_RDONLY;
- if (flags & MS_NOSUID)
- attrs |= MOUNT_ATTR_NOSUID;
- if (flags & MS_NOEXEC)
- attrs |= MOUNT_ATTR_NOEXEC;
- if (flags & MS_NODIRATIME)
- attrs |= MOUNT_ATTR_NODIRATIME;
- if (flags & MS_RELATIME)
- attrs |= MOUNT_ATTR_RELATIME;
- if (flags & MS_NOATIME)
- attrs |= MOUNT_ATTR_NOATIME;
- if (flags & MS_STRICTATIME)
- attrs |= MOUNT_ATTR_STRICTATIME;
- if (flags & MS_NOSYMFOLLOW)
- attrs |= MOUNT_ATTR_NOSYMFOLLOW;
-
- return attrs;
+ switch (flag) {
+ case MS_RDONLY:
+ return MOUNT_ATTR_RDONLY;
+ case MS_NOSUID:
+ return MOUNT_ATTR_NOSUID;
+ case MS_NOEXEC:
+ return MOUNT_ATTR_NOEXEC;
+ case MS_NODIRATIME:
+ return MOUNT_ATTR_NODIRATIME;
+ case MS_RELATIME:
+ return MOUNT_ATTR_RELATIME;
+ case MS_NOATIME:
+ return MOUNT_ATTR_NOATIME;
+ case MS_STRICTATIME:
+ return MOUNT_ATTR_STRICTATIME;
+ case MS_NOSYMFOLLOW:
+ return MOUNT_ATTR_NOSYMFOLLOW;
+ }
+ return 0;
}
#endif
if (!ls || !ls->linux_map || !set || !clr)
return -EINVAL;
+ *set = 0, *clr = 0;
mnt_reset_iter(&itr, MNT_ITER_FORWARD);
while (mnt_optlist_next_opt(ls, &itr, &opt) == 0) {
+ uint64_t x;
+
if (ls->linux_map != opt->map)
continue;
if (!opt->ent || !opt->ent->id)
continue;
if (!is_wanted_opt(opt, ls->linux_map, MNT_OL_FLTR_DFLT))
continue;
+ x = flag_to_attr( opt->ent->id );
+ if (!x)
+ continue;
if (opt->ent->mask & MNT_INVERT)
- *clr |= flags_to_attrs( opt->ent->id );
+ *clr |= x;
else
- *set |= flags_to_attrs( opt->ent->id );
+ *set |= x;
}
DBG(OPTLIST, ul_debugobj(ls, "return attrs set=0x%08" PRIx64
- ", clr=0x08%" PRIx64, *set, *clr));
+ ", clr=0x%08" PRIx64, *set, *clr));
return 0;
#endif
return 0;
rest = flags & ~MS_PROPAGATION;
- return (rest == 0 || rest == MS_SILENT);
+ return (rest == 0 || (rest & (MS_SILENT | MS_REC)));
}
int mnt_optlist_is_remount(struct libmnt_optlist *ls)
return 0;
}
+int mnt_opt_is_external(struct libmnt_opt *opt)
+{
+ return opt && opt->external ? 1 : 0;
+}
#ifdef TEST_PROGRAM