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