summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_pool.c
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>2008-11-22 17:31:52 +0000
committerderaadt <deraadt@openbsd.org>2008-11-22 17:31:52 +0000
commit00a3bdb3abbe43c3ba1efe56c630afef5ecfc1f2 (patch)
tree8ddaa8c066acc2901ebd20074ae485d31ce177d4 /sys/kern/subr_pool.c
parentSome nVidia MCP77 AHCI controllers need special handling. There's 12 (diff)
downloadwireguard-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.c119
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