mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
fs: Allow statmount() in foreign mount namespace
This patch makes use of the new mnt_ns_id field in struct mnt_id_req to allow users to stat mount entries not in their mount namespace. The rules are the same as listmount(), the user must have CAP_SYS_ADMIN in their user namespace and the target mount namespace must be a child of the current namespace. Co-developed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Josef Bacik <josef@toxicpanda.com> Link: https://lore.kernel.org/r/52a2e17e50ba7aa420bc8bae1d9e88ff593395c1.1719243756.git.josef@toxicpanda.com Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
0a3deb1185
commit
71aacb4c8c
@ -4974,10 +4974,8 @@ static int statmount_fs_type(struct kstatmount *s, struct seq_file *seq)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void statmount_mnt_ns_id(struct kstatmount *s)
|
||||
static void statmount_mnt_ns_id(struct kstatmount *s, struct mnt_namespace *ns)
|
||||
{
|
||||
struct mnt_namespace *ns = current->nsproxy->mnt_ns;
|
||||
|
||||
s->sm.mask |= STATMOUNT_MNT_NS_ID;
|
||||
s->sm.mnt_ns_id = ns->seq;
|
||||
}
|
||||
@ -5079,7 +5077,7 @@ static int do_statmount(struct kstatmount *s)
|
||||
err = statmount_string(s, STATMOUNT_MNT_POINT);
|
||||
|
||||
if (!err && s->mask & STATMOUNT_MNT_NS_ID)
|
||||
statmount_mnt_ns_id(s);
|
||||
statmount_mnt_ns_id(s, ns);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
@ -5196,6 +5194,7 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
|
||||
struct statmount __user *, buf, size_t, bufsize,
|
||||
unsigned int, flags)
|
||||
{
|
||||
struct mnt_namespace *ns __free(mnt_ns_release) = NULL;
|
||||
struct vfsmount *mnt;
|
||||
struct mnt_id_req kreq;
|
||||
struct kstatmount ks;
|
||||
@ -5210,13 +5209,28 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ns = grab_requested_mnt_ns(kreq.mnt_ns_id);
|
||||
if (!ns)
|
||||
return -ENOENT;
|
||||
|
||||
if (kreq.mnt_ns_id && (ns != current->nsproxy->mnt_ns) &&
|
||||
!ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
|
||||
return -ENOENT;
|
||||
|
||||
retry:
|
||||
ret = prepare_kstatmount(&ks, &kreq, buf, bufsize, seq_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
down_read(&namespace_sem);
|
||||
mnt = lookup_mnt_in_ns(kreq.mnt_id, current->nsproxy->mnt_ns);
|
||||
/* Has the namespace already been emptied? */
|
||||
if (kreq.mnt_ns_id && RB_EMPTY_ROOT(&ns->mounts)) {
|
||||
up_read(&namespace_sem);
|
||||
kvfree(ks.seq.buf);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
mnt = lookup_mnt_in_ns(kreq.mnt_id, ns);
|
||||
if (!mnt) {
|
||||
up_read(&namespace_sem);
|
||||
kvfree(ks.seq.buf);
|
||||
@ -5224,7 +5238,12 @@ retry:
|
||||
}
|
||||
|
||||
ks.mnt = mnt;
|
||||
get_fs_root(current->fs, &ks.root);
|
||||
ret = grab_requested_root(ns, &ks.root);
|
||||
if (ret) {
|
||||
up_read(&namespace_sem);
|
||||
kvfree(ks.seq.buf);
|
||||
return ret;
|
||||
}
|
||||
ret = do_statmount(&ks);
|
||||
path_put(&ks.root);
|
||||
up_read(&namespace_sem);
|
||||
|
Loading…
Reference in New Issue
Block a user