diff options
author | 2008-11-22 17:31:52 +0000 | |
---|---|---|
committer | 2008-11-22 17:31:52 +0000 | |
commit | 00a3bdb3abbe43c3ba1efe56c630afef5ecfc1f2 (patch) | |
tree | 8ddaa8c066acc2901ebd20074ae485d31ce177d4 /sys/kern/subr_pool.c | |
parent | Some nVidia MCP77 AHCI controllers need special handling. There's 12 (diff) | |
download | wireguard-openbsd-00a3bdb3abbe43c3ba1efe56c630afef5ecfc1f2.tar.xz wireguard-openbsd-00a3bdb3abbe43c3ba1efe56c630afef5ecfc1f2.zip |
Do deadbeef-style protection in pools too, by default, even though it it
is a lot slower. Before release this should be backed out, but for now
we need everyone to run with this and start finding the use-after-free
style bugs this exposes. original version from tedu
ok everyone in the room
Diffstat (limited to 'sys/kern/subr_pool.c')
-rw-r--r-- | sys/kern/subr_pool.c | 119 |
1 files changed, 68 insertions, 51 deletions
diff --git a/sys/kern/subr_pool.c b/sys/kern/subr_pool.c index 8f8b72d9048..37298cee6af 100644 --- a/sys/kern/subr_pool.c +++ b/sys/kern/subr_pool.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_pool.c,v 1.66 2008/10/31 17:17:06 deraadt Exp $ */ +/* $OpenBSD: subr_pool.c,v 1.67 2008/11/22 17:31:52 deraadt Exp $ */ /* $NetBSD: subr_pool.c,v 1.61 2001/09/26 07:14:56 chs Exp $ */ /*- @@ -76,7 +76,7 @@ struct pool_item_header { struct pool_item { #ifdef DIAGNOSTIC - int pi_magic; + u_int32_t pi_magic; #endif #ifdef DEADBEEF1 #define PI_MAGIC DEADBEEF1 @@ -152,7 +152,7 @@ pr_find_pagehead(struct pool *pp, caddr_t page) */ void pr_rmpage(struct pool *pp, struct pool_item_header *ph, - struct pool_pagelist *pq) + struct pool_pagelist *pq) { /* @@ -226,7 +226,7 @@ pool_init(struct pool *pp, size_t size, u_int align, u_int ioff, int flags, #ifdef DIAGNOSTIC if (size > palloc->pa_pagesz) panic("pool_init: pool item size (%lu) too large", - (u_long)size); + (u_long)size); #endif /* @@ -314,7 +314,7 @@ pool_init(struct pool *pp, size_t size, u_int align, u_int ioff, int flags, } /* Insert this into the list of all pools. */ - TAILQ_INSERT_TAIL(&pool_head, pp, pr_poollist); + TAILQ_INSERT_HEAD(&pool_head, pp, pr_poollist); } void @@ -393,6 +393,9 @@ pool_do_get(struct pool *pp, int flags) struct pool_item_header *ph; void *v; int slowdown = 0; +#ifdef DIAGNOSTIC + int i, *ip; +#endif #ifdef DIAGNOSTIC if ((flags & PR_WAITOK) != 0) @@ -438,7 +441,7 @@ startover: */ if (pp->pr_hardlimit_warning != NULL && ratecheck(&pp->pr_hardlimit_warning_last, - &pp->pr_hardlimit_ratecap)) + &pp->pr_hardlimit_ratecap)) log(LOG_ERR, "%s\n", pp->pr_hardlimit_warning); pp->pr_nfail++; @@ -512,10 +515,18 @@ startover: #endif #ifdef DIAGNOSTIC - if (__predict_false(pi->pi_magic != PI_MAGIC)) { - panic("pool_do_get(%s): free list modified: magic=%x; page %p;" - " item addr %p", - pp->pr_wchan, pi->pi_magic, ph->ph_page, pi); + if (__predict_false(pi->pi_magic != PI_MAGIC)) + panic("pool_do_get(%s): free list modified: " + "page %p; item addr %p; offset 0x%x=0x%x", + pp->pr_wchan, ph->ph_page, pi, 0, pi->pi_magic); + for (ip = (int *)pi, i = sizeof(*pi) / sizeof(int); + i < pp->pr_size / sizeof(int); i++) { + if (ip[i] != PI_MAGIC) { + panic("pool_do_get(%s): free list modified: " + "page %p; item addr %p; offset 0x%x=0x%x", + pp->pr_wchan, ph->ph_page, pi, + i * sizeof(int), ip[i]); + } } #endif @@ -593,6 +604,12 @@ pool_do_put(struct pool *pp, void *v) struct pool_item *pi = v; struct pool_item_header *ph; caddr_t page; +#ifdef DIAGNOSTIC + int i, *ip; +#endif + + if (v == NULL) + panic("pool_put of NULL"); #ifdef MALLOC_DEBUG if (pp->pr_roflags & PR_DEBUG) { @@ -623,15 +640,9 @@ pool_do_put(struct pool *pp, void *v) */ #ifdef DIAGNOSTIC pi->pi_magic = PI_MAGIC; -#endif -#ifdef DEBUG - { - int i, *ip = v; - - for (i = 0; i < pp->pr_size / sizeof(int); i++) { - *ip++ = PI_MAGIC; - } - } + for (ip = (int *)pi, i = sizeof(*pi)/sizeof(int); + i < pp->pr_size / sizeof(int); i++) + ip[i] = PI_MAGIC; #endif TAILQ_INSERT_HEAD(&ph->ph_itemlist, pi, pi_list); @@ -735,6 +746,9 @@ pool_prime_page(struct pool *pp, caddr_t storage, struct pool_item_header *ph) unsigned int align = pp->pr_align; unsigned int ioff = pp->pr_itemoffset; int n; +#ifdef DIAGNOSTIC + int i, *ip; +#endif #ifdef DIAGNOSTIC if (((u_long)cp & (pp->pr_alloc->pa_pagesz - 1)) != 0) @@ -781,6 +795,9 @@ pool_prime_page(struct pool *pp, caddr_t storage, struct pool_item_header *ph) TAILQ_INSERT_TAIL(&ph->ph_itemlist, pi, pi_list); #ifdef DIAGNOSTIC pi->pi_magic = PI_MAGIC; + for (ip = (int *)pi, i = sizeof(*pi)/sizeof(int); + i < pp->pr_size / sizeof(int); i++) + ip[i] = PI_MAGIC; #endif cp = (caddr_t)(cp + pp->pr_size); } @@ -1103,6 +1120,8 @@ db_show_all_pools(db_expr_t expr, int haddr, db_expr_t count, char *modif) PRWORD(ovflw, " %*d", 6, 1, pp->pr_minpages); PRWORD(ovflw, " %*s", 6, 1, maxp); PRWORD(ovflw, " %*lu\n", 5, 1, pp->pr_nidle); + + pool_chk(pp, pp->pr_wchan); } } @@ -1112,16 +1131,18 @@ pool_chk_page(struct pool *pp, const char *label, struct pool_item_header *ph) struct pool_item *pi; caddr_t page; int n; +#ifdef DIAGNOSTIC + int i, *ip; +#endif page = (caddr_t)((u_long)ph & pp->pr_alloc->pa_pagemask); if (page != ph->ph_page && (pp->pr_roflags & PR_PHINPAGE) != 0) { if (label != NULL) printf("%s: ", label); - printf("pool(%p:%s): page inconsistency: page %p;" - " at page head addr %p (p %p)\n", pp, - pp->pr_wchan, ph->ph_page, - ph, page); + printf("pool(%p:%s): page inconsistency: page %p; " + "at page head addr %p (p %p)\n", + pp, pp->pr_wchan, ph->ph_page, ph, page); return 1; } @@ -1133,13 +1154,23 @@ pool_chk_page(struct pool *pp, const char *label, struct pool_item_header *ph) if (pi->pi_magic != PI_MAGIC) { if (label != NULL) printf("%s: ", label); - printf("pool(%s): free list modified: magic=%x;" - " page %p; item ordinal %d;" - " addr %p (p %p)\n", - pp->pr_wchan, pi->pi_magic, ph->ph_page, - n, pi, page); - panic("pool"); + printf("pool(%s): free list modified: " + "page %p; item ordinal %d; addr %p " + "(p %p); offset 0x%x=0x%x\n", + pp->pr_wchan, ph->ph_page, n, pi, page, + 0, pi->pi_magic); } + for (ip = (int *)pi, i = sizeof(*pi) / sizeof(int); + i < pp->pr_size / sizeof(int); i++) { + if (ip[i] != PI_MAGIC) { + printf("pool(%s): free list modified: " + "page %p; item ordinal %d; addr %p " + "(p %p); offset 0x%x=0x%x\n", + pp->pr_wchan, ph->ph_page, n, pi, + page, i * sizeof(int), ip[i]); + } + } + #endif page = (caddr_t)((u_long)pi & pp->pr_alloc->pa_pagemask); @@ -1149,9 +1180,8 @@ pool_chk_page(struct pool *pp, const char *label, struct pool_item_header *ph) if (label != NULL) printf("%s: ", label); printf("pool(%p:%s): page inconsistency: page %p;" - " item ordinal %d; addr %p (p %p)\n", pp, - pp->pr_wchan, ph->ph_page, - n, pi, page); + " item ordinal %d; addr %p (p %p)\n", pp, + pp->pr_wchan, ph->ph_page, n, pi, page); return 1; } return 0; @@ -1163,26 +1193,13 @@ pool_chk(struct pool *pp, const char *label) struct pool_item_header *ph; int r = 0; - LIST_FOREACH(ph, &pp->pr_emptypages, ph_pagelist) { - r = pool_chk_page(pp, label, ph); - if (r) { - goto out; - } - } - LIST_FOREACH(ph, &pp->pr_fullpages, ph_pagelist) { - r = pool_chk_page(pp, label, ph); - if (r) { - goto out; - } - } - LIST_FOREACH(ph, &pp->pr_partpages, ph_pagelist) { - r = pool_chk_page(pp, label, ph); - if (r) { - goto out; - } - } + LIST_FOREACH(ph, &pp->pr_emptypages, ph_pagelist) + r += pool_chk_page(pp, label, ph); + LIST_FOREACH(ph, &pp->pr_fullpages, ph_pagelist) + r += pool_chk_page(pp, label, ph); + LIST_FOREACH(ph, &pp->pr_partpages, ph_pagelist) + r += pool_chk_page(pp, label, ph); -out: return (r); } #endif |