[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] xmalloc: add support for checking the pool integrity
On Thursday 04 December 2014 19:01:40 Mihai DonÈu wrote: > Implemented xmem_pool_check(), xmem_pool_check_locked() and > xmem_pool_check_unlocked() to verity the integrity of the TLSF matrix. > > Signed-off-by: Mihai DonÈu <mdontu@xxxxxxxxxxxxxxx> > --- > xen/common/xmalloc_tlsf.c | 119 > +++++++++++++++++++++++++++++++++++++++++++++- > xen/include/xen/xmalloc.h | 7 +++ > 2 files changed, 124 insertions(+), 2 deletions(-) > > diff --git a/xen/common/xmalloc_tlsf.c b/xen/common/xmalloc_tlsf.c > index a5769c9..009ba60 100644 > --- a/xen/common/xmalloc_tlsf.c > +++ b/xen/common/xmalloc_tlsf.c > @@ -120,9 +120,120 @@ struct xmem_pool { > char name[MAX_POOL_NAME_LEN]; > }; > > +static struct xmem_pool *xenpool; > + > +static inline void MAPPING_INSERT(unsigned long r, int *fl, int *sl); > + > /* > * Helping functions > */ > +#ifndef NDEBUG > +static int xmem_pool_check_size(const struct bhdr *b, int fl, int sl) > +{ > + while ( b ) > + { > + int __fl; > + int __sl; > + > + MAPPING_INSERT(b->size, &__fl, &__sl); > + if ( __fl != fl || __sl != sl ) > + { > + printk(XENLOG_ERR "xmem_pool: for block %p size = %u, { fl = %d, > sl = %d } should be { fl = %d, sl = %d }\n", b, b->size, fl, sl, __fl, __sl); > + return 0; > + } > + b = b->ptr.free_ptr.next; > + } > + return 1; > +} > + > +/* > + * This function must be called from a context where pool->lock is > + * already acquired > + */ > +#define xmem_pool_check_unlocked(__pool) > __xmem_pool_check_unlocked(__FILE__, __LINE__, __pool) > +static int __xmem_pool_check_unlocked(const char *file, int line, const > struct xmem_pool *pool) > +{ > + int i; > + int woops = 0; > + static int once = 1; > + > + for ( i = 0; i < REAL_FLI; i++ ) > + { > + int fl = ( pool->fl_bitmap & (1 << i) ) ? i : -1; > + > + if ( fl >= 0 ) > + { > + int j; > + int bitmap_empty = 1; > + int matrix_empty = 1; > + > + for ( j = 0; j < MAX_SLI; j++ ) > + { > + int sl = ( pool->sl_bitmap[fl] & (1 << j) ) ? j : -1; > + > + if ( sl < 0 ) > + continue; > + > + if ( once && !pool->matrix[fl][sl] ) > + { > + /* The bitmap is corrupted */ > + printk(XENLOG_ERR "xmem_pool:%s:%d the TLSF bitmap is > corrupted\n", file, line); > + __warn((char *)file, line); > + once = 0; > + woops = 1; > + } > + else if ( once && > !xmem_pool_check_size(pool->matrix[fl][sl], fl, sl)) > + { > + printk(XENLOG_ERR "xmem_pool:%s:%d the TLSF chunk matrix > is corrupted\n", file, line); > + __warn((char *)file, line); > + once = 0; > + woops = 1; > + } > + if ( pool->matrix[fl][sl] ) > + matrix_empty = 0; > + bitmap_empty = 0; > + } > + if ( once && bitmap_empty ) > + { > + /* The bitmap is corrupted */ > + printk(XENLOG_ERR "xmem_pool:%s:%d the TLSF bitmap is > corrupted (non-empty FL with empty SL)\n", file, line); > + __warn((char *)file, line); > + once = 0; > + woops = 1; > + } > + if ( once && matrix_empty ) > + { > + /* The bitmap is corrupted */ > + printk(XENLOG_ERR "xmem_pool:%s:%d the TLSF bitmap is > corrupted (empty matrix)\n", file, line); > + __warn((char *)file, line); > + once = 0; > + woops = 1; > + } > + } > + } > + > + return woops; > +} > + > +#define xmem_pool_check_locked(__pool) __xmem_pool_check_locked(__FILE__, > __LINE__, __pool) > +static int __xmem_pool_check_locked(const char *file, int line, struct > xmem_pool *pool) > +{ > + int err; > + > + spin_lock(&pool->lock); > + err = __xmem_pool_check_unlocked(file, line, pool); > + spin_unlock(&pool->lock); > + return err; > +} > + > +int __xmem_pool_check(const char *file, int line) > +{ > + return __xmem_pool_check_locked(file, line, xenpool); > +} > +#else > +#define xmem_pool_check_locked(__pool) do { if ( 0 && (__pool) ); } while (0) > +#define xmem_pool_check_unlocked(__pool) do { if ( 0 && (__pool) ); } while > (0) > +#endif > > /** > * Returns indexes (fl, sl) of the list used to serve request of size r > @@ -381,6 +492,8 @@ void *xmem_pool_alloc(unsigned long size, struct > xmem_pool *pool) > int fl, sl; > unsigned long tmp_size; > > + xmem_pool_check_locked(pool); > + > if ( pool->init_region == NULL ) > { > if ( (region = pool->get_mem(pool->init_size)) == NULL ) > @@ -442,11 +555,13 @@ void *xmem_pool_alloc(unsigned long size, struct > xmem_pool *pool) > > pool->used_size += (b->size & BLOCK_SIZE_MASK) + BHDR_OVERHEAD; > > + xmem_pool_check_unlocked(pool); > spin_unlock(&pool->lock); > return (void *)b->ptr.buffer; > > /* Failed alloc */ > out_locked: > + xmem_pool_check_unlocked(pool); > spin_unlock(&pool->lock); > > out: > @@ -464,6 +579,7 @@ void xmem_pool_free(void *ptr, struct xmem_pool *pool) > b = (struct bhdr *)((char *) ptr - BHDR_OVERHEAD); > > spin_lock(&pool->lock); > + xmem_pool_check_unlocked(pool); > b->size |= FREE_BLOCK; > pool->used_size -= (b->size & BLOCK_SIZE_MASK) + BHDR_OVERHEAD; > b->ptr.free_ptr = (struct free_ptr) { NULL, NULL}; > @@ -500,6 +616,7 @@ void xmem_pool_free(void *ptr, struct xmem_pool *pool) > tmp_b->size |= PREV_FREE; > tmp_b->prev_hdr = b; > out: > + xmem_pool_check_unlocked(pool); > spin_unlock(&pool->lock); > } > > @@ -512,8 +629,6 @@ int xmem_pool_maxalloc(struct xmem_pool *pool) > * Glue for xmalloc(). > */ > > -static struct xmem_pool *xenpool; > - > static void *xmalloc_pool_get(unsigned long size) > { > ASSERT(size == PAGE_SIZE); > diff --git a/xen/include/xen/xmalloc.h b/xen/include/xen/xmalloc.h > index 24a99ac..626ead0 100644 > --- a/xen/include/xen/xmalloc.h > +++ b/xen/include/xen/xmalloc.h > @@ -123,4 +123,11 @@ unsigned long xmem_pool_get_used_size(struct xmem_pool > *pool); > */ > unsigned long xmem_pool_get_total_size(struct xmem_pool *pool); > > +#ifndef NDEBUG > +#define xmem_pool_check() __xmem_pool_check(__FILE__, __LINE__) > +int __xmem_pool_check(const char *file, int line); > +#else > +#define xmem_pool_check() do { if ( 0 ); } while (0) > +#endif > + > #endif /* __XMALLOC_H__ */ This change will generate a message like this one: [2014-12-04 15:41:23] (XEN) [ 1374.507125] xmem_pool: for block ffff8304004fb9b0 size = 0, { fl = 3, sl = 9 } should be { fl = 0, sl = 0 } [2014-12-04 15:41:23] (XEN) [ 1374.507127] xmem_pool:xmalloc_tlsf.c:582 the TLSF chunk matrix is corrupted [2014-12-04 15:41:23] (XEN) [ 1374.507128] Xen WARN at xmalloc_tlsf.c:582 [2014-12-04 15:41:23] (XEN) [ 1374.507131] ----[ Xen-4.4.1 x86_64 debug=y Not tainted ]---- [2014-12-04 15:41:23] (XEN) [ 1374.507132] CPU: 3 [2014-12-04 15:41:23] (XEN) [ 1374.507133] RIP: e008:[<ffff82d0801428b0>] __warn+0x1a/0x1e [2014-12-04 15:41:23] (XEN) [ 1374.507136] RFLAGS: 0000000000010282 CONTEXT: hypervisor [2014-12-04 15:41:23] (XEN) [ 1374.507138] rax: 0000000000000000 rbx: 0000000000000009 rcx: 0000000000000000 [2014-12-04 15:41:23] (XEN) [ 1374.507139] rdx: ffff830414388000 rsi: 000000000000000a rdi: ffff82d0802926dc [2014-12-04 15:41:23] (XEN) [ 1374.507141] rbp: ffff83041438fd38 rsp: ffff83041438fd38 r8: ffff8304143b0000 [2014-12-04 15:41:23] (XEN) [ 1374.507142] r9: 0000000000000006 r10: 000000000007bcf8 r11: 0000000000000006 [2014-12-04 15:41:23] (XEN) [ 1374.507143] r12: 0000000000000003 r13: 0000000000000001 r14: 0000000000000003 [2014-12-04 15:41:23] (XEN) [ 1374.507145] r15: ffff8304143ca300 cr0: 000000008005003b cr4: 00000000001526f0 [2014-12-04 15:41:23] (XEN) [ 1374.507146] cr3: 0000000403af6000 cr2: ffffffffff600400 [2014-12-04 15:41:23] (XEN) [ 1374.507147] ds: 002b es: 002b fs: 0000 gs: 0000 ss: e010 cs: e008 [2014-12-04 15:41:23] (XEN) [ 1374.507149] Xen stack trace from rsp=ffff83041438fd38: [2014-12-04 15:41:23] (XEN) [ 1374.507150] ffff83041438fda8 ffff82d0801324d7 0000000000000000 0000013ff87075a2 [2014-12-04 15:41:23] (XEN) [ 1374.507152] 000000ff96ef1b38 000002468016e35d ffff82d08025a8b9 ffff8304143ca000 [2014-12-04 15:41:23] (XEN) [ 1374.507155] 0000000000000001 ffff83040fc67010 ffff8304143ca000 ffff8304143cb868 [2014-12-04 15:41:23] (XEN) [ 1374.507157] ffff830402338000 ffff830410dc7dec ffff83041438fdd8 ffff82d080132dc5 [2014-12-04 15:41:23] (XEN) [ 1374.507159] ffff8300dbfb0030 ffff8300d4bfa000 ffff83040fc67010 ffff830402338da8 [2014-12-04 15:41:23] (XEN) [ 1374.507161] ffff83041438fe18 ffff82d08013358d ffff8300dbfb0000 ffff8300d4bfa000 [2014-12-04 15:41:23] (XEN) [ 1374.507164] 0000000000000000 ffff830402338da8 ffff830402338000 ffff830410dc7dec [2014-12-04 15:41:23] (XEN) [ 1374.507166] ffff83041438fe38 ffff82d0801a2da2 ffff83041438fe48 ffff8300d4bfa000 [2014-12-04 15:41:23] (XEN) [ 1374.507168] ffff83041438fe48 ffff82d0801675bc ffff83041438fe68 ffff82d080161015 [2014-12-04 15:41:23] (XEN) [ 1374.507171] ffff8300d4bfa000 ffff8300d4bfa000 ffff83041438fe98 ffff82d080105094 [2014-12-04 15:41:23] (XEN) [ 1374.507173] ffff8304143962c0 0000000000000000 0000000000000000 ffff830414388000 [2014-12-04 15:41:23] (XEN) [ 1374.507175] ffff83041438fec8 ffff82d0801337d0 ffff830414363dec ffff82d080308180 [2014-12-04 15:41:23] (XEN) [ 1374.507177] ffff82d080308000 ffffffffffffffff ffff83041438fef8 ffff82d08012aa36 [2014-12-04 15:41:23] (XEN) [ 1374.507180] ffff8300d47fe000 ffff8300dbfb0000 0000000000000001 ffff830410dc7000 [2014-12-04 15:41:23] (XEN) [ 1374.507182] ffff83041438ff08 ffff82d08012aa8f ffff83041438fda0 ffff82d08022bd91 [2014-12-04 15:41:23] (XEN) [ 1374.507184] ffff880024c43fd8 ffffffff81ab1b38 0000000000000000 0000000000000000 [2014-12-04 15:41:23] (XEN) [ 1374.507186] ffff880024c43ec0 0000000000000002 0000000000000246 0000000000000000 [2014-12-04 15:41:23] (XEN) [ 1374.507188] 0000000000000000 0000000000000000 0000000000000000 ffffffff810013aa [2014-12-04 15:41:23] (XEN) [ 1374.507190] 0000000000000000 00000000deadbeef 00000000deadbeef 0002010000000000 [2014-12-04 15:41:23] (XEN) [ 1374.507192] ffffffff810013aa 000000000000e033 0000000000000246 ffff880024c43ea8 [2014-12-04 15:41:23] (XEN) [ 1374.507194] Xen call trace: [2014-12-04 15:41:23] (XEN) [ 1374.507196] [<ffff82d0801428b0>] __warn+0x1a/0x1e [2014-12-04 15:41:23] (XEN) [ 1374.507198] [<ffff82d0801324d7>] __xmem_pool_check_unlocked+0x143/0x24f [2014-12-04 15:41:23] (XEN) [ 1374.507200] [<ffff82d080132dc5>] xmem_pool_free+0x3f/0x2d9 [2014-12-04 15:41:23] (XEN) [ 1374.507201] [<ffff82d08013358d>] xfree+0x1d5/0x222 [2014-12-04 15:41:23] (XEN) [ 1374.507203] [<ffff82d0801a2da2>] xstate_free_save_area+0x18/0x2a [2014-12-04 15:41:23] (XEN) [ 1374.507205] [<ffff82d0801675bc>] vcpu_destroy_fpu+0x13/0x23 [2014-12-04 15:41:23] (XEN) [ 1374.507207] [<ffff82d080161015>] vcpu_destroy+0x26/0x50 [2014-12-04 15:41:23] (XEN) [ 1374.507209] [<ffff82d080105094>] complete_domain_destroy+0x49/0x16a [2014-12-04 15:41:23] (XEN) [ 1374.507211] [<ffff82d0801337d0>] rcu_process_callbacks+0x145/0x1a6 [2014-12-04 15:41:23] (XEN) [ 1374.507213] [<ffff82d08012aa36>] __do_softirq+0x81/0x8c [2014-12-04 15:41:23] (XEN) [ 1374.507215] [<ffff82d08012aa8f>] do_softirq+0x13/0x15 [2014-12-04 15:41:23] (XEN) [ 1374.507253] [<ffff82d08022bd91>] process_softirqs+0x21/0x30 every time the xmem pool gets corrupted. This is only a hint, though. A developer will have to place xmem_pool_check() in various places to determine the source of the corruption. I used it to track down a use after free bug (details will follow later). Thanks, -- Mihai DONÈU _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |