diff options
-rw-r--r-- | include/linux/mm_types.h | 1 | ||||
-rw-r--r-- | kernel/fork.c | 9 | ||||
-rw-r--r-- | kernel/ptrace.c | 26 | ||||
-rw-r--r-- | mm/init-mm.c | 2 |
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 | ||
748 | static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p) | 748 | static 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 | ||
790 | fail_nocontext: | 792 | fail_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 | } |
850 | EXPORT_SYMBOL_GPL(__mmdrop); | 853 | EXPORT_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) | |||
220 | static int __ptrace_may_access(struct task_struct *task, unsigned int mode) | 220 | static 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; |
272 | ok: | 272 | ok: |
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 | }; |