xref: /titanic_50/usr/src/lib/libtsol/common/zone.c (revision 45916cd2fec6e79bca5dee0421bd39e3c2910d1e)
1*45916cd2Sjpk /*
2*45916cd2Sjpk  * CDDL HEADER START
3*45916cd2Sjpk  *
4*45916cd2Sjpk  * The contents of this file are subject to the terms of the
5*45916cd2Sjpk  * Common Development and Distribution License (the "License").
6*45916cd2Sjpk  * You may not use this file except in compliance with the License.
7*45916cd2Sjpk  *
8*45916cd2Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*45916cd2Sjpk  * or http://www.opensolaris.org/os/licensing.
10*45916cd2Sjpk  * See the License for the specific language governing permissions
11*45916cd2Sjpk  * and limitations under the License.
12*45916cd2Sjpk  *
13*45916cd2Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
14*45916cd2Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*45916cd2Sjpk  * If applicable, add the following below this CDDL HEADER, with the
16*45916cd2Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
17*45916cd2Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
18*45916cd2Sjpk  *
19*45916cd2Sjpk  * CDDL HEADER END
20*45916cd2Sjpk  */
21*45916cd2Sjpk /*
22*45916cd2Sjpk  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*45916cd2Sjpk  * Use is subject to license terms.
24*45916cd2Sjpk  */
25*45916cd2Sjpk 
26*45916cd2Sjpk #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*45916cd2Sjpk 
28*45916cd2Sjpk #include	<stdlib.h>
29*45916cd2Sjpk #include	<strings.h>
30*45916cd2Sjpk #include	<zone.h>
31*45916cd2Sjpk #include	<errno.h>
32*45916cd2Sjpk #include	<sys/types.h>
33*45916cd2Sjpk #include 	<sys/tsol/label_macro.h>
34*45916cd2Sjpk 
35*45916cd2Sjpk /*
36*45916cd2Sjpk  * Get label from zone name
37*45916cd2Sjpk  */
38*45916cd2Sjpk m_label_t *
getzonelabelbyname(const char * zone)39*45916cd2Sjpk getzonelabelbyname(const char *zone)
40*45916cd2Sjpk {
41*45916cd2Sjpk 	zoneid_t	zoneid;
42*45916cd2Sjpk 
43*45916cd2Sjpk 	if ((zoneid = getzoneidbyname(zone)) == -1) {
44*45916cd2Sjpk 		errno = EINVAL;
45*45916cd2Sjpk 		return (NULL);
46*45916cd2Sjpk 	}
47*45916cd2Sjpk 	return (getzonelabelbyid(zoneid));
48*45916cd2Sjpk }
49*45916cd2Sjpk 
50*45916cd2Sjpk /*
51*45916cd2Sjpk  * Get label from zone id
52*45916cd2Sjpk  */
53*45916cd2Sjpk m_label_t *
getzonelabelbyid(zoneid_t zoneid)54*45916cd2Sjpk getzonelabelbyid(zoneid_t zoneid)
55*45916cd2Sjpk {
56*45916cd2Sjpk 	m_label_t 	*slabel;
57*45916cd2Sjpk 
58*45916cd2Sjpk 	if ((slabel = m_label_alloc(MAC_LABEL)) == NULL)
59*45916cd2Sjpk 		return (NULL);
60*45916cd2Sjpk 
61*45916cd2Sjpk 	if (zone_getattr(zoneid, ZONE_ATTR_SLBL, slabel,
62*45916cd2Sjpk 	    sizeof (m_label_t)) < 0) {
63*45916cd2Sjpk 		m_label_free(slabel);
64*45916cd2Sjpk 		errno = EINVAL;
65*45916cd2Sjpk 		return (NULL);
66*45916cd2Sjpk 	}
67*45916cd2Sjpk 
68*45916cd2Sjpk 	return (slabel);
69*45916cd2Sjpk }
70*45916cd2Sjpk 
71*45916cd2Sjpk /*
72*45916cd2Sjpk  * Get zone id from label
73*45916cd2Sjpk  */
74*45916cd2Sjpk 
75*45916cd2Sjpk zoneid_t
getzoneidbylabel(const m_label_t * label)76*45916cd2Sjpk getzoneidbylabel(const m_label_t *label)
77*45916cd2Sjpk {
78*45916cd2Sjpk 	m_label_t	admin_low;
79*45916cd2Sjpk 	m_label_t	admin_high;
80*45916cd2Sjpk 	zoneid_t	zoneid;
81*45916cd2Sjpk 	zoneid_t 	*zids;
82*45916cd2Sjpk 	uint_t		nzents;
83*45916cd2Sjpk 	uint_t		nzents_saved;
84*45916cd2Sjpk 	int		i;
85*45916cd2Sjpk 
86*45916cd2Sjpk 	bsllow(&admin_low);
87*45916cd2Sjpk 	bslhigh(&admin_high);
88*45916cd2Sjpk 
89*45916cd2Sjpk 	/* Check for admin_low or admin_high; both are global zone */
90*45916cd2Sjpk 	if (blequal(label, &admin_low) || blequal(label, &admin_high))
91*45916cd2Sjpk 		return (GLOBAL_ZONEID);
92*45916cd2Sjpk 
93*45916cd2Sjpk 	nzents = 0;
94*45916cd2Sjpk 	if (zone_list(NULL, &nzents) != 0)
95*45916cd2Sjpk 		return (-1);
96*45916cd2Sjpk 
97*45916cd2Sjpk again:
98*45916cd2Sjpk 	if (nzents == 0) {
99*45916cd2Sjpk 		errno = EINVAL;
100*45916cd2Sjpk 		return (-1);
101*45916cd2Sjpk 	}
102*45916cd2Sjpk 
103*45916cd2Sjpk 	/*
104*45916cd2Sjpk 	 * Add a small amount of padding here to avoid spinning in a tight loop
105*45916cd2Sjpk 	 * if there's a process running somewhere that's creating lots of zones
106*45916cd2Sjpk 	 * all at once.
107*45916cd2Sjpk 	 */
108*45916cd2Sjpk 	nzents += 8;
109*45916cd2Sjpk 	if ((zids = malloc(nzents * sizeof (zoneid_t))) == NULL)
110*45916cd2Sjpk 		return (-1);
111*45916cd2Sjpk 	nzents_saved = nzents;
112*45916cd2Sjpk 
113*45916cd2Sjpk 	if (zone_list(zids, &nzents) != 0) {
114*45916cd2Sjpk 		free(zids);
115*45916cd2Sjpk 		return (-1);
116*45916cd2Sjpk 	}
117*45916cd2Sjpk 	if (nzents > nzents_saved) {
118*45916cd2Sjpk 		/* list changed, try again */
119*45916cd2Sjpk 		free(zids);
120*45916cd2Sjpk 		goto again;
121*45916cd2Sjpk 	}
122*45916cd2Sjpk 
123*45916cd2Sjpk 	for (i = 0; i < nzents; i++) {
124*45916cd2Sjpk 		m_label_t	test_sl;
125*45916cd2Sjpk 
126*45916cd2Sjpk 		if (zids[i] == GLOBAL_ZONEID)
127*45916cd2Sjpk 			continue;
128*45916cd2Sjpk 
129*45916cd2Sjpk 		if (zone_getattr(zids[i], ZONE_ATTR_SLBL, &test_sl,
130*45916cd2Sjpk 		    sizeof (m_label_t)) < 0)
131*45916cd2Sjpk 			continue;	/* Badly configured zone info */
132*45916cd2Sjpk 
133*45916cd2Sjpk 		if (blequal(label, &test_sl) != 0) {
134*45916cd2Sjpk 			zoneid = zids[i];
135*45916cd2Sjpk 			free(zids);
136*45916cd2Sjpk 			return (zoneid);
137*45916cd2Sjpk 		}
138*45916cd2Sjpk 	}
139*45916cd2Sjpk 	free(zids);
140*45916cd2Sjpk 	errno = EINVAL;
141*45916cd2Sjpk 	return (-1);
142*45916cd2Sjpk }
143*45916cd2Sjpk 
144*45916cd2Sjpk /*
145*45916cd2Sjpk  * Get zoneroot for a zoneid
146*45916cd2Sjpk  */
147*45916cd2Sjpk 
148*45916cd2Sjpk char *
getzonerootbyid(zoneid_t zoneid)149*45916cd2Sjpk getzonerootbyid(zoneid_t zoneid)
150*45916cd2Sjpk {
151*45916cd2Sjpk 	char zoneroot[MAXPATHLEN];
152*45916cd2Sjpk 
153*45916cd2Sjpk 	if (zone_getattr(zoneid, ZONE_ATTR_ROOT, zoneroot,
154*45916cd2Sjpk 	    sizeof (zoneroot)) == -1) {
155*45916cd2Sjpk 		return (NULL);
156*45916cd2Sjpk 	}
157*45916cd2Sjpk 
158*45916cd2Sjpk 	return (strdup(zoneroot));
159*45916cd2Sjpk }
160*45916cd2Sjpk 
161*45916cd2Sjpk /*
162*45916cd2Sjpk  * Get zoneroot for a zonename
163*45916cd2Sjpk  */
164*45916cd2Sjpk 
165*45916cd2Sjpk char *
getzonerootbyname(const char * zone)166*45916cd2Sjpk getzonerootbyname(const char *zone)
167*45916cd2Sjpk {
168*45916cd2Sjpk 	zoneid_t	zoneid;
169*45916cd2Sjpk 
170*45916cd2Sjpk 	if ((zoneid = getzoneidbyname(zone)) == -1)
171*45916cd2Sjpk 		return (NULL);
172*45916cd2Sjpk 	return (getzonerootbyid(zoneid));
173*45916cd2Sjpk }
174*45916cd2Sjpk 
175*45916cd2Sjpk /*
176*45916cd2Sjpk  * Get zoneroot for a label
177*45916cd2Sjpk  */
178*45916cd2Sjpk 
179*45916cd2Sjpk char *
getzonerootbylabel(const m_label_t * label)180*45916cd2Sjpk getzonerootbylabel(const m_label_t *label)
181*45916cd2Sjpk {
182*45916cd2Sjpk 	zoneid_t	zoneid;
183*45916cd2Sjpk 
184*45916cd2Sjpk 	if ((zoneid = getzoneidbylabel(label)) == -1)
185*45916cd2Sjpk 		return (NULL);
186*45916cd2Sjpk 	return (getzonerootbyid(zoneid));
187*45916cd2Sjpk }
188*45916cd2Sjpk 
189*45916cd2Sjpk /*
190*45916cd2Sjpk  * Get label of path relative to global zone
191*45916cd2Sjpk  *
192*45916cd2Sjpk  * This function must be called from the global zone
193*45916cd2Sjpk  */
194*45916cd2Sjpk 
195*45916cd2Sjpk m_label_t *
getlabelbypath(const char * path)196*45916cd2Sjpk getlabelbypath(const char *path)
197*45916cd2Sjpk {
198*45916cd2Sjpk 	m_label_t	*slabel;
199*45916cd2Sjpk 	zoneid_t 	*zids;
200*45916cd2Sjpk 	uint_t		nzents;
201*45916cd2Sjpk 	uint_t		nzents_saved;
202*45916cd2Sjpk 	int		i;
203*45916cd2Sjpk 
204*45916cd2Sjpk 	if (getzoneid() != GLOBAL_ZONEID) {
205*45916cd2Sjpk 		errno = EINVAL;
206*45916cd2Sjpk 		return (NULL);
207*45916cd2Sjpk 	}
208*45916cd2Sjpk 
209*45916cd2Sjpk 	nzents = 0;
210*45916cd2Sjpk 	if (zone_list(NULL, &nzents) != 0)
211*45916cd2Sjpk 		return (NULL);
212*45916cd2Sjpk 
213*45916cd2Sjpk again:
214*45916cd2Sjpk 	/* Add a small amount of padding to avoid loops */
215*45916cd2Sjpk 	nzents += 8;
216*45916cd2Sjpk 	zids = malloc(nzents * sizeof (zoneid_t));
217*45916cd2Sjpk 	if (zids == NULL)
218*45916cd2Sjpk 		return (NULL);
219*45916cd2Sjpk 
220*45916cd2Sjpk 	nzents_saved = nzents;
221*45916cd2Sjpk 
222*45916cd2Sjpk 	if (zone_list(zids, &nzents) != 0) {
223*45916cd2Sjpk 		free(zids);
224*45916cd2Sjpk 		return (NULL);
225*45916cd2Sjpk 	}
226*45916cd2Sjpk 	if (nzents > nzents_saved) {
227*45916cd2Sjpk 		/* list changed, try again */
228*45916cd2Sjpk 		free(zids);
229*45916cd2Sjpk 		goto again;
230*45916cd2Sjpk 	}
231*45916cd2Sjpk 
232*45916cd2Sjpk 	slabel = m_label_alloc(MAC_LABEL);
233*45916cd2Sjpk 	if (slabel == NULL) {
234*45916cd2Sjpk 		free(zids);
235*45916cd2Sjpk 		return (NULL);
236*45916cd2Sjpk 	}
237*45916cd2Sjpk 
238*45916cd2Sjpk 	for (i = 0; i < nzents; i++) {
239*45916cd2Sjpk 		char	zoneroot[MAXPATHLEN];
240*45916cd2Sjpk 		int	zonerootlen;
241*45916cd2Sjpk 
242*45916cd2Sjpk 		if (zids[i] == GLOBAL_ZONEID)
243*45916cd2Sjpk 			continue;
244*45916cd2Sjpk 
245*45916cd2Sjpk 		if (zone_getattr(zids[i], ZONE_ATTR_ROOT, zoneroot,
246*45916cd2Sjpk 		    sizeof (zoneroot)) == -1)
247*45916cd2Sjpk 			continue;	/* Badly configured zone info */
248*45916cd2Sjpk 
249*45916cd2Sjpk 		/*
250*45916cd2Sjpk 		 * Need to handle the case for the /dev directory which is
251*45916cd2Sjpk 		 * parallel to the zone's root directory.  So we back up
252*45916cd2Sjpk 		 * 4 bytes - the strlen of "root".
253*45916cd2Sjpk 		 */
254*45916cd2Sjpk 		if ((zonerootlen = strlen(zoneroot)) <= 4)
255*45916cd2Sjpk 			continue;	/* Badly configured zone info */
256*45916cd2Sjpk 		if (strncmp(path, zoneroot, zonerootlen - 4) == 0) {
257*45916cd2Sjpk 			/*
258*45916cd2Sjpk 			 * If we get a match, the file is in a labeled zone.
259*45916cd2Sjpk 			 * Return the label of that zone.
260*45916cd2Sjpk 			 */
261*45916cd2Sjpk 			if (zone_getattr(zids[i], ZONE_ATTR_SLBL, slabel,
262*45916cd2Sjpk 			    sizeof (m_label_t)) < 0)
263*45916cd2Sjpk 				continue;	/* Badly configured zone info */
264*45916cd2Sjpk 
265*45916cd2Sjpk 			free(zids);
266*45916cd2Sjpk 			return (slabel);
267*45916cd2Sjpk 		}
268*45916cd2Sjpk 	}
269*45916cd2Sjpk 	free(zids);
270*45916cd2Sjpk 	bsllow(slabel);
271*45916cd2Sjpk 	return (slabel);
272*45916cd2Sjpk }
273