All Virtuozzo development lists (kernel + QEMU)
 help / color / mirror / Atom feed
From: Mirian Shilakadze <mirian.shilakadze@virtuozzo.com>
Subject: [Devel] [PATCH vz10 3/3] ve/fs: take the owner of copied mounts from the namespace, not the task
Date: Mon, 17 Aug 2026 11:16:41 +0400	[thread overview]
Message-ID: <07f25e8bb318c82bc628051fe3882ccfc37befc2.1786950779.git.mirian.shilakadze@virtuozzo.com> (raw)
In-Reply-To: <cover.1786950779.git.mirian.shilakadze@virtuozzo.com>

A new mount takes its ve_owner from get_exec_env(), the VE of the task
doing the work, rather than the VE of the mount namespace it is working
in. The two differ for a ve0 task that has entered a container's mount
namespace and stayed ve0, which is what nsenter -m gives you.

Two places build mounts that way and neither passes through
commit_tree(), so the transfer added by the previous patch cannot correct
them. copy_mnt_ns() takes the owner from the unsharing task unless an
explicit VE was threaded in, which only happens for CLONE_NEWVE, so a
plain unshare(CLONE_NEWNS) hands back a ve0 owned copy of every mount in
the namespace. open_detached_copy() passes NULL to __do_loopback(), so
open_tree(OPEN_TREE_CLONE) mints ve0 owned clones in an anonymous
namespace the mount never leaves before being executed from.

Either one undoes the trusted exec check with one extra command:

  nsenter -t $INITPID -m -- unshare -m -- /ctown/planted

This is older than the mount transfer it defeats. Both paths also launder
a tmpfs the container created entirely on its own, which
ve_check_trusted_file() was already supposed to refuse, so the check has
been avoidable this way since it was added.

Take the owner from the namespace being worked in rather than from the
caller, the same rule commit_tree() follows for a mount that moves. An
explicit VE for a container being created still wins, and nothing changes
for a task working inside its own VE's namespace, which is every normal
mount, bind and unshare.

Note that ve_mount_allowed() tests the limit against get_exec_env() while
ve_mount_nr_inc() charges the owner, so in the mismatched case a ve0 task
passes the check against ve0 and the copies are charged to the container.
That split is older than this patch, which only widens where it applies.

Fixes: d65efacf542b ("trusted/ve/fs/exec: Don't allow a privileged user to execute untrusted files")
Fixes: fc7157b84c32 ("trusted/ve/mmap: Protect from unsecure library load from CT image")
https://virtuozzo.atlassian.net/browse/VSTOR-141429
Feature: ve: ve generic structures
Signed-off-by: Mirian Shilakadze <mirian.shilakadze@virtuozzo.com>
---
 fs/namespace.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index f8319a2b33df..4adc1db84b4c 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2830,6 +2830,7 @@ static int do_change_type(struct path *path, int ms_flags)
 
 static struct mount *__do_loopback(struct path *old_path, int recurse)
 {
+	struct ve_struct *owner = current->nsproxy->mnt_ns->ve_owner;
 	struct mount *mnt = ERR_PTR(-EINVAL), *old = real_mount(old_path->mnt);
 
 	if (IS_MNT_UNBINDABLE(old))
@@ -2846,11 +2847,17 @@ static struct mount *__do_loopback(struct path *old_path, int recurse)
 	if (!recurse && __has_locked_children(old, old_path->dentry))
 		return mnt;
 
+	/*
+	 * The copy belongs to the namespace it is taken from, not to whoever
+	 * is asking. The two differ for a ve0 task working inside a
+	 * container's mount namespace, and open_detached_copy() never reaches
+	 * commit_tree() to have the owner corrected later.
+	 */
 	if (recurse)
 		mnt = copy_tree(old, old_path->dentry, CL_COPY_MNT_NS_FILE,
-				NULL);
+				owner);
 	else
-		mnt = clone_mnt(old, old_path->dentry, 0, NULL);
+		mnt = clone_mnt(old, old_path->dentry, 0, owner);
 
 	if (!IS_ERR(mnt))
 		mnt->mnt.mnt_flags &= ~MNT_LOCKED;
@@ -4372,7 +4379,16 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
 
 	old = ns->root;
 
-	new_ns = alloc_mnt_ns(user_ns, false, new_ve);
+	/*
+	 * A copied namespace holds copies of @ns's mounts, so it belongs to
+	 * whoever owns @ns rather than to whoever is unsharing. The two differ
+	 * for a ve0 task working inside a container's mount namespace, and
+	 * copy_mnt_ns() populates the namespace directly, without going
+	 * through commit_tree() where the owner would otherwise be corrected.
+	 * An explicit @new_ve still wins: a container being created owns the
+	 * namespace made for it.
+	 */
+	new_ns = alloc_mnt_ns(user_ns, false, new_ve ?: ns->ve_owner);
 	if (IS_ERR(new_ns))
 		return new_ns;
 
-- 
2.43.0


  parent reply	other threads:[~2026-08-17  7:16 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-17  7:16 [Devel] [PATCH vz10 0/3] ve/fs: make mount ownership follow the mount namespace Mirian Shilakadze
2026-08-17  7:16 ` [Devel] [PATCH vz10 1/3] ve/fs: unlink the mount namespace on the copy_mnt_ns() error path Mirian Shilakadze
2026-08-26 15:38   ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-17  7:16 ` [Devel] [PATCH vz10 2/3] ve/fs: transfer mount ownership when a mount enters another VE Mirian Shilakadze
2026-08-26 15:38   ` [Devel] [PATCH RHEL10 COMMIT] " Konstantin Khorenko
2026-08-17  7:16 ` Mirian Shilakadze [this message]
2026-08-26 15:38   ` [Devel] [PATCH RHEL10 COMMIT] ve/fs: take the owner of copied mounts from the namespace, not the task Konstantin Khorenko
2026-08-18 10:40 ` [Devel] [PATCH vz10 0/3] ve/fs: make mount ownership follow the mount namespace Vasileios Almpanis
2026-08-26 15:30   ` Konstantin Khorenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=07f25e8bb318c82bc628051fe3882ccfc37befc2.1786950779.git.mirian.shilakadze@virtuozzo.com \
    --to=mirian.shilakadze@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.