The patch titled
Subject: unshare: unsharing a thread does not require unsharing a vm
has been removed from the -mm tree. Its filename was
unshare-unsharing-a-thread-does-not-require-unsharing-a-vm.patch
This patch was dropped because it was merged into mainline or a subsystem tree
------------------------------------------------------
From: "Eric W. Biederman" <[email protected]>
Subject: unshare: unsharing a thread does not require unsharing a vm
Checking mm_users > 1 does not mean a process is multithreaded. For
example, reading /proc/PID/maps temporarily increments mm_users, allowing
other processes to (accidentally) interfere with unshare() calls.
This fixes observed failures of unshare(CLONE_NEWUSER) incorrectly
returning EINVAL if another processes happened to be simultaneously
reading the maps file.
The logic in the initial commit of unshare made creating a new thread
group for a process contingent upon creating a new memory address space
for that process. That is wrong. Two separate processes in different
thread groups can share a memory address space and clone allows creation
of such proceses.
This is significant because it was observed that mm_users > 1 does not
mean that a process is multi-threaded, as reading /proc/PID/maps
temporarily increments mm_users, which allows other processes to
(accidentally) interfere with unshare() calls.
Correct the check in check_unshare_flags() to test for
!thread_group_empty() for CLONE_THREAD, CLONE_SIGHAND, and CLONE_VM. For
sighand->count > 1 for CLONE_SIGHAND and CLONE_VM. For
!current_is_single_threaded instead of mm_users > 1 for CLONE_VM.
By using the correct checks in unshare this removes the possibility of an
accidental denial of service attack.
Additionally using the correct checks in unshare ensures that only an
explicit unshare(CLONE_VM) can possibly trigger the slow path of
current_is_single_threaded(). As an explict unshare(CLONE_VM) is
pointless it is not expected there are many applications that make that
call.
Fixes: b2e0d98705e60e45 ("userns: Implement unshare of the user namespace")
Signed-off-by: "Eric W. Biederman" <[email protected]>
Reported-by: Ricky Zhou <[email protected]>
Reported-by: Kees Cook <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Kirill A. Shutemov <[email protected]>
Cc: Vladimir Davydov <[email protected]>
Cc: Julien Tinnes <[email protected]>
Cc: <[email protected]> [3.9+]
Signed-off-by: Andrew Morton <[email protected]>
---
kernel/fork.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff -puN
kernel/fork.c~unshare-unsharing-a-thread-does-not-require-unsharing-a-vm
kernel/fork.c
--- a/kernel/fork.c~unshare-unsharing-a-thread-does-not-require-unsharing-a-vm
+++ a/kernel/fork.c
@@ -1873,13 +1873,21 @@ static int check_unshare_flags(unsigned
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;
}
@@ -1948,16 +1956,16 @@ SYSCALL_DEFINE1(unshare, unsigned long,
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.
*/
if (unshare_flags & CLONE_NEWNS)
_
Patches currently in -mm which might be from [email protected] are
proc-change-proc_subdir_lock-to-a-rwlock.patch
kexec-split-kexec_file-syscall-code-to-kexec_filec.patch
kexec-split-kexec_load-syscall-from-kexec-core-code.patch
align-crash_notes-allocation-to-make-it-be-inside-one-physical-page.patch
kdump-vmcoreinfo-report-actual-value-of-phys_base.patch
sysctl-fix-int-unsigned-long-assignments-in-int_min-case.patch
linux-next.patch
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html