Home | History | Annotate | Download | only in common
      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