Index: subr_pool.c =================================================================== RCS file: /cvs/src/sys/kern/subr_pool.c,v retrieving revision 1.159 diff -u -p -r1.159 subr_pool.c --- subr_pool.c 23 Sep 2014 19:54:47 -0000 1.159 +++ subr_pool.c 24 Sep 2014 04:25:06 -0000 @@ -83,14 +83,16 @@ struct pool_item_header { int ph_nmissing; /* # of chunks in use */ caddr_t ph_page; /* this page's address */ caddr_t ph_colored; /* page's colored address */ - int ph_magic; + u_long ph_magic; }; +#define POOL_MAGICBIT (1 << 3) /* keep away from perturbed low bits */ +#define POOL_PHPOISON(ph) ISSET((ph)->ph_magic, POOL_MAGICBIT) struct pool_item { - u_int32_t pi_magic; - /* Other entries use only this list entry */ + u_long pi_magic; XSIMPLEQ_ENTRY(pool_item) pi_list; }; +#define POOL_IMAGIC(ph, pi) ((u_long)(pi) ^ (ph)->ph_magic) #ifdef POOL_DEBUG int pool_debug = 1; @@ -559,18 +561,20 @@ pool_do_get(struct pool *pp, int flags) ph = pp->pr_curpage; pi = XSIMPLEQ_FIRST(&ph->ph_itemlist); - if (pi == NULL) + if (__predict_false(pi == NULL)) panic("%s: %s: page empty", __func__, pp->pr_wchan); - XSIMPLEQ_REMOVE_HEAD(&ph->ph_itemlist, pi_list); -#ifdef DIAGNOSTIC - if (pi->pi_magic != poison_value(pi)) { + if (__predict_false(pi->pi_magic != POOL_IMAGIC(ph, pi))) { panic("%s: %s free list modified: " - "page %p; item addr %p; offset 0x%x=0x%x", __func__, - pp->pr_wchan, ph->ph_page, pi, 0, pi->pi_magic); + "page %p; item addr %p; offset 0x%x=0x%lx != 0x%lx", + __func__, pp->pr_wchan, ph->ph_page, pi, + 0, pi->pi_magic, POOL_IMAGIC(ph, pi)); } - if (pool_debug && ph->ph_magic) { + XSIMPLEQ_REMOVE_HEAD(&ph->ph_itemlist, pi_list); + +#ifdef DIAGNOSTIC + if (pool_debug && POOL_PHPOISON(ph)) { size_t pidx; uint32_t pval; if (poison_check(pi + 1, pp->pr_size - sizeof(*pi), @@ -629,8 +633,6 @@ pool_put(struct pool *pp, void *v) ph = pr_find_pagehead(pp, v); #ifdef DIAGNOSTIC - pi->pi_magic = poison_value(pi); - if (pool_debug) { struct pool_item *qi; XSIMPLEQ_FOREACH(qi, &ph->ph_itemlist, pi_list) { @@ -639,13 +641,15 @@ pool_put(struct pool *pp, void *v) pp->pr_wchan, pi); } } - - if (ph->ph_magic) - poison_mem(pi + 1, pp->pr_size - sizeof(*pi)); } #endif /* DIAGNOSTIC */ + pi->pi_magic = POOL_IMAGIC(ph, pi); XSIMPLEQ_INSERT_HEAD(&ph->ph_itemlist, pi, pi_list); +#ifdef DIAGNOSTIC + if (POOL_PHPOISON(ph)) + poison_mem(pi + 1, pp->pr_size - sizeof(*pi)); +#endif /* DIAGNOSTIC */ if (ph->ph_nmissing-- == pp->pr_itemsperpage) { /* @@ -745,23 +749,23 @@ pool_p_alloc(struct pool *pp, int flags) XSIMPLEQ_INIT(&ph->ph_itemlist); ph->ph_page = addr; ph->ph_nmissing = 0; - if (pool_debug) { - do { - arc4random_buf(&ph->ph_magic, sizeof(ph->ph_magic)); - } while (ph->ph_magic == 0); - } else - ph->ph_magic = 0; + arc4random_buf(&ph->ph_magic, sizeof(ph->ph_magic)); +#ifdef DIAGNOSTIC + /* use a bit in ph_magic to record if we poison page items */ + if (pool_debug) + SET(ph->ph_magic, POOL_MAGICBIT); + else + CLR(ph->ph_magic, POOL_MAGICBIT); +#endif /* DIAGNOSTIC */ n = pp->pr_itemsperpage; while (n--) { pi = (struct pool_item *)addr; -#ifdef DIAGNOSTIC - pi->pi_magic = poison_value(pi); -#endif + pi->pi_magic = POOL_IMAGIC(ph, pi); XSIMPLEQ_INSERT_TAIL(&ph->ph_itemlist, pi, pi_list); #ifdef DIAGNOSTIC - if (pool_debug && ph->ph_magic) + if (POOL_PHPOISON(ph)) poison_mem(pi + 1, pp->pr_size - sizeof(*pi)); #endif /* DIAGNOSTIC */ @@ -774,22 +778,34 @@ pool_p_alloc(struct pool *pp, int flags) void pool_p_free(struct pool *pp, struct pool_item_header *ph) { -#ifdef DIAGNOSTIC struct pool_item *pi; -#endif MUTEX_ASSERT_UNLOCKED(&pp->pr_mtx); KASSERT(ph->ph_nmissing == 0); -#ifdef DIAGNOSTIC XSIMPLEQ_FOREACH(pi, &ph->ph_itemlist, pi_list) { - if (pi->pi_magic != poison_value(pi)) { + if (__predict_false(pi->pi_magic != POOL_IMAGIC(ph, pi))) { panic("%s: %s free list modified: " - "page %p; item addr %p; offset 0x%x=0x%x", __func__, - pp->pr_wchan, ph->ph_page, pi, 0, pi->pi_magic); + "page %p; item addr %p; offset 0x%x=0x%lx", + __func__, pp->pr_wchan, ph->ph_page, pi, + 0, pi->pi_magic); + } + +#ifdef DIAGNOSTIC + if (POOL_PHPOISON(ph)) { + size_t pidx; + uint32_t pval; + if (poison_check(pi + 1, pp->pr_size - sizeof(*pi), + &pidx, &pval)) { + int *ip = (int *)(pi + 1); + panic("%s: %s free list modified: " + "page %p; item addr %p; offset 0x%zx=0x%x", + __func__, pp->pr_wchan, ph->ph_page, pi, + pidx * sizeof(int), ip[pidx]); + } } +#endif /* DIAGNOSTIC */ } -#endif pool_allocator_free(pp, ph->ph_page); @@ -981,14 +997,12 @@ pool_print_pagelist(struct pool_pagelist LIST_FOREACH(ph, pl, ph_pagelist) { (*pr)("\t\tpage %p, nmissing %d\n", ph->ph_page, ph->ph_nmissing); -#ifdef DIAGNOSTIC XSIMPLEQ_FOREACH(pi, &ph->ph_itemlist, pi_list) { - if (pi->pi_magic != poison_value(pi)) { - (*pr)("\t\t\titem %p, magic 0x%x\n", + if (pi->pi_magic != POOL_IMAGIC(ph, pi)) { + (*pr)("\t\t\titem %p, magic 0x%lx\n", pi, pi->pi_magic); } } -#endif } } @@ -1135,17 +1149,17 @@ pool_chk_page(struct pool *pp, struct po for (pi = XSIMPLEQ_FIRST(&ph->ph_itemlist), n = 0; pi != NULL; pi = XSIMPLEQ_NEXT(&ph->ph_itemlist, pi, pi_list), n++) { -#ifdef DIAGNOSTIC - if (pi->pi_magic != poison_value(pi)) { + if (pi->pi_magic != POOL_IMAGIC(ph, pi)) { printf("%s: ", label); printf("pool(%p:%s): free list modified: " "page %p; item ordinal %d; addr %p " - "(p %p); offset 0x%x=0x%x\n", + "(p %p); offset 0x%x=0x%lx\n", pp, pp->pr_wchan, ph->ph_page, n, pi, page, 0, pi->pi_magic); } - if (pool_debug && ph->ph_magic) { +#ifdef DIAGNOSTIC + if (POOL_PHPOISON(ph)) { size_t pidx; uint32_t pval; if (poison_check(pi + 1, pp->pr_size - sizeof(*pi),