summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Cantrill <bryan@joyent.com>2012-01-10 20:31:45 -0500
committerBryan Cantrill <bryan@joyent.com>2012-01-10 20:31:45 -0500
commitd7dba7e519e96f726807ca55f6a17fef3f90092f (patch)
treef23feb26ccefc9a97c71c033e1fd9dc0c4a16bca
parentcabb4db90a300665d2c6540b76706ab5302b583c (diff)
downloadillumos-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.c29
-rw-r--r--usr/src/cmd/mdb/common/modules/libumem/umem.c29
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);
}