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 *
getzonelabelbyname(const char * zone)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 *
getzonelabelbyid(zoneid_t zoneid)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
getzoneidbylabel(const m_label_t * label)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 *
getzonerootbyid(zoneid_t zoneid)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 *
getzonerootbyname(const char * zone)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 *
getzonerootbylabel(const m_label_t * label)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 *
getlabelbypath(const char * path)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