mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	During exec dumpable is cleared if the file that is being executed is
not readable by the user executing the file.  A bug in
ptrace_may_access allows reading the file if the executable happens to
enter into a subordinate user namespace (aka clone(CLONE_NEWUSER),
unshare(CLONE_NEWUSER), or setns(fd, CLONE_NEWUSER).
This problem is fixed with only necessary userspace breakage by adding
a user namespace owner to mm_struct, captured at the time of exec, so
it is clear in which user namespace CAP_SYS_PTRACE must be present in
to be able to safely give read permission to the executable.
The function ptrace_may_access is modified to verify that the ptracer
has CAP_SYS_ADMIN in task->mm->user_ns instead of task->cred->user_ns.
This ensures that if the task changes it's cred into a subordinate
user namespace it does not become ptraceable.
The function ptrace_attach is modified to only set PT_PTRACE_CAP when
CAP_SYS_PTRACE is held over task->mm->user_ns.  The intent of
PT_PTRACE_CAP is to be a flag to note that whatever permission changes
the task might go through the tracer has sufficient permissions for
it not to be an issue.  task->cred->user_ns is always the same
as or descendent of mm->user_ns.  Which guarantees that having
CAP_SYS_PTRACE over mm->user_ns is the worst case for the tasks
credentials.
To prevent regressions mm->dumpable and mm->user_ns are not considered
when a task has no mm.  As simply failing ptrace_may_attach causes
regressions in privileged applications attempting to read things
such as /proc/<pid>/stat
Cc: stable@vger.kernel.org
Acked-by: Kees Cook <keescook@chromium.org>
Tested-by: Cyrill Gorcunov <gorcunov@openvz.org>
Fixes: 8409cca705 ("userns: allow ptrace from non-init user namespaces")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
		
	
			
		
			
				
	
	
		
			27 lines
		
	
	
	
		
			680 B
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			27 lines
		
	
	
	
		
			680 B
		
	
	
	
		
			C
		
	
	
	
	
	
#include <linux/mm_types.h>
 | 
						|
#include <linux/rbtree.h>
 | 
						|
#include <linux/rwsem.h>
 | 
						|
#include <linux/spinlock.h>
 | 
						|
#include <linux/list.h>
 | 
						|
#include <linux/cpumask.h>
 | 
						|
 | 
						|
#include <linux/atomic.h>
 | 
						|
#include <linux/user_namespace.h>
 | 
						|
#include <asm/pgtable.h>
 | 
						|
#include <asm/mmu.h>
 | 
						|
 | 
						|
#ifndef INIT_MM_CONTEXT
 | 
						|
#define INIT_MM_CONTEXT(name)
 | 
						|
#endif
 | 
						|
 | 
						|
struct mm_struct init_mm = {
 | 
						|
	.mm_rb		= RB_ROOT,
 | 
						|
	.pgd		= swapper_pg_dir,
 | 
						|
	.mm_users	= ATOMIC_INIT(2),
 | 
						|
	.mm_count	= ATOMIC_INIT(1),
 | 
						|
	.mmap_sem	= __RWSEM_INITIALIZER(init_mm.mmap_sem),
 | 
						|
	.page_table_lock =  __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
 | 
						|
	.mmlist		= LIST_HEAD_INIT(init_mm.mmlist),
 | 
						|
	.user_ns	= &init_user_ns,
 | 
						|
	INIT_MM_CONTEXT(init_mm)
 | 
						|
};
 |