On Tue, Nov 13, 2018 at 10:31 AM Igor Stoppa <igor.stoppa@xxxxxxxxxx> wrote: > > On 13/11/2018 19:47, Andy Lutomirski wrote: > > > For general rare-writish stuff, I don't think we want IRQs running > > with them mapped anywhere for write. For AVC and IMA, I'm less sure. > > Why would these be less sensitive? I'm not really saying they're less sensitive so much as that the considerations are different. I think the original rare-write code is based on ideas from grsecurity, and it was intended to protect static data like structs full of function pointers. Those targets have some different properties: - Static targets are at addresses that are much more guessable, so they're easier targets for most attacks. (Not spraying attacks like the ones you're interested in, though.) - Static targets are higher value. No offense to IMA or AVC, but outright execution of shellcode, hijacking of control flow, or compete disablement of core security features is higher impact than bypassing SELinux or IMA. Why would you bother corrupting the AVC if you could instead just set enforcing=0? (I suppose that corrupting the AVC is less likely to be noticed by monitoring tools.) - Static targets are small. This means that the interrupt latency would be negligible, especially in comparison to the latency of replacing the entire SELinux policy object. Anyway, I'm not all that familiar with SELinux under the hood, but I'm wondering if a different approach to thinks like the policy database might be appropriate. When the policy is changed, rather than allocating rare-write memory and writing to it, what if we instead allocated normal memory, wrote to it, write-protected it, and then used the rare-write infrastructure to do a much smaller write to replace the pointer? Admittedly, this creates a window where another core could corrupt the data as it's being written. That may not matter so much if an attacker can't force a policy update. Alternatively, the update code could re-verify the policy after write-protecting it, or there could be a fancy API to allocate some temporarily-writable memory (by creating a whole new mm_struct, mapping the memory writable just in that mm_struct, and activating it) so that only the actual policy loader could touch the memory. But I'm mostly speculating here, since I'm not familiar with the code in question. Anyway, I tend to think that the right way to approach mainlining all this is to first get the basic rare write support for static data into place and then to build on that. I think it's great that you're pushing this effort, but doing this for SELinux and IMA is a bigger project than doing it for static data, and it might make sense to do it in bite-sized pieces. Does any of this make sense?