[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 2/2] xmalloc: add a Kconfig option to poison free pool memory
This patch adds XMEM_POOL_POISON to the Kconfig DEBUG options. If set, free blocks (greater than MIN_BLOCK_SIZE) will be poisoned with 0xAA bytes which will then be verified when memory is subsequently allocated. This can help in spotting heap corruption, particularly use-after-free. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Cc: George Dunlap <George.Dunlap@xxxxxxxxxxxxx> Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Cc: Jan Beulich <jbeulich@xxxxxxxx> Cc: Julien Grall <julien.grall@xxxxxxx> Cc: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx> Cc: Tim Deegan <tim@xxxxxxx> Cc: Wei Liu <wl@xxxxxxx> v3: - #define the POISON_BYTE - Fix whitespace in Kconfig.debug v2: - Change Kconfig option name to XMEM_POOL_POISON - Add an implementation of memchr_inv() and use that --- xen/Kconfig.debug | 7 +++++++ xen/common/string.c | 20 ++++++++++++++++++++ xen/common/xmalloc_tlsf.c | 12 ++++++++++++ xen/include/xen/string.h | 2 ++ 4 files changed, 41 insertions(+) diff --git a/xen/Kconfig.debug b/xen/Kconfig.debug index daacf85141..e10e314e25 100644 --- a/xen/Kconfig.debug +++ b/xen/Kconfig.debug @@ -105,6 +105,13 @@ config DEBUG_TRACE either directly to the console or are printed to console in case of a system crash. +config XMEM_POOL_POISON + bool "Poison free xenpool blocks" + default DEBUG + ---help--- + Poison free blocks with 0xAA bytes and verify them when a block is + allocated in order to spot use-after-free issues. + endif # DEBUG || EXPERT endmenu diff --git a/xen/common/string.c b/xen/common/string.c index a2bbe7dc97..af3d96ad0f 100644 --- a/xen/common/string.c +++ b/xen/common/string.c @@ -423,6 +423,26 @@ void *(memchr)(const void *s, int c, size_t n) } #endif +/** + * memchr_inv - Find an unmatching character in an area of memory. + * @s: The memory area + * @c: The byte that is expected + * @n: The size of the area. + * + * returns the address of the first occurrence of a character other than @c, + * or %NULL if the whole buffer contains just @c. + */ +void *memchr_inv(const void *s, int c, size_t n) +{ + const unsigned char *p = s; + + while (n--) + if ((unsigned char)c != *p++) + return (void *)(p - 1); + + return NULL; +} + /* * Local variables: * mode: C diff --git a/xen/common/xmalloc_tlsf.c b/xen/common/xmalloc_tlsf.c index e4e476a27c..a1acfceaf6 100644 --- a/xen/common/xmalloc_tlsf.c +++ b/xen/common/xmalloc_tlsf.c @@ -215,6 +215,8 @@ static inline void EXTRACT_BLOCK_HDR(struct bhdr *b, struct xmem_pool *p, int fl b->ptr.free_ptr = (struct free_ptr) {NULL, NULL}; } +#define POISON_BYTE 0xAA + /** * Removes block(b) from free list with indexes (fl, sl) */ @@ -238,6 +240,11 @@ static inline void EXTRACT_BLOCK(struct bhdr *b, struct xmem_pool *p, int fl, } } b->ptr.free_ptr = (struct free_ptr) {NULL, NULL}; +#ifdef CONFIG_XMEM_POOL_POISON + if ( (b->size & BLOCK_SIZE_MASK) > MIN_BLOCK_SIZE ) + ASSERT(!memchr_inv(b->ptr.buffer + MIN_BLOCK_SIZE, POISON_BYTE, + (b->size & BLOCK_SIZE_MASK) - MIN_BLOCK_SIZE)); +#endif /* CONFIG_XMEM_POOL_POISON */ } /** @@ -245,6 +252,11 @@ static inline void EXTRACT_BLOCK(struct bhdr *b, struct xmem_pool *p, int fl, */ static inline void INSERT_BLOCK(struct bhdr *b, struct xmem_pool *p, int fl, int sl) { +#ifdef CONFIG_XMEM_POOL_POISON + if ( (b->size & BLOCK_SIZE_MASK) > MIN_BLOCK_SIZE ) + memset(b->ptr.buffer + MIN_BLOCK_SIZE, POISON_BYTE, + (b->size & BLOCK_SIZE_MASK) - MIN_BLOCK_SIZE); +#endif /* CONFIG_XMEM_POOL_POISON */ b->ptr.free_ptr = (struct free_ptr) {NULL, p->matrix[fl][sl]}; if ( p->matrix[fl][sl] ) p->matrix[fl][sl]->ptr.free_ptr.prev = b; diff --git a/xen/include/xen/string.h b/xen/include/xen/string.h index 711cb60a7d..4b3b57e74f 100644 --- a/xen/include/xen/string.h +++ b/xen/include/xen/string.h @@ -106,6 +106,8 @@ void *memchr(const void *, int, size_t); #define memchr(s, c, n) __builtin_memchr(s, c, n) #endif +void *memchr_inv(const void *, int, size_t); + #define is_char_array(x) __builtin_types_compatible_p(typeof(x), char[]) /* safe_xxx always NUL-terminates and returns !=0 if result is truncated. */ -- 2.20.1.2.gb21ebb671 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |