[grsec] module support under KERNEXEC
pageexec at freemail.hu
pageexec at freemail.hu
Mon Nov 21 20:17:40 EST 2005
the latest PaX test patch for 2.6 adds preliminary module support
under KERNEXEC, that is, you can now have non-executable pages and
keep using modules. of course as it is now, it's a complete circumvention
of the very idea of KERNEXEC (disabling runtime code generation in
the kernel itself), but we'll get to that later.
for now i'd like to ask adventurous souls to enable KERNEXEC and
module support and see what blows up. it works here (TM), but that's
a small sample, hence my request. if your life depends on your machine
then better wait (it doesn't go into grsec either for some time).
if something does blow up, then be prepared to have a serial console
attached (or maybe netconsole) and logging enabled, else your kernel
will most likely be dead (or just reboot), and taking a screenshot
by hand is not much fun ;P.
some things to be aware of:
- KERNEXEC is not compatible with EFI, HOTPLUG_PCI_COMPAQ_NVRAM
and PCI_BIOS support. the latter is easy to fix as you just have
to set the PCI access method to direct. the former two depend
on your hardware, probably most of you are not affected.
- linux in a vmware guest works fine, so you can test there (although
i tried that myself, so it's not really a new data point). linux
(with KERNEXEC enabled) as a vmware host will most likely not work,
but i didn't try that myself. if it does, then it's still bad news
as it means that it probably circumvents KERNEXEC ;-).
- due to the way non-executable pages can be implemented on i386,
the non-writable (that is, executable code and read-only data)
region reserved for modules is limited and has to be a compile
time constant. it is set to 4MB (+whatever is left in the kernel's
own code/rodata region), this could be changed in 2 or 4MB quanta
(PAE/non-PAE mode dependent). this number was based on some quick
poll in #grsecurity and should accomodate even such monsters as
the binary nvidia and ati drivers, but lacking such hardware i
couldn't try it myself. i'd be interested in learning the module
setup that you're using, especially if it represents some extreme.
providing /proc/modules should be enough.
- the above mentioned 4MB is permanently allocated physical RAM, so
it goes wasted if your modules occupy less space. initially i
decided to hardcode the module space and not allow users to tweak
it via the kernel's config, but if we can't find a good compromise
for this size, i'll have to think of something better. you can check
your kernel's module space via 'readelf -e vmlinux | grep module':
[25] .module.text PROGBITS c08a4000 7a5000 55c000 00 WA 0 0 1
i.e., in my case i have 0x55c000 bytes for module code/rodata. 4MB
of this comes from explicit allocation, the rest is from the slack
space in the kernel's own code/rodata region (which under KERNEXEC
has to be a multiple of 2/4MB, so there's usually some space left
there, in my case it's big enough to hold all my modules and i
wouldn't even need the explicit 4MB region).
- due to the limited memory allocated for non-writable module sections,
fragmentation caused by repeated module loading/unloading can become
a real problem, so don't do that, or at least try to follow the
LIFO order as much as possible. note that module unloading in general
is tricky business (it's a separate kernel config option for that
reason), so it's better to avoid it anyway.
- as i mentioned at the beginning, allowing modules amounts to runtime
code generation in kernel land, therefore it's not exactly a good idea
for (kernel) security. there should be a way to control what modules
can be loaded and/or limit the window of time they can be loaded in.
there're a few ways of accomplishing that (with various benefits and
drawbacks), if anyone has an opinion on this, feel free to share. what
crossed my mind so far:
- cryptographically signed modules (labourious to get right not to
mention to actually use it)
- 'lockdown' flag, there're a few ways of doing this:
- dummy module loaded last that would replace the sys_init_module
entry in the syscall table with sys_ni_syscall, or set some
(otherwise read-only) flag that tells sys_init_module to stand down
- some /proc entry that when written will trigger the same action
as above, access to this could be controlled via gradm too, may
even allow re-enabling of module loading
that's all for now, cheers
More information about the grsecurity
mailing list