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