|
|
Subscribe / Log in / New account

kmemcheck

By Jonathan Corbet
November 27, 2007
Using uninitialized memory can lead to some seriously annoying bugs. If you are lucky, the kernel will crash with the telltale slab poisoning pattern (0x5a5a5a5a or similar) in the traceback. Other times, though, something more subtly wrong happens, forcing a long hunt for the stupid mistake. Wouldn't it be nicer if the kernel could simply detect references to uninitialized memory and scream loudly at the time?

The kmemcheck patch recently posted by Vegard Nossum offers just that functionality, though, perhaps, in a somewhat heavy-handed manner. A kernel with kmemcheck enabled is unlikely to be suitable for production use, but it should, indeed, do a good job at finding code using memory which has not yet been set to a useful value.

Kmemcheck is a relatively simple patch; the approach used is, essentially, this:

  • Every memory allocation is trapped at the page-allocator level. For each allocation, the requested order is increased by one, doubling the size of the allocation. The additional ("shadow") pages are initialized to zero and kept hidden.

  • The allocated memory is returned to the caller, but with the "present" bit cleared in the page tables. As a result, every attempt to access that memory will cause a page fault.

  • Once the fault happens, kmemcheck (through some ugly, architecture-specific code) determines the exact address and size of the attempted access. If the access is a write, the corresponding bytes in the shadow page are set to 0xff and the operation is allowed to complete.

  • For read accesses, the corresponding shadow page bytes are tested; if any of them are zero, the code concludes that the read is trying to access uninitialized data. A stack traceback is printed to enable the developer to find the location where this access is happening.

As should be evident, running with kmemcheck enabled will have certain performance impacts. Taking a page fault on every access to slab memory just cannot be fast. Doubling the size of every allocation will impose costs of its own, including the cache effects of simply working with twice as much memory. But that is a cost which can be paid when the kernel is being run in a debugging mode.

Vegard has posted some sample output which shows how the system responds to reads from uninitialized memory. If this output is to be believed, access to unset memory is not an especially uncommon occurrence in current kernels. If some of references flagged here, once tracked down, turn out to be real bugs, the kmemcheck patch will have earned its keep, even if it never finds its way into the mainline.

Index entries for this article
KernelDevelopment tools/Kernel debugging


to post comments

kmemcheck

Posted Nov 29, 2007 13:19 UTC (Thu) by dw (subscriber, #12017) [Link] (6 responses)

Doubling the size of every allocation seems pretty wasteful, couldn't a bitmap be used
instead, with byte or even word-level granularity?

new_size = (size + (size/8))

kmemcheck

Posted Nov 29, 2007 14:44 UTC (Thu) by nix (subscriber, #2304) [Link]

A bitmap definitely can be used instead. (This is how valgrind's memcheck 
tool implements uninitialized checks, although using JIT simulation rather 
than page faulting to detect accesses.)

kmemcheck

Posted Nov 29, 2007 15:20 UTC (Thu) by jreiser (subscriber, #11027) [Link]

On a 32-bit machine it is tempting to use 8 bits (an entire byte) to track access to 32 bits
(one word) of memory.  This gives speed while still saving some space.

kmemcheck

Posted Nov 29, 2007 18:16 UTC (Thu) by felixfix (subscriber, #242) [Link] (3 responses)

The code to map bits would be slower; maybe he did not like the tradeoff.

kmemcheck

Posted Nov 29, 2007 18:41 UTC (Thu) by lysse (guest, #3190) [Link] (2 responses)

When there's already a page fault happening on every memory access, I have some doubts of the
significance of such additional overhead.

kmemcheck

Posted Nov 29, 2007 18:52 UTC (Thu) by felixfix (subscriber, #242) [Link]

Well, hmmmm, I guess I was thinking just enough to stick my foot in my mouth :-)

kmemcheck

Posted Nov 29, 2007 19:06 UTC (Thu) by nix (subscriber, #2304) [Link]

Also the extra memory accesses will tend to blow the cache more if you use 
more memory to track the uninit state.

kmemcheck

Posted Nov 30, 2007 2:18 UTC (Fri) by vomlehn (guest, #45588) [Link]

I would say that this idea pretty much rocks. Yes, it will slow the kernel way down and that
will make it unusable for production use, but the ability to do these checks on debugging
kernels is an excellent idea and the implementation makes a lot of sense for a first cut.


Copyright © 2007, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds