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