ASA-2019-00465 – Linux kernel: Broken permission and object lifetime handling for PTRACE_TRACEME

Allele Security Alert



ASA-2019-00465, CVE-2019-13272


Broken permission and object lifetime handling for PTRACE_TRACEME


Linux foundation


Linux kernel

Affected version(s)

Linux kernel versions before 5.2

Linux kernel versions before 4.4.185
Linux kernel versions before 4.9.185
Linux kernel versions before 4.14.133
Linux kernel versions before 4.19.58
Linux kernel versions before 5.1.17

Linux kernel versions with the following commit applied:

ptrace: Capture the ptracer’s creds not PT_PTRACE_CAP

Fixed version(s)

Linux kernel version 5.2

Linux kernel version 4.4.185
Linux kernel version 4.9.185
Linux kernel version 4.14.133
Linux kernel version 4.19.58
Linux kernel version 5.1.17

Proof of concept



A flaw was found in the way PTRACE_TRACEME functionality was handled in the Linux kernel. The kernel’s implementation of ptrace can inadvertently grant elevated permissions to an attacker who can then abuse the relationship between the tracer and the process being traced. This flaw could allow a local, unprivileged user to increase their privileges on the system or cause a denial of service.

Technical details

ptrace relationships can be set up in two ways:

Either the tracer attaches to another process (PTRACE_ATTACH/PTRACE_SEIZE), or the tracee forces its parent to attach to it (PTRACE_TRACEME). When a tracee goes through a privilege-gaining execve(), the kernel checks whether the ptrace relationship is privileged. If it is not, the privilege-gaining effect of execve is suppressed. The idea here is that a privileged tracer (e.g. if root runs “strace” on some process) is allowed to trace through setuid/setcap execution, but an unprivileged tracer must not be allowed to do that, since it could otherwise inject arbitrary code into privileged processes.

In the PTRACE_ATTACH/PTRACE_SEIZE case, the tracer’s credentials are recorded at the time it calls PTRACE_ATTACH/PTRACE_SEIZE; later, when the tracee goes through execve(), it is checked whether the recorded credentials are capable over the tracee’s user namespace. But in the PTRACE_TRACEME case, the kernel also records _the tracer’s_ credentials, even though the tracer is not requesting the operation. There are two problems with that.

First, there is an object lifetime issue:

ptrace_traceme() -> ptrace_link() grabs __task_cred(new_parent) in an RCU read-side critical section, then passes the creds to __ptrace_link(), which calls get_cred() on them. If the parent concurrently switches its creds (e.g. via setresuid()), the creds’ refcount may already be zero, in which case put_cred_rcu() will already have been scheduled. The kernel usually manages to panic() before memory corruption occurs here using the following code in put_cred_rcu(). However, memory corruption would also be possible if this code races exactly the right way.

 if (atomic_read(&cred->usage) != 0)
     panic("CRED: put_cred_rcu() sees %p with usage %d\n", cred, atomic_read(&cred->usage));

The second problem is that, because the PTRACE_TRACEME case grabs the credentials of a potentially unaware tracer, it can be possible for a normal user to create and use a ptrace relationship that is marked as privileged even though no privileged code ever requested or used that ptrace relationship. This requires the presence of a setuid binary with certain behavior: It has to drop privileges and then become dumpable again (via prctl() or execve()).

– task A: fork()s a child, task B
– task B: fork()s a child, task C
– task B: execve(/some/special/suid/binary)
– task C: PTRACE_TRACEME (creates privileged ptrace relationship)
– task C: execve(/usr/bin/passwd)
– task B: drop privileges (setresuid(getuid(), getuid(), getuid()))
– task B: become dumpable again (e.g. execve(/some/other/binary))
– task A: PTRACE_ATTACH to task B
– task A: use ptrace to take control of task B
– task B: use ptrace to take control of task C

Polkit’s pkexec helper fits this pattern. On a typical desktop system, any process running under an active local session can invoke some helpers through pkexec (see configuration in /usr/share/polkit-1/actions, search for <action>s that specify <allow_active> yes </allow_active> and <annotate key=”org.freedesktop.policykit.exec.path”> …</annotate>).

While pkexec is normally used to run programs as root, pkexec actually allows its caller to specify the user to run a command as with –user, which permits using pkexec to run a command as the user who executed pkexec.


Jann Horn (Google Project Zero)


Issue 1903: Linux: broken permission and object lifetime handling for PTRACE_TRACEME

ptrace: Fix ->ptracer_cred handling for PTRACE_TRACEME

ptrace: Capture the ptracer’s creds not PT_PTRACE_CAP

Linux 5.2

Linux kernel 4.4.185

Linux kernel 4.9.185

Linux kernel 4.14.133

Linux kernel 4.19.58

Linux kernel 5.1.17

CVE-2019-13272 Linux local root exploit

CVE-2019-13272 - Red Hat Customer Portal

CVE-2019-13272 in Ubuntu

CVE-2019-13272 | SUSE




If there is any error in this alert or you wish a comprehensive analysis, let us know.

Last modified: October 10, 2019

We are not responsible for any data loss, device corruption or any other type of issue due to the use of any information mentioned in our security alerts.