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