CVE-2014-9322: local privilege escalation, all kernel versions
Any kernel that is not patched against CVE-2014-9090 is vulnerable to
privilege escalation due to incorrect handling of a #SS fault caused
by an IRET instruction. In particular, if IRET executes on a
writeable kernel stack (this was always the case before 3.16 and is
sometimes the case on 3.16 and newer), the assembly function
general_protection will execute with the user's gsbase and the
kernel's gsbase swapped.
This is likely to be easy to exploit for privilege escalation, except
on systems with SMAP or UDEREF. On those systems, assuming that the
mitigation works correctly, the impact of this bug may be limited to
massive memory corruption and an eventual crash or reboot.
As with CVE-2014-9090, this is fixed by:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/x86/kernel/entry_64.S?id=6f442be2fb22be02cafa606f1769fa1e6f894441
The related fix to remove bad_iret is also an effective mitigation to
prevent a bug like this from being reintroduced:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/x86/kernel/entry_64.S?id=b645af2d5905c4e32399005b867987919cbfc3ae
Partial credit for this bug goes to Borislav Petkov, who asked pointed
questions about CVE-2014-9090, causing me to realize that there were
two separate bugs in #SS handling. The first bug (CVE-2014-9090)
caused a fatal double fault, masking the second bug that caused the
gsbase issue.
----------
The next two bugs are related to espfix. The IRET instruction has IMO
a blatant design flaw: IRET to a 16-bit user stack segment will leak
bits 31:16 of the kernel stack pointer. This flaw exists on 32-bit
and 64-bit systems. 32-bit Linux kernels have mitigated this leak for
a long time, and 64-bit Linux kernels have mitigated this leak since
3.16. The mitigation is called espfix.
CVE-2014-8133: espfix bypass using set_thread_area
On all kernels, a valid 16-bit stack segment can be created using
set_thread_area. Arranging to return to such a stack segment will
bypass espfix, leaking bits 31:16 of the kernel stack pointer. Fixed
by:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/x86?id=41bdc78544b8a93a9c6814b8bbbfef966272abbe
CVE-2014-8134: espfix was broken on 32-bit KVM paravirt guests
espfix was completely broken on 32-bit Linux KVM guests with
CONFIG_KVM_GUEST=y. Fixed by:
https://git.kernel.org/cgit/virt/kvm/kvm.git/commit/?h=linux-next&id=29fa6825463c97e5157284db80107d1bfac5d77b
This commit hasn't made it to Linus' tree yet.
----------
CVE-2014-9090 (previously announced), CVE-2014-9322, CVE-2014-8133,
and CVE-2014-8134 can be tested by sigreturn_32, available here:
https://gitorious.org/linux-test-utils/linux-clock-tests/source/10b9a7d317f6d8ae5f32bcb4bbbb186acdd6b89a
Save your data before running this on a production system. If you a
vulnerable to CVE-2014-9090 or CVE-2014-9322, the test will crash your
system. The espfix issues will cause warnings and failures that
mention register mismatches.
--
Andy Lutomirski
AMA Capital Management, LLC