kmemcheck
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 | |
---|---|
Kernel | Development tools/Kernel debugging |
Posted Nov 29, 2007 13:19 UTC (Thu)
by dw (subscriber, #12017)
[Link] (6 responses)
Posted Nov 29, 2007 14:44 UTC (Thu)
by nix (subscriber, #2304)
[Link]
Posted Nov 29, 2007 15:20 UTC (Thu)
by jreiser (subscriber, #11027)
[Link]
Posted Nov 29, 2007 18:16 UTC (Thu)
by felixfix (subscriber, #242)
[Link] (3 responses)
Posted Nov 29, 2007 18:41 UTC (Thu)
by lysse (guest, #3190)
[Link] (2 responses)
Posted Nov 29, 2007 18:52 UTC (Thu)
by felixfix (subscriber, #242)
[Link]
Posted Nov 29, 2007 19:06 UTC (Thu)
by nix (subscriber, #2304)
[Link]
Posted Nov 30, 2007 2:18 UTC (Fri)
by vomlehn (guest, #45588)
[Link]
kmemcheck
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
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
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
The code to map bits would be slower; maybe he did not like the tradeoff.
kmemcheck
When there's already a page fault happening on every memory access, I have some doubts of the
significance of such additional overhead.
kmemcheck
Well, hmmmm, I guess I was thinking just enough to stick my foot in my mouth :-)
kmemcheck
Also the extra memory accesses will tend to blow the cache more if you use
more memory to track the uninit state.
kmemcheck
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.