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