1*1676Sjpk /*
2*1676Sjpk * CDDL HEADER START
3*1676Sjpk *
4*1676Sjpk * The contents of this file are subject to the terms of the
5*1676Sjpk * Common Development and Distribution License (the "License").
6*1676Sjpk * You may not use this file except in compliance with the License.
7*1676Sjpk *
8*1676Sjpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1676Sjpk * or http://www.opensolaris.org/os/licensing.
10*1676Sjpk * See the License for the specific language governing permissions
11*1676Sjpk * and limitations under the License.
12*1676Sjpk *
13*1676Sjpk * When distributing Covered Code, include this CDDL HEADER in each
14*1676Sjpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1676Sjpk * If applicable, add the following below this CDDL HEADER, with the
16*1676Sjpk * fields enclosed by brackets "[]" replaced with your own identifying
17*1676Sjpk * information: Portions Copyright [yyyy] [name of copyright owner]
18*1676Sjpk *
19*1676Sjpk * CDDL HEADER END
20*1676Sjpk */
21*1676Sjpk /*
22*1676Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23*1676Sjpk * Use is subject to license terms.
24*1676Sjpk */
25*1676Sjpk
26*1676Sjpk #pragma ident "%Z%%M% %I% %E% SMI"
27*1676Sjpk
28*1676Sjpk #include <stdlib.h>
29*1676Sjpk #include <strings.h>
30*1676Sjpk #include <zone.h>
31*1676Sjpk #include <errno.h>
32*1676Sjpk #include <sys/types.h>
33*1676Sjpk #include <sys/tsol/label_macro.h>
34*1676Sjpk
35*1676Sjpk /*
36*1676Sjpk * Get label from zone name
37*1676Sjpk */
38*1676Sjpk m_label_t *
getzonelabelbyname(const char * zone)39*1676Sjpk getzonelabelbyname(const char *zone)
40*1676Sjpk {
41*1676Sjpk zoneid_t zoneid;
42*1676Sjpk
43*1676Sjpk if ((zoneid = getzoneidbyname(zone)) == -1) {
44*1676Sjpk errno = EINVAL;
45*1676Sjpk return (NULL);
46*1676Sjpk }
47*1676Sjpk return (getzonelabelbyid(zoneid));
48*1676Sjpk }
49*1676Sjpk
50*1676Sjpk /*
51*1676Sjpk * Get label from zone id
52*1676Sjpk */
53*1676Sjpk m_label_t *
getzonelabelbyid(zoneid_t zoneid)54*1676Sjpk getzonelabelbyid(zoneid_t zoneid)
55*1676Sjpk {
56*1676Sjpk m_label_t *slabel;
57*1676Sjpk
58*1676Sjpk if ((slabel = m_label_alloc(MAC_LABEL)) == NULL)
59*1676Sjpk return (NULL);
60*1676Sjpk
61*1676Sjpk if (zone_getattr(zoneid, ZONE_ATTR_SLBL, slabel,
62*1676Sjpk sizeof (m_label_t)) < 0) {
63*1676Sjpk m_label_free(slabel);
64*1676Sjpk errno = EINVAL;
65*1676Sjpk return (NULL);
66*1676Sjpk }
67*1676Sjpk
68*1676Sjpk return (slabel);
69*1676Sjpk }
70*1676Sjpk
71*1676Sjpk /*
72*1676Sjpk * Get zone id from label
73*1676Sjpk */
74*1676Sjpk
75*1676Sjpk zoneid_t
getzoneidbylabel(const m_label_t * label)76*1676Sjpk getzoneidbylabel(const m_label_t *label)
77*1676Sjpk {
78*1676Sjpk m_label_t admin_low;
79*1676Sjpk m_label_t admin_high;
80*1676Sjpk zoneid_t zoneid;
81*1676Sjpk zoneid_t *zids;
82*1676Sjpk uint_t nzents;
83*1676Sjpk uint_t nzents_saved;
84*1676Sjpk int i;
85*1676Sjpk
86*1676Sjpk bsllow(&admin_low);
87*1676Sjpk bslhigh(&admin_high);
88*1676Sjpk
89*1676Sjpk /* Check for admin_low or admin_high; both are global zone */
90*1676Sjpk if (blequal(label, &admin_low) || blequal(label, &admin_high))
91*1676Sjpk return (GLOBAL_ZONEID);
92*1676Sjpk
93*1676Sjpk nzents = 0;
94*1676Sjpk if (zone_list(NULL, &nzents) != 0)
95*1676Sjpk return (-1);
96*1676Sjpk
97*1676Sjpk again:
98*1676Sjpk if (nzents == 0) {
99*1676Sjpk errno = EINVAL;
100*1676Sjpk return (-1);
101*1676Sjpk }
102*1676Sjpk
103*1676Sjpk /*
104*1676Sjpk * Add a small amount of padding here to avoid spinning in a tight loop
105*1676Sjpk * if there's a process running somewhere that's creating lots of zones
106*1676Sjpk * all at once.
107*1676Sjpk */
108*1676Sjpk nzents += 8;
109*1676Sjpk if ((zids = malloc(nzents * sizeof (zoneid_t))) == NULL)
110*1676Sjpk return (-1);
111*1676Sjpk nzents_saved = nzents;
112*1676Sjpk
113*1676Sjpk if (zone_list(zids, &nzents) != 0) {
114*1676Sjpk free(zids);
115*1676Sjpk return (-1);
116*1676Sjpk }
117*1676Sjpk if (nzents > nzents_saved) {
118*1676Sjpk /* list changed, try again */
119*1676Sjpk free(zids);
120*1676Sjpk goto again;
121*1676Sjpk }
122*1676Sjpk
123*1676Sjpk for (i = 0; i < nzents; i++) {
124*1676Sjpk m_label_t test_sl;
125*1676Sjpk
126*1676Sjpk if (zids[i] == GLOBAL_ZONEID)
127*1676Sjpk continue;
128*1676Sjpk
129*1676Sjpk if (zone_getattr(zids[i], ZONE_ATTR_SLBL, &test_sl,
130*1676Sjpk sizeof (m_label_t)) < 0)
131*1676Sjpk continue; /* Badly configured zone info */
132*1676Sjpk
133*1676Sjpk if (blequal(label, &test_sl) != 0) {
134*1676Sjpk zoneid = zids[i];
135*1676Sjpk free(zids);
136*1676Sjpk return (zoneid);
137*1676Sjpk }
138*1676Sjpk }
139*1676Sjpk free(zids);
140*1676Sjpk errno = EINVAL;
141*1676Sjpk return (-1);
142*1676Sjpk }
143*1676Sjpk
144*1676Sjpk /*
145*1676Sjpk * Get zoneroot for a zoneid
146*1676Sjpk */
147*1676Sjpk
148*1676Sjpk char *
getzonerootbyid(zoneid_t zoneid)149*1676Sjpk getzonerootbyid(zoneid_t zoneid)
150*1676Sjpk {
151*1676Sjpk char zoneroot[MAXPATHLEN];
152*1676Sjpk
153*1676Sjpk if (zone_getattr(zoneid, ZONE_ATTR_ROOT, zoneroot,
154*1676Sjpk sizeof (zoneroot)) == -1) {
155*1676Sjpk return (NULL);
156*1676Sjpk }
157*1676Sjpk
158*1676Sjpk return (strdup(zoneroot));
159*1676Sjpk }
160*1676Sjpk
161*1676Sjpk /*
162*1676Sjpk * Get zoneroot for a zonename
163*1676Sjpk */
164*1676Sjpk
165*1676Sjpk char *
getzonerootbyname(const char * zone)166*1676Sjpk getzonerootbyname(const char *zone)
167*1676Sjpk {
168*1676Sjpk zoneid_t zoneid;
169*1676Sjpk
170*1676Sjpk if ((zoneid = getzoneidbyname(zone)) == -1)
171*1676Sjpk return (NULL);
172*1676Sjpk return (getzonerootbyid(zoneid));
173*1676Sjpk }
174*1676Sjpk
175*1676Sjpk /*
176*1676Sjpk * Get zoneroot for a label
177*1676Sjpk */
178*1676Sjpk
179*1676Sjpk char *
getzonerootbylabel(const m_label_t * label)180*1676Sjpk getzonerootbylabel(const m_label_t *label)
181*1676Sjpk {
182*1676Sjpk zoneid_t zoneid;
183*1676Sjpk
184*1676Sjpk if ((zoneid = getzoneidbylabel(label)) == -1)
185*1676Sjpk return (NULL);
186*1676Sjpk return (getzonerootbyid(zoneid));
187*1676Sjpk }
188*1676Sjpk
189*1676Sjpk /*
190*1676Sjpk * Get label of path relative to global zone
191*1676Sjpk *
192*1676Sjpk * This function must be called from the global zone
193*1676Sjpk */
194*1676Sjpk
195*1676Sjpk m_label_t *
getlabelbypath(const char * path)196*1676Sjpk getlabelbypath(const char *path)
197*1676Sjpk {
198*1676Sjpk m_label_t *slabel;
199*1676Sjpk zoneid_t *zids;
200*1676Sjpk uint_t nzents;
201*1676Sjpk uint_t nzents_saved;
202*1676Sjpk int i;
203*1676Sjpk
204*1676Sjpk if (getzoneid() != GLOBAL_ZONEID) {
205*1676Sjpk errno = EINVAL;
206*1676Sjpk return (NULL);
207*1676Sjpk }
208*1676Sjpk
209*1676Sjpk nzents = 0;
210*1676Sjpk if (zone_list(NULL, &nzents) != 0)
211*1676Sjpk return (NULL);
212*1676Sjpk
213*1676Sjpk again:
214*1676Sjpk /* Add a small amount of padding to avoid loops */
215*1676Sjpk nzents += 8;
216*1676Sjpk zids = malloc(nzents * sizeof (zoneid_t));
217*1676Sjpk if (zids == NULL)
218*1676Sjpk return (NULL);
219*1676Sjpk
220*1676Sjpk nzents_saved = nzents;
221*1676Sjpk
222*1676Sjpk if (zone_list(zids, &nzents) != 0) {
223*1676Sjpk free(zids);
224*1676Sjpk return (NULL);
225*1676Sjpk }
226*1676Sjpk if (nzents > nzents_saved) {
227*1676Sjpk /* list changed, try again */
228*1676Sjpk free(zids);
229*1676Sjpk goto again;
230*1676Sjpk }
231*1676Sjpk
232*1676Sjpk slabel = m_label_alloc(MAC_LABEL);
233*1676Sjpk if (slabel == NULL) {
234*1676Sjpk free(zids);
235*1676Sjpk return (NULL);
236*1676Sjpk }
237*1676Sjpk
238*1676Sjpk for (i = 0; i < nzents; i++) {
239*1676Sjpk char zoneroot[MAXPATHLEN];
240*1676Sjpk int zonerootlen;
241*1676Sjpk
242*1676Sjpk if (zids[i] == GLOBAL_ZONEID)
243*1676Sjpk continue;
244*1676Sjpk
245*1676Sjpk if (zone_getattr(zids[i], ZONE_ATTR_ROOT, zoneroot,
246*1676Sjpk sizeof (zoneroot)) == -1)
247*1676Sjpk continue; /* Badly configured zone info */
248*1676Sjpk
249*1676Sjpk /*
250*1676Sjpk * Need to handle the case for the /dev directory which is
251*1676Sjpk * parallel to the zone's root directory. So we back up
252*1676Sjpk * 4 bytes - the strlen of "root".
253*1676Sjpk */
254*1676Sjpk if ((zonerootlen = strlen(zoneroot)) <= 4)
255*1676Sjpk continue; /* Badly configured zone info */
256*1676Sjpk if (strncmp(path, zoneroot, zonerootlen - 4) == 0) {
257*1676Sjpk /*
258*1676Sjpk * If we get a match, the file is in a labeled zone.
259*1676Sjpk * Return the label of that zone.
260*1676Sjpk */
261*1676Sjpk if (zone_getattr(zids[i], ZONE_ATTR_SLBL, slabel,
262*1676Sjpk sizeof (m_label_t)) < 0)
263*1676Sjpk continue; /* Badly configured zone info */
264*1676Sjpk
265*1676Sjpk free(zids);
266*1676Sjpk return (slabel);
267*1676Sjpk }
268*1676Sjpk }
269*1676Sjpk free(zids);
270*1676Sjpk bsllow(slabel);
271*1676Sjpk return (slabel);
272*1676Sjpk }
273