|
@@ -1280,10 +1280,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
|
|
|
|
|
/*
|
|
|
* If the new process will be in a different pid or user namespace
|
|
|
- * do not allow it to share a thread group or signal handlers or
|
|
|
- * parent with the forking task.
|
|
|
+ * do not allow it to share a thread group with the forking task.
|
|
|
*/
|
|
|
- if (clone_flags & CLONE_SIGHAND) {
|
|
|
+ if (clone_flags & CLONE_THREAD) {
|
|
|
if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) ||
|
|
|
(task_active_pid_ns(current) !=
|
|
|
current->nsproxy->pid_ns_for_children))
|
|
@@ -1872,13 +1871,21 @@ static int check_unshare_flags(unsigned long unshare_flags)
|
|
|
CLONE_NEWUSER|CLONE_NEWPID))
|
|
|
return -EINVAL;
|
|
|
/*
|
|
|
- * Not implemented, but pretend it works if there is nothing to
|
|
|
- * unshare. Note that unsharing CLONE_THREAD or CLONE_SIGHAND
|
|
|
- * needs to unshare vm.
|
|
|
+ * Not implemented, but pretend it works if there is nothing
|
|
|
+ * to unshare. Note that unsharing the address space or the
|
|
|
+ * signal handlers also need to unshare the signal queues (aka
|
|
|
+ * CLONE_THREAD).
|
|
|
*/
|
|
|
if (unshare_flags & (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM)) {
|
|
|
- /* FIXME: get_task_mm() increments ->mm_users */
|
|
|
- if (atomic_read(¤t->mm->mm_users) > 1)
|
|
|
+ if (!thread_group_empty(current))
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ if (unshare_flags & (CLONE_SIGHAND | CLONE_VM)) {
|
|
|
+ if (atomic_read(¤t->sighand->count) > 1)
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ if (unshare_flags & CLONE_VM) {
|
|
|
+ if (!current_is_single_threaded())
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
@@ -1942,20 +1949,21 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
|
|
|
int err;
|
|
|
|
|
|
/*
|
|
|
- * If unsharing a user namespace must also unshare the thread.
|
|
|
+ * If unsharing a user namespace must also unshare the thread group
|
|
|
+ * and unshare the filesystem root and working directories.
|
|
|
*/
|
|
|
if (unshare_flags & CLONE_NEWUSER)
|
|
|
unshare_flags |= CLONE_THREAD | CLONE_FS;
|
|
|
- /*
|
|
|
- * If unsharing a thread from a thread group, must also unshare vm.
|
|
|
- */
|
|
|
- if (unshare_flags & CLONE_THREAD)
|
|
|
- unshare_flags |= CLONE_VM;
|
|
|
/*
|
|
|
* If unsharing vm, must also unshare signal handlers.
|
|
|
*/
|
|
|
if (unshare_flags & CLONE_VM)
|
|
|
unshare_flags |= CLONE_SIGHAND;
|
|
|
+ /*
|
|
|
+ * If unsharing a signal handlers, must also unshare the signal queues.
|
|
|
+ */
|
|
|
+ if (unshare_flags & CLONE_SIGHAND)
|
|
|
+ unshare_flags |= CLONE_THREAD;
|
|
|
/*
|
|
|
* If unsharing namespace, must also unshare filesystem information.
|
|
|
*/
|