diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/fork.c | 9 | ||||
| -rw-r--r-- | kernel/ptrace.c | 26 |
2 files changed, 17 insertions, 18 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index f6422f07d133..0a2f907b1302 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -527,7 +527,8 @@ static void mm_init_aio(struct mm_struct *mm) #endif } -static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p) +static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, + struct user_namespace *user_ns) { atomic_set(&mm->mm_users, 1); atomic_set(&mm->mm_count, 1); @@ -551,6 +552,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p) if (likely(!mm_alloc_pgd(mm))) { mmu_notifier_mm_init(mm); + mm->user_ns = get_user_ns(user_ns); return mm; } @@ -588,7 +590,7 @@ struct mm_struct *mm_alloc(void) memset(mm, 0, sizeof(*mm)); mm_init_cpumask(mm); - return mm_init(mm, current); + return mm_init(mm, current, current_user_ns()); } /* @@ -603,6 +605,7 @@ void __mmdrop(struct mm_struct *mm) destroy_context(mm); mmu_notifier_mm_destroy(mm); check_mm(mm); + put_user_ns(mm->user_ns); free_mm(mm); } EXPORT_SYMBOL_GPL(__mmdrop); @@ -822,7 +825,7 @@ static struct mm_struct *dup_mm(struct task_struct *tsk) #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS mm->pmd_huge_pte = NULL; #endif - if (!mm_init(mm, tsk)) + if (!mm_init(mm, tsk, mm->user_ns)) goto fail_nomem; if (init_new_context(tsk, mm)) diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 19c73f4faf83..6cd57678bbf4 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -230,7 +230,7 @@ static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode) static int __ptrace_may_access(struct task_struct *task, unsigned int mode) { const struct cred *cred = current_cred(), *tcred; - int dumpable = 0; + struct mm_struct *mm; kuid_t caller_uid; kgid_t caller_gid; @@ -281,16 +281,11 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode) return -EPERM; ok: rcu_read_unlock(); - smp_rmb(); - if (task->mm) - dumpable = get_dumpable(task->mm); - rcu_read_lock(); - if (dumpable != SUID_DUMP_USER && - !ptrace_has_cap(__task_cred(task)->user_ns, mode)) { - rcu_read_unlock(); - return -EPERM; - } - rcu_read_unlock(); + mm = task->mm; + if (mm && + ((get_dumpable(mm) != SUID_DUMP_USER) && + !ptrace_has_cap(mm->user_ns, mode))) + return -EPERM; return security_ptrace_access_check(task, mode); } @@ -341,6 +336,11 @@ static int ptrace_attach(struct task_struct *task, long request, task_lock(task); retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH_REALCREDS); + if (!retval) { + struct mm_struct *mm = task->mm; + if (mm && ns_capable(mm->user_ns, CAP_SYS_PTRACE)) + flags |= PT_PTRACE_CAP; + } task_unlock(task); if (retval) goto unlock_creds; @@ -354,10 +354,6 @@ static int ptrace_attach(struct task_struct *task, long request, if (seize) flags |= PT_SEIZED; - rcu_read_lock(); - if (ns_capable(__task_cred(task)->user_ns, CAP_SYS_PTRACE)) - flags |= PT_PTRACE_CAP; - rcu_read_unlock(); task->ptrace = flags; __ptrace_link(task, current); |
