Source-Changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

CVS commit: src/sys

Module Name:    src
Committed By:   maxv
Date:           Sat Sep  2 12:57:03 UTC 2017

Modified Files:
        src/sys/arch/amd64/amd64: gdt.c
        src/sys/arch/i386/i386: gdt.c
        src/sys/compat/linux32/arch/amd64: linux32_machdep.c

Log Message:
Fix a subtle ring0 escalation vulnerability in amd64, and implement a
mitigation against similar bugs.

The operations on segment registers can generate a page fault if there is
an issue when touching the in-memory gdt. Theoretically, it is never
supposed to happen, since the gdt is mapped correctly. However, in the
kernel we allow the gdt to be resized, and to do that, we allocate the
maximum amount of va needed by it, but only kenter a few pages until we
need more. Moreover, to avoid reloading the gdt each time we grow it, the
'size' field of gdtr is set to the maximum value. All of this means that
if a mov or iretq is done with a segment register whose index hits a page
that has not been kentered, a page fault is sent.

Such a page fault, if received in kernel mode, does not trigger a swapgs
on amd64; in other words, the kernel would be re-entered with the userland

And there just happens to be a place in compat_linux32 where the index of
%cs is controlled by userland, making it easy to trigger the page fault
and get kernel privileges.

The mitigation simply consists in abandoning the gdt_grow mechanism and
allocating/kentering the maximum size right away, in such a way that no
page fault can be triggered because of segment registers.

To generate a diff of this commit:
cvs rdiff -u -r1.40 -r1.41 src/sys/arch/amd64/amd64/gdt.c
cvs rdiff -u -r1.65 -r1.66 src/sys/arch/i386/i386/gdt.c
cvs rdiff -u -r1.38 -r1.39 \

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Home | Main Index | Thread Index | Old Index