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