[GIT PULL] Minor ptrace fixes for v5.2-rc5

From: Eric W. Biederman
Date: Tue Jun 11 2019 - 16:28:27 EST



Linus,

Please pull the for-linus branch from the git tree:

git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git for-linus

HEAD:f6581f5b55141a95657ef5742cf6a6bfa20a109f ptrace: restore smp_rmb() in __ptrace_may_access()

This is just two very minor fixes. Preventing ptrace from reading
unitialized kernel memory found twice by syzkaller, and restoring a
missing smp_rmb in ptrace_may_access and commening it so it is not
removed by accident again.

Apologies for being a little slow about getting this to you, I am still
figuring out how to develop with a little baby in the house.


Eric W. Biederman (1):
signal/ptrace: Don't leak unitialized kernel memory with PTRACE_PEEK_SIGINFO

Jann Horn (1):
ptrace: restore smp_rmb() in __ptrace_may_access()

kernel/cred.c | 9 +++++++++
kernel/ptrace.c | 20 ++++++++++++++++++--
2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/kernel/cred.c b/kernel/cred.c
index 45d77284aed0..07e069d00696 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -450,6 +450,15 @@ int commit_creds(struct cred *new)
if (task->mm)
set_dumpable(task->mm, suid_dumpable);
task->pdeath_signal = 0;
+ /*
+ * If a task drops privileges and becomes nondumpable,
+ * the dumpability change must become visible before
+ * the credential change; otherwise, a __ptrace_may_access()
+ * racing with this change may be able to attach to a task it
+ * shouldn't be able to attach to (as if the task had dropped
+ * privileges without becoming nondumpable).
+ * Pairs with a read barrier in __ptrace_may_access().
+ */
smp_wmb();
}

diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 6f357f4fc859..c9b4646ad375 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -323,6 +323,16 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
return -EPERM;
ok:
rcu_read_unlock();
+ /*
+ * If a task drops privileges and becomes nondumpable (through a syscall
+ * like setresuid()) while we are trying to access it, we must ensure
+ * that the dumpability is read after the credentials; otherwise,
+ * we may be able to attach to a task that we shouldn't be able to
+ * attach to (as if the task had dropped privileges without becoming
+ * nondumpable).
+ * Pairs with a write barrier in commit_creds().
+ */
+ smp_rmb();
mm = task->mm;
if (mm &&
((get_dumpable(mm) != SUID_DUMP_USER) &&
@@ -704,6 +714,10 @@ static int ptrace_peek_siginfo(struct task_struct *child,
if (arg.nr < 0)
return -EINVAL;

+ /* Ensure arg.off fits in an unsigned long */
+ if (arg.off > ULONG_MAX)
+ return 0;
+
if (arg.flags & PTRACE_PEEKSIGINFO_SHARED)
pending = &child->signal->shared_pending;
else
@@ -711,18 +725,20 @@ static int ptrace_peek_siginfo(struct task_struct *child,

for (i = 0; i < arg.nr; ) {
kernel_siginfo_t info;
- s32 off = arg.off + i;
+ unsigned long off = arg.off + i;
+ bool found = false;

spin_lock_irq(&child->sighand->siglock);
list_for_each_entry(q, &pending->list, list) {
if (!off--) {
+ found = true;
copy_siginfo(&info, &q->info);
break;
}
}
spin_unlock_irq(&child->sighand->siglock);

- if (off >= 0) /* beyond the end of the list */
+ if (!found) /* beyond the end of the list */
break;

#ifdef CONFIG_COMPAT



Eric