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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/tsol/tndb.h> 28 #include <sys/modhash_impl.h> 29 30 #include <mdb/mdb_modapi.h> 31 #include <mdb/mdb_ks.h> 32 33 #include "tsol.h" 34 #include "modhash.h" 35 36 /* ****************** tnrh ****************** */ 37 38 typedef struct tnrh_walk_s { 39 tnrhc_hash_t **hptr; 40 int idx; 41 tnrhc_hash_t *tnrhc_table[TSOL_MASK_TABLE_SIZE]; 42 tnrhc_hash_t *tnrhc_table_v6[TSOL_MASK_TABLE_SIZE_V6]; 43 } tnrh_walk_t; 44 45 /* 46 * Free the mdb storage pointed to by the given per-prefix table. 47 */ 48 static void 49 free_table(tnrhc_hash_t **table, int ntable) 50 { 51 while (--ntable >= 0) { 52 if (*table != NULL) 53 mdb_free(*table, TNRHC_SIZE * sizeof (**table)); 54 table++; 55 } 56 } 57 58 /* 59 * Read in a list of per-prefix-length hash tables. Allocate storage for the 60 * hashes that are present. On successful return, the table will contain 61 * pointers to mdb-resident storage, not kernel addresses. On failure, the 62 * contents will not point to any mdb storage. 63 */ 64 static int 65 read_table(const char *symname, tnrhc_hash_t **table, int ntable) 66 { 67 GElf_Sym tnrhc_hash; 68 tnrhc_hash_t **hp; 69 uintptr_t addr; 70 71 if (mdb_lookup_by_name(symname, &tnrhc_hash) == -1) { 72 mdb_warn("failed to read %s", symname); 73 return (-1); 74 } 75 if (mdb_vread(table, ntable * sizeof (*table), 76 tnrhc_hash.st_value) == -1) { 77 mdb_warn("can't read %s at %p", symname, tnrhc_hash.st_value); 78 return (-1); 79 } 80 for (hp = table; hp < table + ntable; hp++) { 81 if ((addr = (uintptr_t)*hp) != 0) { 82 *hp = mdb_alloc(TNRHC_SIZE * sizeof (**hp), UM_SLEEP); 83 if (mdb_vread(*hp, TNRHC_SIZE * sizeof (**hp), 84 addr) == -1) { 85 mdb_warn("can't read %s[%d] at %p", symname, 86 hp - table, addr); 87 free_table(table, (hp - table) + 1); 88 return (-1); 89 } 90 } 91 } 92 return (0); 93 } 94 95 int 96 tnrh_walk_init(mdb_walk_state_t *wsp) 97 { 98 tnrh_walk_t *twp; 99 100 twp = mdb_alloc(sizeof (*twp), UM_SLEEP); 101 102 if (read_table("tnrhc_table", twp->tnrhc_table, 103 TSOL_MASK_TABLE_SIZE) == -1) { 104 mdb_free(twp, sizeof (*twp)); 105 return (WALK_ERR); 106 } 107 if (read_table("tnrhc_table_v6", twp->tnrhc_table_v6, 108 TSOL_MASK_TABLE_SIZE_V6) == -1) { 109 free_table(twp->tnrhc_table, TSOL_MASK_TABLE_SIZE); 110 mdb_free(twp, sizeof (*twp)); 111 return (WALK_ERR); 112 } 113 114 twp->hptr = twp->tnrhc_table; 115 twp->idx = 0; 116 wsp->walk_addr = 0; 117 wsp->walk_data = twp; 118 119 return (WALK_NEXT); 120 } 121 122 int 123 tnrh_walk_step(mdb_walk_state_t *wsp) 124 { 125 tnrh_walk_t *twp = wsp->walk_data; 126 tsol_tnrhc_t tnrhc; 127 int status; 128 129 while (wsp->walk_addr == 0) { 130 if (*twp->hptr == NULL || twp->idx >= TNRHC_SIZE) { 131 twp->hptr++; 132 if (twp->hptr == twp->tnrhc_table + 133 TSOL_MASK_TABLE_SIZE) 134 twp->hptr = twp->tnrhc_table_v6; 135 else if (twp->hptr == twp->tnrhc_table_v6 + 136 TSOL_MASK_TABLE_SIZE_V6) 137 return (WALK_DONE); 138 twp->idx = 0; 139 } else { 140 wsp->walk_addr = (uintptr_t)(*twp->hptr)[twp->idx++]. 141 tnrh_list; 142 } 143 } 144 145 if (mdb_vread(&tnrhc, sizeof (tnrhc), wsp->walk_addr) == -1) { 146 mdb_warn("can't read tsol_tnrhc_t at %p", wsp->walk_addr); 147 return (WALK_ERR); 148 } 149 150 status = wsp->walk_callback(wsp->walk_addr, &tnrhc, 151 wsp->walk_cbdata); 152 153 wsp->walk_addr = (uintptr_t)tnrhc.rhc_next; 154 return (status); 155 } 156 157 void 158 tnrh_walk_fini(mdb_walk_state_t *wsp) 159 { 160 tnrh_walk_t *twp = wsp->walk_data; 161 162 free_table(twp->tnrhc_table, TSOL_MASK_TABLE_SIZE); 163 free_table(twp->tnrhc_table_v6, TSOL_MASK_TABLE_SIZE_V6); 164 mdb_free(twp, sizeof (*twp)); 165 } 166 167 /* ****************** tnrhtp ****************** */ 168 169 typedef struct tnrhtp_walk_data_s { 170 int (*old_callback)(uintptr_t, const void *, void *); 171 void *old_cbdata; 172 } tnrhtp_walk_data_t; 173 174 /* ARGSUSED */ 175 static int 176 tnrhtp_walk_callback(uintptr_t addr, const void *data, void *private) 177 { 178 const struct mod_hash_entry *mhe = data; 179 tnrhtp_walk_data_t *twd = private; 180 tsol_tpc_t tpc; 181 182 if (mdb_vread(&tpc, sizeof (tpc), (uintptr_t)mhe->mhe_val) == -1) { 183 mdb_warn("failed to read tsol_tpc_t at %p", mhe->mhe_val); 184 return (WALK_ERR); 185 } else { 186 return (twd->old_callback((uintptr_t)mhe->mhe_val, &tpc, 187 twd->old_cbdata)); 188 } 189 } 190 191 int 192 tnrhtp_walk_init(mdb_walk_state_t *wsp) 193 { 194 mod_hash_t *tpc_name_hash; 195 196 if (mdb_readvar(&tpc_name_hash, "tpc_name_hash") == -1) { 197 mdb_warn("failed to read tpc_name_hash"); 198 return (WALK_ERR); 199 } 200 201 wsp->walk_addr = (uintptr_t)tpc_name_hash; 202 203 return (modent_walk_init(wsp)); 204 } 205 206 int 207 tnrhtp_walk_step(mdb_walk_state_t *wsp) 208 { 209 tnrhtp_walk_data_t twd; 210 int retv; 211 212 twd.old_callback = wsp->walk_callback; 213 twd.old_cbdata = wsp->walk_cbdata; 214 wsp->walk_callback = tnrhtp_walk_callback; 215 wsp->walk_cbdata = &twd; 216 217 retv = modent_walk_step(wsp); 218 219 wsp->walk_callback = twd.old_callback; 220 wsp->walk_cbdata = twd.old_cbdata; 221 222 return (retv); 223 } 224 225 void 226 tnrhtp_walk_fini(mdb_walk_state_t *wsp) 227 { 228 modent_walk_fini(wsp); 229 } 230