From d7dba7e519e96f726807ca55f6a17fef3f90092f Mon Sep 17 00:00:00 2001 From: Bryan Cantrill Date: Tue, 10 Jan 2012 20:31:45 -0500 Subject: 1917 ::umem_verify seg faults on a dump with rampant corruption Reviewed by: Richard Lowe Reviewed by: Robert Mustacchi Approved by: Richard Lowe --- usr/src/cmd/mdb/common/modules/genunix/kmem.c | 29 +++++++++++++++++++-------- usr/src/cmd/mdb/common/modules/libumem/umem.c | 29 +++++++++++++++++++-------- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/usr/src/cmd/mdb/common/modules/genunix/kmem.c b/usr/src/cmd/mdb/common/modules/genunix/kmem.c index 1dcac5344f..909b7ecc7b 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/kmem.c +++ b/usr/src/cmd/mdb/common/modules/genunix/kmem.c @@ -23,6 +23,10 @@ * Use is subject to license terms. */ +/* + * Copyright 2011 Joyent, Inc. All rights reserved. + */ + #include #include #include @@ -1121,7 +1125,7 @@ bufctl_walk_callback(kmem_cache_t *cp, mdb_walk_state_t *wsp, uintptr_t buf) typedef struct kmem_walk { int kmw_type; - int kmw_addr; /* cache address */ + uintptr_t kmw_addr; /* cache address */ kmem_cache_t *kmw_cp; size_t kmw_csize; @@ -1488,15 +1492,24 @@ kmem_walk_step(mdb_walk_state_t *wsp) buf = bc.bc_addr; } else { /* - * Otherwise the buffer is in the slab which - * we've read in; we just need to determine - * its offset in the slab to find the - * kmem_bufctl_t. + * Otherwise the buffer is (or should be) in the slab + * that we've read in; determine its offset in the + * slab, validate that it's not corrupt, and add to + * our base address to find the umem_bufctl_t. (Note + * that we don't need to add the size of the bufctl + * to our offset calculation because of the slop that's + * allocated for the buffer at ubase.) */ - bc = *((kmem_bufctl_t *) - ((uintptr_t)bcp - (uintptr_t)kbase + - (uintptr_t)ubase)); + uintptr_t offs = (uintptr_t)bcp - (uintptr_t)kbase; + + if (offs > chunks * chunksize) { + mdb_warn("found corrupt bufctl ptr %p" + " in slab %p in cache %p\n", bcp, + wsp->walk_addr, addr); + break; + } + bc = *((kmem_bufctl_t *)((uintptr_t)ubase + offs)); buf = KMEM_BUF(cp, bcp); } diff --git a/usr/src/cmd/mdb/common/modules/libumem/umem.c b/usr/src/cmd/mdb/common/modules/libumem/umem.c index fc2126de05..0bd52baf1e 100644 --- a/usr/src/cmd/mdb/common/modules/libumem/umem.c +++ b/usr/src/cmd/mdb/common/modules/libumem/umem.c @@ -23,6 +23,10 @@ * Use is subject to license terms. */ +/* + * Copyright 2011 Joyent, Inc. All rights reserved. + */ + #include "umem.h" #include @@ -920,7 +924,7 @@ bufctl_walk_callback(umem_cache_t *cp, mdb_walk_state_t *wsp, uintptr_t buf) typedef struct umem_walk { int umw_type; - int umw_addr; /* cache address */ + uintptr_t umw_addr; /* cache address */ umem_cache_t *umw_cp; size_t umw_csize; @@ -1266,15 +1270,24 @@ umem_walk_step(mdb_walk_state_t *wsp) buf = bc.bc_addr; } else { /* - * Otherwise the buffer is in the slab which - * we've read in; we just need to determine - * its offset in the slab to find the - * umem_bufctl_t. + * Otherwise the buffer is (or should be) in the slab + * that we've read in; determine its offset in the + * slab, validate that it's not corrupt, and add to + * our base address to find the umem_bufctl_t. (Note + * that we don't need to add the size of the bufctl + * to our offset calculation because of the slop that's + * allocated for the buffer at ubase.) */ - bc = *((umem_bufctl_t *) - ((uintptr_t)bcp - (uintptr_t)kbase + - (uintptr_t)ubase)); + uintptr_t offs = (uintptr_t)bcp - (uintptr_t)kbase; + + if (offs > chunks * chunksize) { + mdb_warn("found corrupt bufctl ptr %p" + " in slab %p in cache %p\n", bcp, + wsp->walk_addr, addr); + break; + } + bc = *((umem_bufctl_t *)((uintptr_t)ubase + offs)); buf = UMEM_BUF(cp, bcp); } -- cgit v1.2.3