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 %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_HMAC_NO_UPDATE) ? 184 "CRYPTO_HMAC_NO_UPDATE" : " ", 185 (desc.pd_flags & CRYPTO_SYNCHRONOUS) ? 186 "CRYPTO_SYNCHRONOUS" : " ", 187 (desc.pd_flags & KCF_LPROV_MEMBER) ? 188 "KCF_LPROV_MEMBER" : " ", 189 (desc.pd_flags & KCF_PROV_RESTRICTED) ? 190 "KCF_PROV_RESTRICTED" : " "); 191 if (desc.pd_flags & CRYPTO_HASH_NO_UPDATE) 192 mdb_printf("pd_hash_limit:\t\t%u\n", desc.pd_hash_limit); 193 if (desc.pd_flags & CRYPTO_HMAC_NO_UPDATE) 194 mdb_printf("pd_hmac_limit:\t\t%u\n", desc.pd_hmac_limit); 195 196 mdb_printf("pd_kstat:\t\t%p\n", desc.pd_kstat); 197 198 return (DCMD_OK); 199 } 200 201 #define GOT_NONE (-2) 202 203 /*ARGSUSED*/ 204 int 205 prov_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 206 { 207 kcf_provider_desc_t **tab; 208 kcf_provider_desc_t desc; 209 kcf_provider_desc_t *ptr; 210 uint_t prov_tab_max; 211 int i; 212 int gotzero = GOT_NONE; 213 char string[MAXNAMELEN + 1]; 214 215 if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) { 216 return (DCMD_USAGE); 217 } else if (mdb_readsym(&ptr, sizeof (void *), "prov_tab") 218 == -1) { 219 mdb_warn("cannot read prov_tab"); 220 return (DCMD_ERR); 221 222 } else if (mdb_readvar(&prov_tab_max, "prov_tab_max") == -1) { 223 mdb_warn("cannot read prov_tab_max"); 224 return (DCMD_ERR); 225 } 226 mdb_printf("%<b>prov_tab = %p%</b>\n", ptr); 227 tab = mdb_zalloc(prov_tab_max * sizeof (kcf_provider_desc_t *), 228 UM_SLEEP| UM_GC); 229 230 #ifdef DEBUG 231 mdb_printf("DEBUG: tab = %p, prov_tab_max = %d\n", tab, prov_tab_max); 232 #endif 233 234 if (mdb_vread(tab, prov_tab_max * sizeof (kcf_provider_desc_t *), 235 (uintptr_t)ptr) == -1) { 236 mdb_warn("cannot read prov_tab"); 237 return (DCMD_ERR); 238 } 239 #ifdef DEBUG 240 mdb_printf("DEBUG: got past mdb_vread of tab\n"); 241 mdb_printf("DEBUG: *tab = %p\n", *tab); 242 #endif 243 for (i = 0; i < prov_tab_max; i++) { 244 /* save space, only print range for long list of nulls */ 245 if (tab[i] == NULL) { 246 if (gotzero == GOT_NONE) { 247 mdb_printf("prov_tab[%d", i); 248 gotzero = i; 249 } 250 } else { 251 /* first non-null in awhile, print index of prev null */ 252 if (gotzero != GOT_NONE) { 253 if (gotzero == (i - 1)) 254 mdb_printf("] = NULL\n", i - 1); 255 else 256 mdb_printf(" - %d] = NULL\n", i - 1); 257 gotzero = GOT_NONE; 258 } 259 /* interesting value, print it */ 260 mdb_printf("prov_tab[%d] = %p ", i, tab[i]); 261 262 if (mdb_vread(&desc, sizeof (kcf_provider_desc_t), 263 (uintptr_t)tab[i]) == -1) { 264 mdb_warn("cannot read at address %p", 265 (uintptr_t)tab[i]); 266 return (DCMD_ERR); 267 } 268 269 (void) mdb_readstr(string, MAXNAMELEN + 1, 270 (uintptr_t)desc.pd_name); 271 mdb_printf("(%s\t%s)\n", string, 272 prov_states[desc.pd_state]); 273 } 274 } 275 /* if we've printed the first of many nulls but left the brace open */ 276 if ((i > 0) && (tab[i-1] == NULL)) { 277 if (gotzero == GOT_NONE) 278 mdb_printf("] = NULL\n"); 279 else 280 mdb_printf(" - %d] = NULL\n", i - 1); 281 } 282 283 return (DCMD_OK); 284 } 285 286 /*ARGSUSED*/ 287 int 288 policy_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 289 { 290 kcf_policy_desc_t **tab; 291 kcf_policy_desc_t *ptr; 292 uint_t policy_tab_max; 293 int num, i; 294 int gotzero = GOT_NONE; 295 296 if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) { 297 return (DCMD_USAGE); 298 } else if (mdb_readsym(&ptr, sizeof (void *), "policy_tab") 299 == -1) { 300 mdb_warn("cannot read policy_tab"); 301 return (DCMD_ERR); 302 303 } else if (mdb_readvar(&policy_tab_max, "policy_tab_max") == -1) { 304 mdb_warn("cannot read policy_tab_max"); 305 return (DCMD_ERR); 306 } 307 308 /* get the current number of descriptors in the table */ 309 if (mdb_readvar(&num, "policy_tab_num") == -1) { 310 mdb_warn("cannot read policy_tab_num"); 311 return (DCMD_ERR); 312 } 313 mdb_printf("%<b>policy_tab = %p%</b> \tpolicy_tab_num = %d\n", 314 ptr, num); 315 316 tab = mdb_zalloc(policy_tab_max * sizeof (kcf_policy_desc_t *), 317 UM_SLEEP| UM_GC); 318 319 if (mdb_vread(tab, policy_tab_max * sizeof (kcf_policy_desc_t *), 320 (uintptr_t)ptr) == -1) { 321 mdb_warn("cannot read policy_tab"); 322 return (DCMD_ERR); 323 } 324 #ifdef DEBUG 325 mdb_printf("DEBUG: got past mdb_vread of tab\n"); 326 mdb_printf("DEBUG: *tab = %p\n", *tab); 327 #endif 328 for (i = 0; i < policy_tab_max; i++) { 329 /* save space, only print range for long list of nulls */ 330 if (tab[i] == NULL) { 331 if (gotzero == GOT_NONE) { 332 mdb_printf("policy_tab[%d", i); 333 gotzero = i; 334 } 335 } else { 336 /* first non-null in awhile, print index of prev null */ 337 if (gotzero != GOT_NONE) { 338 if (gotzero == (i - 1)) 339 mdb_printf("] = NULL\n", i - 1); 340 else 341 mdb_printf(" - %d] = NULL\n", i - 1); 342 gotzero = GOT_NONE; 343 } 344 /* interesting value, print it */ 345 mdb_printf("policy_tab[%d] = %p\n", i, tab[i]); 346 } 347 } 348 /* if we've printed the first of many nulls but left the brace open */ 349 if ((i > 0) && (tab[i-1] == NULL)) { 350 if (gotzero == GOT_NONE) 351 mdb_printf("] = NULL\n"); 352 else 353 mdb_printf(" - %d] = NULL\n", i - 1); 354 } 355 356 return (DCMD_OK); 357 } 358 359 static void 360 prt_mechs(int count, crypto_mech_name_t *mechs) 361 { 362 int i; 363 char name[CRYPTO_MAX_MECH_NAME + 1]; 364 char name2[CRYPTO_MAX_MECH_NAME + 3]; 365 366 for (i = 0; i < count; i++) { 367 if (mdb_readstr(name, CRYPTO_MAX_MECH_NAME, 368 (uintptr_t)((char *)mechs)) == -1) 369 continue; 370 /* put in quotes */ 371 (void) mdb_snprintf(name2, sizeof (name2), "\"%s\"", name); 372 /* yes, length is 32, but then it will wrap */ 373 /* this shorter size formats nicely for most cases */ 374 mdb_printf("mechs[%d]=%-28s", i, name2); 375 mdb_printf("%s", i%2 ? "\n" : " "); /* 2-columns */ 376 mechs++; 377 } 378 } 379 380 /* ARGSUSED2 */ 381 static int 382 prt_soft_conf_entry(kcf_soft_conf_entry_t *addr, kcf_soft_conf_entry_t *entry, 383 void *cbdata) 384 { 385 char name[MAXNAMELEN + 1]; 386 387 mdb_printf("\n%<b>kcf_soft_conf_entry_t at %p:%</b>\n", addr); 388 mdb_printf("ce_next: %p", entry->ce_next); 389 390 if (entry->ce_name == NULL) 391 mdb_printf("\tce_name: NULL\n"); 392 else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)entry->ce_name) 393 == -1) 394 mdb_printf("could not read ce_name from %p\n", 395 entry->ce_name); 396 else 397 mdb_printf("\tce_name: %s\n", name); 398 399 mdb_printf("ce_count: %d\n", entry->ce_count); 400 prt_mechs(entry->ce_count, entry->ce_mechs); 401 return (WALK_NEXT); 402 } 403 404 int 405 soft_conf_walk_init(mdb_walk_state_t *wsp) 406 { 407 uintptr_t *soft; 408 409 if (mdb_readsym(&soft, sizeof (kcf_soft_conf_entry_t *), 410 "soft_config_list") == -1) { 411 mdb_warn("failed to find 'soft_config_list'"); 412 return (WALK_ERR); 413 } 414 wsp->walk_addr = (uintptr_t)soft; 415 wsp->walk_data = mdb_alloc(sizeof (kcf_soft_conf_entry_t), UM_SLEEP); 416 wsp->walk_callback = (mdb_walk_cb_t)prt_soft_conf_entry; 417 return (WALK_NEXT); 418 } 419 420 /* 421 * At each step, read a kcf_soft_conf_entry_t into our private storage, then 422 * invoke the callback function. We terminate when we reach a NULL ce_next 423 * pointer. 424 */ 425 int 426 soft_conf_walk_step(mdb_walk_state_t *wsp) 427 { 428 int status; 429 430 if (wsp->walk_addr == NULL) /* then we're done */ 431 return (WALK_DONE); 432 #ifdef DEBUG 433 else 434 mdb_printf("DEBUG: wsp->walk_addr == %p\n", wsp->walk_addr); 435 #endif 436 437 if (mdb_vread(wsp->walk_data, sizeof (kcf_soft_conf_entry_t), 438 wsp->walk_addr) == -1) { 439 mdb_warn("failed to read kcf_soft_conf_entry at %p", 440 wsp->walk_addr); 441 return (WALK_DONE); 442 } 443 444 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 445 wsp->walk_cbdata); 446 447 wsp->walk_addr = 448 (uintptr_t)(((kcf_soft_conf_entry_t *)wsp->walk_data)->ce_next); 449 return (status); 450 } 451 452 /* 453 * The walker's fini function is invoked at the end of each walk. Since we 454 * dynamically allocated a kcf_soft_conf_entry_t in soft_conf_walk_init, 455 * we must free it now. 456 */ 457 void 458 soft_conf_walk_fini(mdb_walk_state_t *wsp) 459 { 460 #ifdef DEBUG 461 mdb_printf("...end of kcf_soft_conf_entry walk\n"); 462 #endif 463 mdb_free(wsp->walk_data, sizeof (kcf_soft_conf_entry_t)); 464 } 465 /* ARGSUSED2 */ 466 int 467 kcf_soft_conf_entry(uintptr_t addr, uint_t flags, int argc, 468 const mdb_arg_t *argv) 469 { 470 kcf_soft_conf_entry_t entry; 471 kcf_soft_conf_entry_t *ptr; 472 473 if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) { 474 if (addr == NULL) /* not allowed with DCMD_ADDRSPEC */ 475 return (DCMD_USAGE); 476 else 477 ptr = (kcf_soft_conf_entry_t *)addr; 478 } else if (mdb_readsym(&ptr, sizeof (void *), "soft_config_list") 479 == -1) { 480 mdb_warn("cannot read soft_config_list"); 481 return (DCMD_ERR); 482 } else 483 mdb_printf("soft_config_list = %p\n", ptr); 484 485 if (ptr == NULL) 486 return (DCMD_OK); 487 488 if (mdb_vread(&entry, sizeof (kcf_soft_conf_entry_t), (uintptr_t)ptr) 489 == -1) { 490 mdb_warn("cannot read at address %p", (uintptr_t)ptr); 491 return (DCMD_ERR); 492 } 493 494 /* this could change in the future to have more than one ret val */ 495 if (prt_soft_conf_entry(ptr, &entry, NULL) != WALK_ERR) 496 return (DCMD_OK); 497 return (DCMD_ERR); 498 } 499 500 /* ARGSUSED1 */ 501 int 502 kcf_policy_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 503 { 504 kcf_policy_desc_t desc; 505 char name[MAXNAMELEN + 1]; 506 507 508 if ((flags & DCMD_ADDRSPEC) != DCMD_ADDRSPEC) 509 return (DCMD_USAGE); 510 511 if (mdb_vread(&desc, sizeof (kcf_policy_desc_t), (uintptr_t)addr) 512 == -1) { 513 mdb_warn("Could not read kcf_policy_desc_t at %p\n", addr); 514 return (DCMD_ERR); 515 } 516 mdb_printf("pd_prov_type: %s", 517 desc.pd_prov_type == CRYPTO_HW_PROVIDER ? "CRYPTO_HW_PROVIDER" : 518 "CRYPTO_SW_PROVIDER"); 519 520 if (desc.pd_name == NULL) 521 mdb_printf("\tpd_name: NULL\n"); 522 else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)desc.pd_name) 523 == -1) 524 mdb_printf("could not read pd_name from %p\n", 525 desc.pd_name); 526 else 527 mdb_printf("\tpd_name: %s\n", name); 528 529 mdb_printf("pd_instance: %d ", desc.pd_instance); 530 mdb_printf("\t\tpd_refcnt: %d\n", desc.pd_refcnt); 531 mdb_printf("pd_mutex: %p", desc.pd_mutex); 532 mdb_printf("\t\tpd_disabled_count: %d", desc.pd_disabled_count); 533 mdb_printf("\npd_disabled_mechs:\n"); 534 mdb_inc_indent(4); 535 prt_mechs(desc.pd_disabled_count, desc.pd_disabled_mechs); 536 mdb_dec_indent(4); 537 return (DCMD_OK); 538 } 539