xref: /illumos-gate/usr/src/lib/libtsol/common/zone.c (revision fe4627ef755b7c263f91a0e6f07cdca5d7083501)
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