aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/mm_types.h1
-rw-r--r--kernel/fork.c9
-rw-r--r--kernel/ptrace.c26
-rw-r--r--mm/init-mm.c2
4 files changed, 20 insertions, 18 deletions
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 4a8acedf4b7d..08d947fc4c59 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -473,6 +473,7 @@ struct mm_struct {
473 */ 473 */
474 struct task_struct __rcu *owner; 474 struct task_struct __rcu *owner;
475#endif 475#endif
476 struct user_namespace *user_ns;
476 477
477 /* store ref to file /proc/<pid>/exe symlink points to */ 478 /* store ref to file /proc/<pid>/exe symlink points to */
478 struct file __rcu *exe_file; 479 struct file __rcu *exe_file;
diff --git a/kernel/fork.c b/kernel/fork.c
index 997ac1d584f7..ba8a01564985 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -745,7 +745,8 @@ static void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
745#endif 745#endif
746} 746}
747 747
748static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p) 748static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
749 struct user_namespace *user_ns)
749{ 750{
750 mm->mmap = NULL; 751 mm->mmap = NULL;
751 mm->mm_rb = RB_ROOT; 752 mm->mm_rb = RB_ROOT;
@@ -785,6 +786,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
785 if (init_new_context(p, mm)) 786 if (init_new_context(p, mm))
786 goto fail_nocontext; 787 goto fail_nocontext;
787 788
789 mm->user_ns = get_user_ns(user_ns);
788 return mm; 790 return mm;
789 791
790fail_nocontext: 792fail_nocontext:
@@ -830,7 +832,7 @@ struct mm_struct *mm_alloc(void)
830 return NULL; 832 return NULL;
831 833
832 memset(mm, 0, sizeof(*mm)); 834 memset(mm, 0, sizeof(*mm));
833 return mm_init(mm, current); 835 return mm_init(mm, current, current_user_ns());
834} 836}
835 837
836/* 838/*
@@ -845,6 +847,7 @@ void __mmdrop(struct mm_struct *mm)
845 destroy_context(mm); 847 destroy_context(mm);
846 mmu_notifier_mm_destroy(mm); 848 mmu_notifier_mm_destroy(mm);
847 check_mm(mm); 849 check_mm(mm);
850 put_user_ns(mm->user_ns);
848 free_mm(mm); 851 free_mm(mm);
849} 852}
850EXPORT_SYMBOL_GPL(__mmdrop); 853EXPORT_SYMBOL_GPL(__mmdrop);
@@ -1126,7 +1129,7 @@ static struct mm_struct *dup_mm(struct task_struct *tsk)
1126 1129
1127 memcpy(mm, oldmm, sizeof(*mm)); 1130 memcpy(mm, oldmm, sizeof(*mm));
1128 1131
1129 if (!mm_init(mm, tsk)) 1132 if (!mm_init(mm, tsk, mm->user_ns))
1130 goto fail_nomem; 1133 goto fail_nomem;
1131 1134
1132 err = dup_mmap(mm, oldmm); 1135 err = dup_mmap(mm, oldmm);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index e6474f7272ec..282821557183 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -220,7 +220,7 @@ static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
220static int __ptrace_may_access(struct task_struct *task, unsigned int mode) 220static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
221{ 221{
222 const struct cred *cred = current_cred(), *tcred; 222 const struct cred *cred = current_cred(), *tcred;
223 int dumpable = 0; 223 struct mm_struct *mm;
224 kuid_t caller_uid; 224 kuid_t caller_uid;
225 kgid_t caller_gid; 225 kgid_t caller_gid;
226 226
@@ -271,16 +271,11 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
271 return -EPERM; 271 return -EPERM;
272ok: 272ok:
273 rcu_read_unlock(); 273 rcu_read_unlock();
274 smp_rmb(); 274 mm = task->mm;
275 if (task->mm) 275 if (mm &&
276 dumpable = get_dumpable(task->mm); 276 ((get_dumpable(mm) != SUID_DUMP_USER) &&
277 rcu_read_lock(); 277 !ptrace_has_cap(mm->user_ns, mode)))
278 if (dumpable != SUID_DUMP_USER && 278 return -EPERM;
279 !ptrace_has_cap(__task_cred(task)->user_ns, mode)) {
280 rcu_read_unlock();
281 return -EPERM;
282 }
283 rcu_read_unlock();
284 279
285 return security_ptrace_access_check(task, mode); 280 return security_ptrace_access_check(task, mode);
286} 281}
@@ -331,6 +326,11 @@ static int ptrace_attach(struct task_struct *task, long request,
331 326
332 task_lock(task); 327 task_lock(task);
333 retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH_REALCREDS); 328 retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH_REALCREDS);
329 if (!retval) {
330 struct mm_struct *mm = task->mm;
331 if (mm && ns_capable(mm->user_ns, CAP_SYS_PTRACE))
332 flags |= PT_PTRACE_CAP;
333 }
334 task_unlock(task); 334 task_unlock(task);
335 if (retval) 335 if (retval)
336 goto unlock_creds; 336 goto unlock_creds;
@@ -344,10 +344,6 @@ static int ptrace_attach(struct task_struct *task, long request,
344 344
345 if (seize) 345 if (seize)
346 flags |= PT_SEIZED; 346 flags |= PT_SEIZED;
347 rcu_read_lock();
348 if (ns_capable(__task_cred(task)->user_ns, CAP_SYS_PTRACE))
349 flags |= PT_PTRACE_CAP;
350 rcu_read_unlock();
351 task->ptrace = flags; 347 task->ptrace = flags;
352 348
353 __ptrace_link(task, current); 349 __ptrace_link(task, current);
diff --git a/mm/init-mm.c b/mm/init-mm.c
index a56a851908d2..975e49f00f34 100644
--- a/mm/init-mm.c
+++ b/mm/init-mm.c
@@ -6,6 +6,7 @@
6#include <linux/cpumask.h> 6#include <linux/cpumask.h>
7 7
8#include <linux/atomic.h> 8#include <linux/atomic.h>
9#include <linux/user_namespace.h>
9#include <asm/pgtable.h> 10#include <asm/pgtable.h>
10#include <asm/mmu.h> 11#include <asm/mmu.h>
11 12
@@ -21,5 +22,6 @@ struct mm_struct init_mm = {
21 .mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem), 22 .mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem),
22 .page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock), 23 .page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
23 .mmlist = LIST_HEAD_INIT(init_mm.mmlist), 24 .mmlist = LIST_HEAD_INIT(init_mm.mmlist),
25 .user_ns = &init_user_ns,
24 INIT_MM_CONTEXT(init_mm) 26 INIT_MM_CONTEXT(init_mm)
25}; 27};