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