diff options
author | Bryan Cantrill <bryan@joyent.com> | 2012-01-10 20:31:45 -0500 |
---|---|---|
committer | Bryan Cantrill <bryan@joyent.com> | 2012-01-10 20:31:45 -0500 |
commit | d7dba7e519e96f726807ca55f6a17fef3f90092f (patch) | |
tree | f23feb26ccefc9a97c71c033e1fd9dc0c4a16bca | |
parent | cabb4db90a300665d2c6540b76706ab5302b583c (diff) | |
download | illumos-joyent-d7dba7e519e96f726807ca55f6a17fef3f90092f.tar.gz |
1917 ::umem_verify seg faults on a dump with rampant corruption
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
-rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/kmem.c | 29 | ||||
-rw-r--r-- | 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 <mdb/mdb_param.h> #include <mdb/mdb_modapi.h> #include <mdb/mdb_ctf.h> @@ -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 <sys/vmem_impl_user.h> @@ -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); } |