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 <stdlib.h> 27 #include <strings.h> 28 #include <zone.h> 29 #include <errno.h> 30 #include <sys/types.h> 31 #include <sys/tsol/label_macro.h> 32 33 /* 34 * Get label from zone name 35 */ 36 m_label_t * 37 getzonelabelbyname(const char *zone) 38 { 39 zoneid_t zoneid; 40 41 if ((zoneid = getzoneidbyname(zone)) == -1) { 42 errno = EINVAL; 43 return (NULL); 44 } 45 return (getzonelabelbyid(zoneid)); 46 } 47 48 /* 49 * Get label from zone id 50 */ 51 m_label_t * 52 getzonelabelbyid(zoneid_t zoneid) 53 { 54 m_label_t *slabel; 55 56 if ((slabel = m_label_alloc(MAC_LABEL)) == NULL) 57 return (NULL); 58 59 if (zone_getattr(zoneid, ZONE_ATTR_SLBL, slabel, 60 sizeof (m_label_t)) < 0) { 61 m_label_free(slabel); 62 errno = EINVAL; 63 return (NULL); 64 } 65 66 return (slabel); 67 } 68 69 /* 70 * Get zone id from label 71 */ 72 73 zoneid_t 74 getzoneidbylabel(const m_label_t *label) 75 { 76 m_label_t admin_low; 77 m_label_t admin_high; 78 zoneid_t zoneid; 79 zoneid_t *zids; 80 uint_t nzents; 81 uint_t nzents_saved; 82 int i; 83 84 bsllow(&admin_low); 85 bslhigh(&admin_high); 86 87 /* Check for admin_low or admin_high; both are global zone */ 88 if (blequal(label, &admin_low) || blequal(label, &admin_high)) 89 return (GLOBAL_ZONEID); 90 91 nzents = 0; 92 if (zone_list(NULL, &nzents) != 0) 93 return (-1); 94 95 again: 96 if (nzents == 0) { 97 errno = EINVAL; 98 return (-1); 99 } 100 101 /* 102 * Add a small amount of padding here to avoid spinning in a tight loop 103 * if there's a process running somewhere that's creating lots of zones 104 * all at once. 105 */ 106 nzents += 8; 107 if ((zids = malloc(nzents * sizeof (zoneid_t))) == NULL) 108 return (-1); 109 nzents_saved = nzents; 110 111 if (zone_list(zids, &nzents) != 0) { 112 free(zids); 113 return (-1); 114 } 115 if (nzents > nzents_saved) { 116 /* list changed, try again */ 117 free(zids); 118 goto again; 119 } 120 121 for (i = 0; i < nzents; i++) { 122 m_label_t test_sl; 123 124 if (zids[i] == GLOBAL_ZONEID) 125 continue; 126 127 if (zone_getattr(zids[i], ZONE_ATTR_SLBL, &test_sl, 128 sizeof (m_label_t)) < 0) 129 continue; /* Badly configured zone info */ 130 131 if (blequal(label, &test_sl) != 0) { 132 zoneid = zids[i]; 133 free(zids); 134 return (zoneid); 135 } 136 } 137 free(zids); 138 errno = EINVAL; 139 return (-1); 140 } 141 142 /* 143 * Get zoneroot for a zoneid 144 */ 145 146 char * 147 getzonerootbyid(zoneid_t zoneid) 148 { 149 char zoneroot[MAXPATHLEN]; 150 151 if (zone_getattr(zoneid, ZONE_ATTR_ROOT, zoneroot, 152 sizeof (zoneroot)) == -1) { 153 return (NULL); 154 } 155 156 return (strdup(zoneroot)); 157 } 158 159 /* 160 * Get zoneroot for a zonename 161 */ 162 163 char * 164 getzonerootbyname(const char *zone) 165 { 166 zoneid_t zoneid; 167 168 if ((zoneid = getzoneidbyname(zone)) == -1) 169 return (NULL); 170 return (getzonerootbyid(zoneid)); 171 } 172 173 /* 174 * Get zoneroot for a label 175 */ 176 177 char * 178 getzonerootbylabel(const m_label_t *label) 179 { 180 zoneid_t zoneid; 181 182 if ((zoneid = getzoneidbylabel(label)) == -1) 183 return (NULL); 184 return (getzonerootbyid(zoneid)); 185 } 186 187 /* 188 * Get label of path relative to global zone 189 * 190 * This function must be called from the global zone 191 */ 192 193 m_label_t * 194 getlabelbypath(const char *path) 195 { 196 m_label_t *slabel; 197 zoneid_t *zids; 198 uint_t nzents; 199 uint_t nzents_saved; 200 int i; 201 202 if (getzoneid() != GLOBAL_ZONEID) { 203 errno = EINVAL; 204 return (NULL); 205 } 206 207 nzents = 0; 208 if (zone_list(NULL, &nzents) != 0) 209 return (NULL); 210 211 again: 212 /* Add a small amount of padding to avoid loops */ 213 nzents += 8; 214 zids = malloc(nzents * sizeof (zoneid_t)); 215 if (zids == NULL) 216 return (NULL); 217 218 nzents_saved = nzents; 219 220 if (zone_list(zids, &nzents) != 0) { 221 free(zids); 222 return (NULL); 223 } 224 if (nzents > nzents_saved) { 225 /* list changed, try again */ 226 free(zids); 227 goto again; 228 } 229 230 slabel = m_label_alloc(MAC_LABEL); 231 if (slabel == NULL) { 232 free(zids); 233 return (NULL); 234 } 235 236 for (i = 0; i < nzents; i++) { 237 char zoneroot[MAXPATHLEN]; 238 int zonerootlen; 239 240 if (zids[i] == GLOBAL_ZONEID) 241 continue; 242 243 if (zone_getattr(zids[i], ZONE_ATTR_ROOT, zoneroot, 244 sizeof (zoneroot)) == -1) 245 continue; /* Badly configured zone info */ 246 247 /* 248 * Need to handle the case for the /dev directory which is 249 * parallel to the zone's root directory. So we back up 250 * 4 bytes - the strlen of "root". 251 */ 252 if ((zonerootlen = strlen(zoneroot)) <= 4) 253 continue; /* Badly configured zone info */ 254 if (strncmp(path, zoneroot, zonerootlen - 4) == 0) { 255 /* 256 * If we get a match, the file is in a labeled zone. 257 * Return the label of that zone. 258 */ 259 if (zone_getattr(zids[i], ZONE_ATTR_SLBL, slabel, 260 sizeof (m_label_t)) < 0) 261 continue; /* Badly configured zone info */ 262 263 free(zids); 264 return (slabel); 265 } 266 } 267 free(zids); 268 bsllow(slabel); 269 return (slabel); 270 } 271