Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Tue, 08 Jul 2014 15:22:36 -0700
From: Andy Lutomirski <luto@...capital.net>
To: oss-security@...ts.openwall.com
Subject: Re: CVE-2014-4699: Linux ptrace bug

On 07/04/2014 02:05 PM, Andy Lutomirski wrote:
> Hi everyone-
> 
> Upstream commit b9cd18de4db3c9ffa7e17b0dc0ca99ed5aa4d43a fixes a
> ptrace bug.  The exact scope of the bug is somewhat unclear right now.
> I see no reason why the bug should not be present as far back as Linux
> 2.6.17, but it seems to be difficult to reproduce on old kernels.
> 
> There is some ongoing discussion on linux-distros about the impact and
> applicability of this bug.
> 
> More details and a PoC to follow some time next week.
> 
> I'm being intentionally vague here: this bug has existed for a long
> time, but exploiting it at all is tricky enough (and possibly
> kernel-version dependent enough) that it's gone unnoticed.  I would
> currently prefer to give the distros and users a bit of a headstart
> before publicly disclosing the complete details of how to test/exploit
> the bug.  It is likely to have a high enough impact, at least on new
> enough kernels, that it should be patched ASAP.

Time for full details.

Intel CPUs implement sysret oddly: sysret will #GP *from kernel mode* if
RIP/RCX is non-canonical.  This is only a problem because sysret does
not affect RSP, so the kernel needs to load the user's RSP value prior
to running sysret.  That means that an exception frame will be written
to the address at RSP, which is necessarily user-controlled.  If RSP is
a writable user address and the CPU does not have SMAP, then the
kernel's general_protection handler will actually execute from a
user-controlled stack, and user code can attempt to race with the kernel
to take over the system.

Even on SMAP systems (which no one has yet anyway), it's possible to set
RSP to point to an important kernel data structure and overwrite it in a
partially controlled manner.  Overwriting the IDT like this was
traditional, but that's difficult now on Linux, since the public IDT
address is read-only.

If RSP points somewhere non-writable, then sysret will double-fault and
OOPS cleanly on an IST stack.

The upshot is that allowing user code to set the saved RIP address to a
non-canonical value in a non-IRET-using system call is bad.  On recent
unpatched kernels, this can be done using fork(2).  On other kernels,
there may or may not be other attack vectors.

The upstream fix fixes a related bug in that the sysret path failed to
restore some registers on the same fork(2) path.  This could potentially
cause gdb to malfunction.

I've attached a proof-of-concept exploit.  It double-faults reliably on
unpatched Intel CPUs.  The precise cause of the double-fault is left as
an exercise to the reader :)

--Andy


View attachment "ptrace_fork.c" of type "text/plain" (1690 bytes)

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.