KSPP / linux

Linux kernel source tree (Kernel Self Protection Project)
https://kernsec.org/wiki/index.php/Kernel_Self_Protection_Project
Other
83 stars 5 forks source link

random slab canaries with leading zero #281

Open thestinger opened 1 year ago

thestinger commented 1 year ago

SLUB_DEBUG is not designed as a security feature and shouldn't actually be enabled in production on hardened systems. The redzone implementation fills spare padding space with a standard value and checks for it, then reports corruption when detected at free and attempts to recover. A security feature needs to guarantee a certain size of canary is present rather than only being opportunistic, should use a random value to prevent concealing a sequential overflow by matching the padding value and should use a leading zero to reliably contain string overflows like the Linux kernel stack canaries now do. Bug detection vs. security makes the implementation quite different very much like init on free / init on alloc vs. page/slab poisoning. It was accepted for that, and I think it should be accepted upstream for this too if someone is willing to deal with the hassle of trying to upstream it.

In linux-hardened, there's an implementation of random canaries that are 4 bytes on 32-bit and 8 bytes on 64-bit with a leading zero on 64-bit to reliably contain string function overflows both to prevent overflowing elsewhere and to protect leaking the canaries. The random canary values are unique to each slab cache. There's a separate value for active and inactive allocations to provide a quick way to check whether an allocation is active.

https://github.com/anthraxx/linux-hardened/commit/6649c22339d5b951dd95bd88ccc6e06f9d300d75.patch

The canary value is checked both at free time and inside the __check_heap_object function used by HARDENED_USERCOPY which helps with detecting corruption earlier along with providing use-after-free detection there.

It would be nice if this feature was finally upstream. I'm not personally interested in spending my time dealing with linux kernel mailing lists and maintainers anymore, but I do want this to be upstream.

Performance overhead is incredibly low, especially when using it alongside zero-at-free. The canary is implemented by increasing the request size, meaning that when possible it avoids additional memory usage. For example, a 24 byte allocation is rounded to 32 bytes anyway so there's no additional memory usage. Many allocations do end up bumped into the next size class, so it does increase memory usage, but not as much as you might expect.