SELinux hardening for mmap_min_addr protections
eparis
So in the last article I talked about how SELinux systems provide stronger protections against mapping low memory regions for remote attacks, but are weaker against attacks from authenticated users running unconfined.  The surprise to users that their SELinux enabled system could be weaker to some class of attacks was labeled CVE-2009-2695.

After a bit of thought I've decided the best way to address this is for LSMs to abandon the mmap_min_addr tunable altogether.  That tunable lets a root user disable protections.  Why would an LSM want a root user to be able to control it's protections at all?  What it protects should be defined entirely by the kernel and the policy.  So, what I've done is to separate out the mmap_min_addr root vs. non-root check and the LSM check.  There is a new hard coded at kernel compile time amount of memory protected by the LSM.  This is unrelated to the /proc/sys/vm/mmap_min_addr file.  You can set that to 0 and the LSM will still be able to protect low memory.

So in upstream kernels (2.6.30-rc6ish and later) to map the 0 page you will need both CAP_SYS_RAWIO (root) and the SELinux memprotect/mmap_zero permission instead of only needing one or the other.  If you set /proc/sys/vm/mmap_min_addr to 0 you will still need the SELinux mamprotect/mmap_zero permission.

Hurray until the next time someone finds a way to map the 0 page and a null pointer bug in the kernel (lots of the latter as of late)

http://git.kernel.org/linus/9c0d90103c7e0eb6e638e5b649e9f6d8d9c1b4b3
http://git.kernel.org/linus/8cf948e744e0218af604c32edecde10006dc8e9e
http://git.kernel.org/linus/788084aba2ab7348257597496befcbccabdc98a3
http://git.kernel.org/linus/1d9959734a1949ea4f2427bd2d8b21ede6b2441c

mmap_min_addr on SELinux and non-SELinux systems
eparis
There has been a lot of conversation about the difference in how the mmap_min_addr proteciton is applied on SELinux vs. non-SELinux systems and how these differences made it easier to exploit a recent kernel BUG on SELinux systems.  A number of people have claimed the SELinux made the system weaker.  It did, but in other ways it was still stronger.  I'm working to get the best of both worlds, but it isn't fair to claim a universal across the board weakening.

We, the SELinux team, made a decision to not require CAP_SYS_RAWIO (non techies can think of this as root, or uid=0) for mapping the 0 page.  Instead we have an SELinux policy specific permission for this operation, mmap_zero. We made the choice to not require one to be root because WINE needs to do this operation and (sadly) there are a number of users out there who run windows applications inside WINE.

Recently a kernel exploit was posted which works by mapping the 0 page, putting crafty info on that page, tickling a bug in the kernel, and winning (It is brilliant, as usual from Brad.)   To get that 0 page mapped on a non-SELinux system he had to find a busted suid application (he found pulseaudio) and get that to map the page for him.  Since SELinux systems don't require root, he didn't need to find a busted suid application, he just had to map the 0 page and tickle the kernel bug.

Now the claim comes out that SELinux systems are less secure than non-SELinux systems.  It's true, SELinux systems are weaker against authenticated logged in local users in this case.  But it's stronger against remote attacks.  What?  Yes, I agree completely that I need to strengthen the system against attacks from a malicious local user, but we do a much better job in this case if an attacker was trying to attack remotely.

On a non-SELinux system if the attacker was able to subvert any network facing daemon they won.  They just tickled do the same thing.  Take over daemon remotely, use pulseaudio to map the page, tickle the kernel bug, win.  But what happens on an SELinux system?  It doesn't work!  Take over the network facing daemon, try the pulseaudio trick, crap, didn't get the page.  Try to map the zero page directly.  Crap it didn't work.  Now what?  You win, they lose.  SELinux is stronger than non-SELinux.

This is because SELinux confines network facing daemons and doesn't give them permissions to map the 0 page.  It's not about root or non-root.  It's not about suid or non-suid.  It's about the SELinux domain not allowing the daemon to map the 0 page.  Yes, as an unconfined user you can map the page (and I'm looking at ways to fix that) but if your system is subverted remotely, you are likely much better protected with SELinux than without.

You are viewing eparis