[grsec] KERNEXEC^Vmware?

pageexec at freemail.hu pageexec at freemail.hu
Wed Jan 11 20:15:00 EST 2006


On 11 Jan 2006 at 12:56, Angelo Dell'Aera wrote:
> This is the detailed analysis I did about the problem I found while
> executing Vmware with KERNEXEC enabled we were talking about in the last
> days. If needed I can provide even my .config and System.map files. So
> let's start.

nice analysis, i'll add my own where you missed some stuff.

> [  161.078921] PAX: vmware-vmx:19216, uid/euid: 1000/1000, attempted to
> modify kernel code at virtual address c05bd085 [  161.078926]  printing
> eip: [  161.078928] 0032da06

what this says is that some code executing in the kernel (ring-0 on
i386) attempted to write to read-only memory (that is, something
that's actually made read-only under KERNEXEC, under a vanilla
kernel everything is writable in kernel space). this information
is reported by show_stack, that's why it shows up in the stack trace,
but it's already after the fact, so it not the culprit, it's just
reporting the trouble.

the real offender was the insn at what the reported EIP says: 0x0032da06.
this is a logical address, to find the corresponding linear address
you have to add __KERNEL_TEXT_OFFSET to it (under KERNEXEC this is
0xc0400000, not 0 as in vanilla), so it was 0xc072da06. we also see
that the insn at this address tried to modify memory at 0xc05bd085.
this is again a logical address but since it's in the data segment
which is 0 based, it's also the corresponding linear address.

now armed with this information we want to know what and where this
insn is and what it tried to modify.

the oops nicely gave us the code dump around the offending EIP, the
actual insn begins with the byte between <> which disassembles to:

88D0                         mov         al,dl
24F0                         and         al,0F0
0C09                         or          al,009
<88>4105                       mov         [ecx][05],al

i disassembled some insns before as well to make the explanation
easier below. this says that we indeed have an insn that writes to
memory (this is intel syntax, not at&t), we're writing a byte at
the address held in ecx + 5, which according to the oops happens
to contain 0xc05bd080 which gives 0xc05bd080+5 = 0xc05bd085, the
reported fault address. so we can be quite sure we got the right
guy.

now we want to know what it tried to modify. as you correctly found
out, it's c05bd000 R cpu_gdt_table, that is, the GDT, in particular
it's the TSS descriptor in it as arch/i386/kernel/head.S says that
at offset 0x80 there's a TSS descriptor. from the few insns before
we can also see that the code is trying to clear the busy bit in it
(see for example http://sandpile.org./ia32/desc.htm for the TSS
descriptor format).

finally, we want to know where this insn really is. you said that
the reported EIP (logical address) couldn't be found in System.map
(and in particular, it's outside the _stext/_etext region if you
take a look), so it must have been a module. now that we also know
the corresponding linear address, we can easily find out that the
culprit was: vmmon 0 0 42895 51244 2 - Live 0xc0727000 0xf0693000
as its code was mapped at 0xc0727000-0xc073178f (the upper boundary
comes from 0xc0727000 + 42895). so we now know that it's indeed
vmware that writes to the GDT.

as for fixing it, you (or vmware, if they cared) would have to add
pax_open_kernel/pax_close_kernel calls around all the code that
attempts to modify read-only memory. short of source code, one can
resort to binary patching, but that'll be a bit of black magic ;-).



More information about the grsecurity mailing list