1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * mdb dcmds for selected structures from 28 * usr/src/uts/common/sys/crypto/impl.h 29 */ 30 #include <stdio.h> 31 #include <sys/mdb_modapi.h> 32 #include <sys/modctl.h> 33 #include <sys/types.h> 34 #include <sys/crypto/api.h> 35 #include <sys/crypto/common.h> 36 #include <sys/crypto/impl.h> 37 #include "crypto_cmds.h" 38 39 static const char *prov_states[] = { 40 "none", 41 "KCF_PROV_ALLOCATED", 42 "KCF_PROV_UNVERIFIED", 43 "KCF_PROV_VERIFICATION_FAILED", 44 "KCF_PROV_READY", 45 "KCF_PROV_BUSY", 46 "KCF_PROV_FAILED", 47 "KCF_PROV_DISABLED", 48 "KCF_PROV_UNREGISTERING", 49 "KCF_PROV_UNREGISTERED" 50 }; 51 52 /*ARGSUSED*/ 53 int 54 kcf_provider_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 55 { 56 kcf_provider_desc_t desc; 57 kcf_provider_desc_t *ptr; 58 char string[MAXNAMELEN + 1]; 59 int i, j; 60 crypto_mech_info_t *mech_pointer; 61 kcf_prov_cpu_t stats; 62 uint64_t dtotal, ftotal, btotal; 63 int holdcnt, jobcnt; 64 65 if ((flags & DCMD_ADDRSPEC) != DCMD_ADDRSPEC) 66 return (DCMD_USAGE); 67 ptr = (kcf_provider_desc_t *)addr; 68 69 #ifdef DEBUG 70 mdb_printf("DEBUG: reading kcf_provider_desc at %p\n", ptr); 71 #endif 72 73 if (mdb_vread(&desc, sizeof (kcf_provider_desc_t), (uintptr_t)ptr) 74 == -1) { 75 mdb_warn("cannot read at address %p", (uintptr_t)ptr); 76 return (DCMD_ERR); 77 } 78 mdb_printf("%<b>kcf_provider_desc at %p%</b>\n", ptr); 79 80 switch (desc.pd_prov_type) { 81 case CRYPTO_HW_PROVIDER: 82 mdb_printf("pd_prov_type:\t\tCRYPTO_HW_PROVIDER\n"); 83 break; 84 case CRYPTO_SW_PROVIDER: 85 mdb_printf("pd_prov_type:\t\tCRYPTO_SW_PROVIDER\n"); 86 break; 87 case CRYPTO_LOGICAL_PROVIDER: 88 mdb_printf("pd_prov_type:\t\tCRYPTO_LOGICAL_PROVIDER\n"); 89 break; 90 default: 91 mdb_printf("bad pd_prov_type:\t%d\n", desc.pd_prov_type); 92 } 93 94 mdb_printf("pd_prov_id:\t\t%u\n", desc.pd_prov_id); 95 if (desc.pd_description == NULL) 96 mdb_printf("pd_description:\t\tNULL\n"); 97 else if (mdb_readstr(string, MAXNAMELEN + 1, 98 (uintptr_t)desc.pd_description) == -1) { 99 mdb_warn("cannot read %p", desc.pd_description); 100 } else 101 mdb_printf("pd_description:\t\t%s\n", string); 102 103 mdb_printf("pd_sid:\t\t\t%u\n", desc.pd_sid); 104 mdb_printf("pd_taskq:\t\t%p\n", desc.pd_taskq); 105 mdb_printf("pd_nbins:\t\t%u\n", desc.pd_nbins); 106 mdb_printf("pd_percpu_bins:\t\t%p\n", desc.pd_percpu_bins); 107 108 dtotal = ftotal = btotal = 0; 109 holdcnt = jobcnt = 0; 110 for (i = 0; i < desc.pd_nbins; i++) { 111 if (mdb_vread(&stats, sizeof (kcf_prov_cpu_t), 112 (uintptr_t)(desc.pd_percpu_bins + i)) == -1) { 113 mdb_warn("cannot read addr %p", 114 desc.pd_percpu_bins + i); 115 return (DCMD_ERR); 116 } 117 118 holdcnt += stats.kp_holdcnt; 119 jobcnt += stats.kp_jobcnt; 120 dtotal += stats.kp_ndispatches; 121 ftotal += stats.kp_nfails; 122 btotal += stats.kp_nbusy_rval; 123 } 124 mdb_inc_indent(4); 125 mdb_printf("total kp_holdcnt:\t\t%d\n", holdcnt); 126 mdb_printf("total kp_jobcnt:\t\t%u\n", jobcnt); 127 mdb_printf("total kp_ndispatches:\t%llu\n", dtotal); 128 mdb_printf("total kp_nfails:\t\t%llu\n", ftotal); 129 mdb_printf("total kp_nbusy_rval:\t%llu\n", btotal); 130 mdb_dec_indent(4); 131 132 mdb_printf("pd_prov_handle:\t\t%p\n", desc.pd_prov_handle); 133 mdb_printf("pd_kcf_prov_handle:\t%u\n", desc.pd_kcf_prov_handle); 134 135 mdb_printf("pd_ops_vector:\t\t%p\n", desc.pd_ops_vector); 136 mdb_printf("pd_mech_list_count:\t%u\n", desc.pd_mech_list_count); 137 /* mechanisms */ 138 mdb_inc_indent(4); 139 for (i = 0; i < desc.pd_mech_list_count; i++) { 140 mech_pointer = desc.pd_mechanisms + i; 141 mdb_call_dcmd("crypto_mech_info", 142 (uintptr_t)mech_pointer, DCMD_ADDRSPEC, 0, NULL); 143 } 144 mdb_dec_indent(4); 145 mdb_printf("pd_mech_indx:\n"); 146 mdb_inc_indent(8); 147 for (i = 0; i < KCF_OPS_CLASSSIZE; i++) { 148 for (j = 0; j < KCF_MAXMECHTAB; j++) { 149 if (desc.pd_mech_indx[i][j] == KCF_INVALID_INDX) 150 mdb_printf("N "); 151 else 152 mdb_printf("%u ", desc.pd_mech_indx[i][j]); 153 } 154 mdb_printf("\n"); 155 } 156 mdb_dec_indent(8); 157 158 if (desc.pd_name == NULL) 159 mdb_printf("pd_name:\t\t NULL\n"); 160 else if (mdb_readstr(string, MAXNAMELEN + 1, (uintptr_t)desc.pd_name) 161 == -1) 162 mdb_warn("could not read pd_name from %X\n", desc.pd_name); 163 else 164 mdb_printf("pd_name:\t\t%s\n", string); 165 166 mdb_printf("pd_instance:\t\t%u\n", desc.pd_instance); 167 mdb_printf("pd_module_id:\t\t%d\n", desc.pd_module_id); 168 mdb_printf("pd_mctlp:\t\t%p\n", desc.pd_mctlp); 169 mdb_printf("pd_lock:\t\t%p\n", desc.pd_lock); 170 if (desc.pd_state < KCF_PROV_ALLOCATED || 171 desc.pd_state > KCF_PROV_UNREGISTERED) 172 mdb_printf("pd_state is invalid:\t%d\n", desc.pd_state); 173 else 174 mdb_printf("pd_state:\t%s\n", prov_states[desc.pd_state]); 175 mdb_printf("pd_provider_list:\t%p\n", desc.pd_provider_list); 176 177 mdb_printf("pd_resume_cv:\t\t%hd\n", desc.pd_resume_cv._opaque); 178 mdb_printf("pd_flags:\t\t%s %s %s %s %s\n", 179 (desc.pd_flags & CRYPTO_HIDE_PROVIDER) ? 180 "CRYPTO_HIDE_PROVIDER" : " ", 181 (desc.pd_flags & CRYPTO_HASH_NO_UPDATE) ? 182 "CRYPTO_HASH_NO_UPDATE" : " ", 183 (desc.pd_flags & CRYPTO_SYNCHRONOUS) ? 184 "CRYPTO_SYNCHRONOUS" : " ", 185 (desc.pd_flags & KCF_LPROV_MEMBER) ? 186 "KCF_LPROV_MEMBER" : " ", 187 (desc.pd_flags & KCF_PROV_RESTRICTED) ? 188 "KCF_PROV_RESTRICTED" : " "); 189 if (desc.pd_flags & CRYPTO_HASH_NO_UPDATE) 190 mdb_printf("pd_hash_limit:\t\t%u\n", desc.pd_hash_limit); 191 192 mdb_printf("pd_kstat:\t\t%p\n", desc.pd_kstat); 193 194 return (DCMD_OK); 195 } 196 197 #define GOT_NONE (-2) 198 199 /*ARGSUSED*/ 200 int 201 prov_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 202 { 203 kcf_provider_desc_t **tab; 204 kcf_provider_desc_t desc; 205 kcf_provider_desc_t *ptr; 206 uint_t prov_tab_max; 207 int i; 208 int gotzero = GOT_NONE; 209 char string[MAXNAMELEN + 1]; 210 211 if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) { 212 return (DCMD_USAGE); 213 } else if (mdb_readsym(&ptr, sizeof (void *), "prov_tab") 214 == -1) { 215 mdb_warn("cannot read prov_tab"); 216 return (DCMD_ERR); 217 218 } else if (mdb_readvar(&prov_tab_max, "prov_tab_max") == -1) { 219 mdb_warn("cannot read prov_tab_max"); 220 return (DCMD_ERR); 221 } 222 mdb_printf("%<b>prov_tab = %p%</b>\n", ptr); 223 tab = mdb_zalloc(prov_tab_max * sizeof (kcf_provider_desc_t *), 224 UM_SLEEP| UM_GC); 225 226 #ifdef DEBUG 227 mdb_printf("DEBUG: tab = %p, prov_tab_max = %d\n", tab, prov_tab_max); 228 #endif 229 230 if (mdb_vread(tab, prov_tab_max * sizeof (kcf_provider_desc_t *), 231 (uintptr_t)ptr) == -1) { 232 mdb_warn("cannot read prov_tab"); 233 return (DCMD_ERR); 234 } 235 #ifdef DEBUG 236 mdb_printf("DEBUG: got past mdb_vread of tab\n"); 237 mdb_printf("DEBUG: *tab = %p\n", *tab); 238 #endif 239 for (i = 0; i < prov_tab_max; i++) { 240 /* save space, only print range for long list of nulls */ 241 if (tab[i] == NULL) { 242 if (gotzero == GOT_NONE) { 243 mdb_printf("prov_tab[%d", i); 244 gotzero = i; 245 } 246 } else { 247 /* first non-null in awhile, print index of prev null */ 248 if (gotzero != GOT_NONE) { 249 if (gotzero == (i - 1)) 250 mdb_printf("] = NULL\n", i - 1); 251 else 252 mdb_printf(" - %d] = NULL\n", i - 1); 253 gotzero = GOT_NONE; 254 } 255 /* interesting value, print it */ 256 mdb_printf("prov_tab[%d] = %p ", i, tab[i]); 257 258 if (mdb_vread(&desc, sizeof (kcf_provider_desc_t), 259 (uintptr_t)tab[i]) == -1) { 260 mdb_warn("cannot read at address %p", 261 (uintptr_t)tab[i]); 262 return (DCMD_ERR); 263 } 264 265 (void) mdb_readstr(string, MAXNAMELEN + 1, 266 (uintptr_t)desc.pd_name); 267 mdb_printf("(%s\t%s)\n", string, 268 prov_states[desc.pd_state]); 269 } 270 } 271 /* if we've printed the first of many nulls but left the brace open */ 272 if ((i > 0) && (tab[i-1] == NULL)) { 273 if (gotzero == GOT_NONE) 274 mdb_printf("] = NULL\n"); 275 else 276 mdb_printf(" - %d] = NULL\n", i - 1); 277 } 278 279 return (DCMD_OK); 280 } 281 282 /*ARGSUSED*/ 283 int 284 policy_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 285 { 286 kcf_policy_desc_t **tab; 287 kcf_policy_desc_t *ptr; 288 uint_t policy_tab_max; 289 int num, i; 290 int gotzero = GOT_NONE; 291 292 if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) { 293 return (DCMD_USAGE); 294 } else if (mdb_readsym(&ptr, sizeof (void *), "policy_tab") 295 == -1) { 296 mdb_warn("cannot read policy_tab"); 297 return (DCMD_ERR); 298 299 } else if (mdb_readvar(&policy_tab_max, "policy_tab_max") == -1) { 300 mdb_warn("cannot read policy_tab_max"); 301 return (DCMD_ERR); 302 } 303 304 /* get the current number of descriptors in the table */ 305 if (mdb_readvar(&num, "policy_tab_num") == -1) { 306 mdb_warn("cannot read policy_tab_num"); 307 return (DCMD_ERR); 308 } 309 mdb_printf("%<b>policy_tab = %p%</b> \tpolicy_tab_num = %d\n", 310 ptr, num); 311 312 tab = mdb_zalloc(policy_tab_max * sizeof (kcf_policy_desc_t *), 313 UM_SLEEP| UM_GC); 314 315 if (mdb_vread(tab, policy_tab_max * sizeof (kcf_policy_desc_t *), 316 (uintptr_t)ptr) == -1) { 317 mdb_warn("cannot read policy_tab"); 318 return (DCMD_ERR); 319 } 320 #ifdef DEBUG 321 mdb_printf("DEBUG: got past mdb_vread of tab\n"); 322 mdb_printf("DEBUG: *tab = %p\n", *tab); 323 #endif 324 for (i = 0; i < policy_tab_max; i++) { 325 /* save space, only print range for long list of nulls */ 326 if (tab[i] == NULL) { 327 if (gotzero == GOT_NONE) { 328 mdb_printf("policy_tab[%d", i); 329 gotzero = i; 330 } 331 } else { 332 /* first non-null in awhile, print index of prev null */ 333 if (gotzero != GOT_NONE) { 334 if (gotzero == (i - 1)) 335 mdb_printf("] = NULL\n", i - 1); 336 else 337 mdb_printf(" - %d] = NULL\n", i - 1); 338 gotzero = GOT_NONE; 339 } 340 /* interesting value, print it */ 341 mdb_printf("policy_tab[%d] = %p\n", i, tab[i]); 342 } 343 } 344 /* if we've printed the first of many nulls but left the brace open */ 345 if ((i > 0) && (tab[i-1] == NULL)) { 346 if (gotzero == GOT_NONE) 347 mdb_printf("] = NULL\n"); 348 else 349 mdb_printf(" - %d] = NULL\n", i - 1); 350 } 351 352 return (DCMD_OK); 353 } 354 355 static void 356 prt_mechs(int count, crypto_mech_name_t *mechs) 357 { 358 int i; 359 char name[CRYPTO_MAX_MECH_NAME + 1]; 360 char name2[CRYPTO_MAX_MECH_NAME + 3]; 361 362 for (i = 0; i < count; i++) { 363 if (mdb_readstr(name, CRYPTO_MAX_MECH_NAME, 364 (uintptr_t)((char *)mechs)) == -1) 365 continue; 366 /* put in quotes */ 367 (void) mdb_snprintf(name2, sizeof (name2), "\"%s\"", name); 368 /* yes, length is 32, but then it will wrap */ 369 /* this shorter size formats nicely for most cases */ 370 mdb_printf("mechs[%d]=%-28s", i, name2); 371 mdb_printf("%s", i%2 ? "\n" : " "); /* 2-columns */ 372 mechs++; 373 } 374 } 375 376 /* ARGSUSED2 */ 377 static int 378 prt_soft_conf_entry(kcf_soft_conf_entry_t *addr, kcf_soft_conf_entry_t *entry, 379 void *cbdata) 380 { 381 char name[MAXNAMELEN + 1]; 382 383 mdb_printf("\n%<b>kcf_soft_conf_entry_t at %p:%</b>\n", addr); 384 mdb_printf("ce_next: %p", entry->ce_next); 385 386 if (entry->ce_name == NULL) 387 mdb_printf("\tce_name: NULL\n"); 388 else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)entry->ce_name) 389 == -1) 390 mdb_printf("could not read ce_name from %p\n", 391 entry->ce_name); 392 else 393 mdb_printf("\tce_name: %s\n", name); 394 395 mdb_printf("ce_count: %d\n", entry->ce_count); 396 prt_mechs(entry->ce_count, entry->ce_mechs); 397 return (WALK_NEXT); 398 } 399 400 int 401 soft_conf_walk_init(mdb_walk_state_t *wsp) 402 { 403 uintptr_t *soft; 404 405 if (mdb_readsym(&soft, sizeof (kcf_soft_conf_entry_t *), 406 "soft_config_list") == -1) { 407 mdb_warn("failed to find 'soft_config_list'"); 408 return (WALK_ERR); 409 } 410 wsp->walk_addr = (uintptr_t)soft; 411 wsp->walk_data = mdb_alloc(sizeof (kcf_soft_conf_entry_t), UM_SLEEP); 412 wsp->walk_callback = (mdb_walk_cb_t)prt_soft_conf_entry; 413 return (WALK_NEXT); 414 } 415 416 /* 417 * At each step, read a kcf_soft_conf_entry_t into our private storage, then 418 * invoke the callback function. We terminate when we reach a NULL ce_next 419 * pointer. 420 */ 421 int 422 soft_conf_walk_step(mdb_walk_state_t *wsp) 423 { 424 int status; 425 426 if (wsp->walk_addr == NULL) /* then we're done */ 427 return (WALK_DONE); 428 #ifdef DEBUG 429 else 430 mdb_printf("DEBUG: wsp->walk_addr == %p\n", wsp->walk_addr); 431 #endif 432 433 if (mdb_vread(wsp->walk_data, sizeof (kcf_soft_conf_entry_t), 434 wsp->walk_addr) == -1) { 435 mdb_warn("failed to read kcf_soft_conf_entry at %p", 436 wsp->walk_addr); 437 return (WALK_DONE); 438 } 439 440 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 441 wsp->walk_cbdata); 442 443 wsp->walk_addr = 444 (uintptr_t)(((kcf_soft_conf_entry_t *)wsp->walk_data)->ce_next); 445 return (status); 446 } 447 448 /* 449 * The walker's fini function is invoked at the end of each walk. Since we 450 * dynamically allocated a kcf_soft_conf_entry_t in soft_conf_walk_init, 451 * we must free it now. 452 */ 453 void 454 soft_conf_walk_fini(mdb_walk_state_t *wsp) 455 { 456 #ifdef DEBUG 457 mdb_printf("...end of kcf_soft_conf_entry walk\n"); 458 #endif 459 mdb_free(wsp->walk_data, sizeof (kcf_soft_conf_entry_t)); 460 } 461 /* ARGSUSED2 */ 462 int 463 kcf_soft_conf_entry(uintptr_t addr, uint_t flags, int argc, 464 const mdb_arg_t *argv) 465 { 466 kcf_soft_conf_entry_t entry; 467 kcf_soft_conf_entry_t *ptr; 468 469 if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) { 470 if (addr == NULL) /* not allowed with DCMD_ADDRSPEC */ 471 return (DCMD_USAGE); 472 else 473 ptr = (kcf_soft_conf_entry_t *)addr; 474 } else if (mdb_readsym(&ptr, sizeof (void *), "soft_config_list") 475 == -1) { 476 mdb_warn("cannot read soft_config_list"); 477 return (DCMD_ERR); 478 } else 479 mdb_printf("soft_config_list = %p\n", ptr); 480 481 if (ptr == NULL) 482 return (DCMD_OK); 483 484 if (mdb_vread(&entry, sizeof (kcf_soft_conf_entry_t), (uintptr_t)ptr) 485 == -1) { 486 mdb_warn("cannot read at address %p", (uintptr_t)ptr); 487 return (DCMD_ERR); 488 } 489 490 /* this could change in the future to have more than one ret val */ 491 if (prt_soft_conf_entry(ptr, &entry, NULL) != WALK_ERR) 492 return (DCMD_OK); 493 return (DCMD_ERR); 494 } 495 496 /* ARGSUSED1 */ 497 int 498 kcf_policy_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 499 { 500 kcf_policy_desc_t desc; 501 char name[MAXNAMELEN + 1]; 502 503 504 if ((flags & DCMD_ADDRSPEC) != DCMD_ADDRSPEC) 505 return (DCMD_USAGE); 506 507 if (mdb_vread(&desc, sizeof (kcf_policy_desc_t), (uintptr_t)addr) 508 == -1) { 509 mdb_warn("Could not read kcf_policy_desc_t at %p\n", addr); 510 return (DCMD_ERR); 511 } 512 mdb_printf("pd_prov_type: %s", 513 desc.pd_prov_type == CRYPTO_HW_PROVIDER ? "CRYPTO_HW_PROVIDER" : 514 "CRYPTO_SW_PROVIDER"); 515 516 if (desc.pd_name == NULL) 517 mdb_printf("\tpd_name: NULL\n"); 518 else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)desc.pd_name) 519 == -1) 520 mdb_printf("could not read pd_name from %p\n", 521 desc.pd_name); 522 else 523 mdb_printf("\tpd_name: %s\n", name); 524 525 mdb_printf("pd_instance: %d ", desc.pd_instance); 526 mdb_printf("\t\tpd_refcnt: %d\n", desc.pd_refcnt); 527 mdb_printf("pd_mutex: %p", desc.pd_mutex); 528 mdb_printf("\t\tpd_disabled_count: %d", desc.pd_disabled_count); 529 mdb_printf("\npd_disabled_mechs:\n"); 530 mdb_inc_indent(4); 531 prt_mechs(desc.pd_disabled_count, desc.pd_disabled_mechs); 532 mdb_dec_indent(4); 533 return (DCMD_OK); 534 } 535