[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