We had the same thing for ve cgroup before, so let's also enforce it for
ve namespace. It's much easier when process (thread group) belongs to
one VE exclusively.

Let's do the same to what CLONE_NEWUSER does:

- On clone, fail if CLONE_THREAD is in flags (on new thread creation);
- On unshare, force CLONE_THREAD to flags, which leads to
  check_unshare_flags verifying that the process is single threaded;
- On setns, fail if the process is not single threaded.

Note: This does effectively the same thing that ve_task_can_attach() did
for ve cgroup.

https://virtuozzo.atlassian.net/browse/VSTOR-119941
Signed-off-by: Pavel Tikhomirov <[email protected]>

Feature: ve: ve generic structures
---
 kernel/fork.c            | 8 ++++++++
 kernel/ve/ve_namespace.c | 4 ++++
 2 files changed, 12 insertions(+)

diff --git a/kernel/fork.c b/kernel/fork.c
index cfafff15bb85..5ce4c2ac91c1 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2182,6 +2182,10 @@ __latent_entropy struct task_struct *copy_process(
                if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) ||
                    (task_active_pid_ns(current) != nsp->pid_ns_for_children))
                        return ERR_PTR(-EINVAL);
+
+               /* Do not allow sharing a thread group across VE boundaries. */
+               if (clone_flags & CLONE_NEWVE)
+                       return ERR_PTR(-EINVAL);
        }
 
        if (clone_flags & CLONE_PIDFD) {
@@ -3315,6 +3319,10 @@ int ksys_unshare(unsigned long unshare_flags)
        if (unshare_flags & CLONE_NEWNS)
                unshare_flags |= CLONE_FS;
 
+       /* If unsharing a ve namespace must also unshare the thread group. */
+       if (unshare_flags & CLONE_NEWVE)
+               unshare_flags |= CLONE_THREAD;
+
        err = check_unshare_flags(unshare_flags);
        if (err)
                goto bad_unshare_out;
diff --git a/kernel/ve/ve_namespace.c b/kernel/ve/ve_namespace.c
index e76a41a0fbca..9df82c95f3d5 100644
--- a/kernel/ve/ve_namespace.c
+++ b/kernel/ve/ve_namespace.c
@@ -183,6 +183,10 @@ static int ve_ns_install(struct nsset *nsset, struct 
ns_common *new)
 {
        struct ve_namespace *ve_ns = to_ve_ns(new);
 
+       /* Tasks that share a thread group must share a VE namespace. */
+       if (!thread_group_empty(current))
+               return -EINVAL;
+
        if (!ns_capable(ve_ns->user_ns, CAP_SYS_ADMIN) ||
            !ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN))
                return -EPERM;
-- 
2.52.0

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to