Project

General

Profile

Bug #1917

::umem_verify seg faults on a dump with rampant corruption

Added by John Sonnenschein over 8 years ago. Updated about 8 years ago.

Status:
Resolved
Priority:
Normal
Category:
cmd - userland programs
Start date:
2011-12-21
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:

Description

Running ::umem_verify on a dump with corruption was seen to induce a core dump from mdb:

{code}

libumem.so`umem_walk_step+0x34e(814a710, 8046810, 1c, 8626fe4, 30, fe7b6000)
layered_walk_step+0x21(8626fe4, 8046810, 814a710, fe79ae62)
libumem.so`umem_slab_walk_step+0x7a(814a6d8, 8142670, 80, 814a710)
walk_step+0x59(814a6d8, fe7b6000, 80468a8, fe79c70d)
walk_step+0x1c(814a710, 8046eb0, 80d0290, fed0ebe4)
walk_common+0x93(814a710, fe79d51c, 8046bd0, 8210010)
mdb_pwalk+0x32(fe7a5090, fe79d51c, 8046bd0, 8210010)
libumem.so`whatis_walk_cache+0x136(8210010, 8046960, 8046bd0, 8210010)
libumem.so`whatis_walk_touch+0x30(8210010, 8046960, 8046bd0, fe79aa15)
libumem.so`umem_cache_walk_step+0x51(814a7f0, 0, ffffffff, ffffffff)
walk_step+0x59(814a7f0, 8046eb0, 8046b88, 8046bc4)
walk_common+0x93(814a7f0, fe79da98, 8046bd0, 0)
mdb_pwalk+0x32(fe7a5b0c, fe79da98, 8046bd0, 0, 9, fe7b6000)
mdb_walk+0x16(fe7a5b0c, fe79da98, 8046bd0, fe79db4c)
libumem.so`whatis_run_umem+0x71(8046c20, 0, 4, 809d0d4)
cmd_whatis+0x1f4(8626018, f, 0, 0)
dcmd_invoke+0x4e(80e0358, 8626018, f, 0, 0, 0)
mdb_call_idcmd+0x134(80e0358, febcb87c, 0, 1, 0, 0)
mdb_call+0x32e(febcb87c, 0, 1, 0, 0, 8046f10)
yyparse+0x498(0, fef10000, 3, feea2dfb, 80c5080, 0)
mdb_run+0x2eb(0, 8047df8, 0, 0, 0, 0)
main+0x13e3(2, 8047d2c, 8047d38, feffbafc)
_start+0x7d(2, 8047df4, 8047df8, 0, 8047e0c, 8047e18) {code}

History

#1

Updated by Milan Jurik about 8 years ago

  • Status changed from New to Feedback

Any chance to have reproducible testcase - the problematic corefile?

#2

Updated by John Sonnenschein about 8 years ago

No, this is a copy of a Joyent bug, in order to integrate a changeset that already exists

From e9af913034578289b03c917a6f79dc40f8c2ed78 Mon Sep 17 00:00:00 2001
From: Bryan Cantrill <>
Date: Thu, 24 Nov 2011 09:01:40 +0000
Subject: [PATCH] 1917 ::umem_verify seg faults on a dump with rampant corruption
Reviewed by: Richard Lowe <>

diff --git a/usr/src/cmd/mdb/common/modules/genunix/kmem.c b/usr/src/cmd/mdb/common/modules/genunix/kmem.c
index 1dcac53..909b7ec 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 fc2126d..0bd52ba 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 &lt;sys/vmem_impl_user.h&gt;
@ -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);
}

#3

Updated by Rich Lowe about 8 years ago

  • Category set to cmd - userland programs
  • Status changed from Feedback to Resolved
  • Assignee set to Bryan Cantrill
  • % Done changed from 0 to 100
  • Tags deleted (needs-triage)

Resolved in r13557 commit:36d116935c7e

Also available in: Atom PDF