xref: /illumos-gate/usr/src/lib/libc/port/sys/zone.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #pragma weak getzoneid = _getzoneid
30*7c478bd9Sstevel@tonic-gate #pragma weak getzoneidbyname = _getzoneidbyname
31*7c478bd9Sstevel@tonic-gate #pragma weak getzonenamebyid = _getzonenamebyid
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include "synonyms.h"
34*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/syscall.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/zone.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/priv.h>
38*7c478bd9Sstevel@tonic-gate #include <zone.h>
39*7c478bd9Sstevel@tonic-gate #include <dlfcn.h>
40*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
41*7c478bd9Sstevel@tonic-gate #include <errno.h>
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate zoneid_t
44*7c478bd9Sstevel@tonic-gate zone_create(const char *name, const char *root, const priv_set_t *privs,
45*7c478bd9Sstevel@tonic-gate     const char *rctls, size_t rctlsz, int *extended_error)
46*7c478bd9Sstevel@tonic-gate {
47*7c478bd9Sstevel@tonic-gate 	zone_def  zd;
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate 	zd.zone_name = name;
50*7c478bd9Sstevel@tonic-gate 	zd.zone_root = root;
51*7c478bd9Sstevel@tonic-gate 	zd.zone_privs = privs;
52*7c478bd9Sstevel@tonic-gate 	zd.rctlbuf = rctls;
53*7c478bd9Sstevel@tonic-gate 	zd.rctlbufsz = rctlsz;
54*7c478bd9Sstevel@tonic-gate 	zd.extended_error = extended_error;
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate 	return ((zoneid_t)syscall(SYS_zone,
57*7c478bd9Sstevel@tonic-gate 	    ZONE_CREATE, &zd));
58*7c478bd9Sstevel@tonic-gate }
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate int
61*7c478bd9Sstevel@tonic-gate zone_boot(zoneid_t zoneid, const char *bootargs)
62*7c478bd9Sstevel@tonic-gate {
63*7c478bd9Sstevel@tonic-gate 	return (syscall(SYS_zone, ZONE_BOOT, zoneid, bootargs));
64*7c478bd9Sstevel@tonic-gate }
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate int
67*7c478bd9Sstevel@tonic-gate zone_shutdown(zoneid_t zoneid)
68*7c478bd9Sstevel@tonic-gate {
69*7c478bd9Sstevel@tonic-gate 	return (syscall(SYS_zone, ZONE_SHUTDOWN, zoneid));
70*7c478bd9Sstevel@tonic-gate }
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate int
73*7c478bd9Sstevel@tonic-gate zone_destroy(zoneid_t zoneid)
74*7c478bd9Sstevel@tonic-gate {
75*7c478bd9Sstevel@tonic-gate 	return (syscall(SYS_zone, ZONE_DESTROY, zoneid));
76*7c478bd9Sstevel@tonic-gate }
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate ssize_t
79*7c478bd9Sstevel@tonic-gate zone_getattr(zoneid_t zoneid, int attr, void *valp, size_t size)
80*7c478bd9Sstevel@tonic-gate {
81*7c478bd9Sstevel@tonic-gate 	sysret_t rval;
82*7c478bd9Sstevel@tonic-gate 	int error;
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate 	error = __systemcall(&rval, SYS_zone, ZONE_GETATTR, zoneid,
85*7c478bd9Sstevel@tonic-gate 	    attr, valp, size);
86*7c478bd9Sstevel@tonic-gate 	if (error)
87*7c478bd9Sstevel@tonic-gate 		(void) __set_errno(error);
88*7c478bd9Sstevel@tonic-gate 	return ((ssize_t)rval.sys_rval1);
89*7c478bd9Sstevel@tonic-gate }
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate int
92*7c478bd9Sstevel@tonic-gate zone_enter(zoneid_t zoneid)
93*7c478bd9Sstevel@tonic-gate {
94*7c478bd9Sstevel@tonic-gate 	return (syscall(SYS_zone, ZONE_ENTER, zoneid));
95*7c478bd9Sstevel@tonic-gate }
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate /*
98*7c478bd9Sstevel@tonic-gate  * Get id (if any) for specified zone.
99*7c478bd9Sstevel@tonic-gate  *
100*7c478bd9Sstevel@tonic-gate  * Call the real zone_get_id() in libzonecfg.so.1 if it can be found.
101*7c478bd9Sstevel@tonic-gate  * Otherwise, perform a stripped-down version of the function.
102*7c478bd9Sstevel@tonic-gate  * Any changes in one version should probably be reflected in the other.
103*7c478bd9Sstevel@tonic-gate  *
104*7c478bd9Sstevel@tonic-gate  * This stripped-down version of the function only checks for active
105*7c478bd9Sstevel@tonic-gate  * (booted) zones, by numeric id or name.
106*7c478bd9Sstevel@tonic-gate  */
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate typedef	int (*zone_get_id_t)(const char *, zoneid_t *);
109*7c478bd9Sstevel@tonic-gate static zone_get_id_t real_zone_get_id = NULL;
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate int
112*7c478bd9Sstevel@tonic-gate zone_get_id(const char *str, zoneid_t *zip)
113*7c478bd9Sstevel@tonic-gate {
114*7c478bd9Sstevel@tonic-gate 	zoneid_t zoneid;
115*7c478bd9Sstevel@tonic-gate 	char *cp;
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 	/*
118*7c478bd9Sstevel@tonic-gate 	 * The first time we are called, attempt to dlopen() libzonecfg.so.1
119*7c478bd9Sstevel@tonic-gate 	 * and get a pointer to the real zone_get_id().
120*7c478bd9Sstevel@tonic-gate 	 * If we fail, set our pointer to -1 so we won't try again.
121*7c478bd9Sstevel@tonic-gate 	 */
122*7c478bd9Sstevel@tonic-gate 	if (real_zone_get_id == NULL) {
123*7c478bd9Sstevel@tonic-gate 		/*
124*7c478bd9Sstevel@tonic-gate 		 * There's no harm in doing this more than once, even
125*7c478bd9Sstevel@tonic-gate 		 * concurrently.  We will get the same result each time,
126*7c478bd9Sstevel@tonic-gate 		 * and the dynamic linker will single-thread the dlopen()
127*7c478bd9Sstevel@tonic-gate 		 * with its own internal lock.  The worst that can happen
128*7c478bd9Sstevel@tonic-gate 		 * is that the handle gets a reference count greater than
129*7c478bd9Sstevel@tonic-gate 		 * one, which doesn't matter since we never dlclose()
130*7c478bd9Sstevel@tonic-gate 		 * the handle if we successfully find the symbol; the
131*7c478bd9Sstevel@tonic-gate 		 * library just stays in the address space until exit().
132*7c478bd9Sstevel@tonic-gate 		 */
133*7c478bd9Sstevel@tonic-gate 		void *dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY);
134*7c478bd9Sstevel@tonic-gate 		void *sym = (void *)(-1);
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 		if (dlhandle != NULL &&
137*7c478bd9Sstevel@tonic-gate 		    (sym = dlsym(dlhandle, "zone_get_id")) == NULL) {
138*7c478bd9Sstevel@tonic-gate 			sym = (void *)(-1);
139*7c478bd9Sstevel@tonic-gate 			(void) dlclose(dlhandle);
140*7c478bd9Sstevel@tonic-gate 		}
141*7c478bd9Sstevel@tonic-gate 		real_zone_get_id = (zone_get_id_t)sym;
142*7c478bd9Sstevel@tonic-gate 	}
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	/*
145*7c478bd9Sstevel@tonic-gate 	 * If we've successfully loaded it, call the real zone_get_id().
146*7c478bd9Sstevel@tonic-gate 	 * Otherwise, perform our stripped-down version of the code.
147*7c478bd9Sstevel@tonic-gate 	 */
148*7c478bd9Sstevel@tonic-gate 	if (real_zone_get_id != (zone_get_id_t)(-1))
149*7c478bd9Sstevel@tonic-gate 		return (real_zone_get_id(str, zip));
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 	/* first try looking for active zone by id */
152*7c478bd9Sstevel@tonic-gate 	errno = 0;
153*7c478bd9Sstevel@tonic-gate 	zoneid = (zoneid_t)strtol(str, &cp, 0);
154*7c478bd9Sstevel@tonic-gate 	if (errno == 0 && cp != str && *cp == '\0' &&
155*7c478bd9Sstevel@tonic-gate 	    getzonenamebyid(zoneid, NULL, 0) != -1) {
156*7c478bd9Sstevel@tonic-gate 		*zip = zoneid;
157*7c478bd9Sstevel@tonic-gate 		return (0);
158*7c478bd9Sstevel@tonic-gate 	}
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	/* then look for active zone by name */
161*7c478bd9Sstevel@tonic-gate 	if ((zoneid = getzoneidbyname(str)) != -1) {
162*7c478bd9Sstevel@tonic-gate 		*zip = zoneid;
163*7c478bd9Sstevel@tonic-gate 		return (0);
164*7c478bd9Sstevel@tonic-gate 	}
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	/* not an active zone, return error */
167*7c478bd9Sstevel@tonic-gate 	return (-1);
168*7c478bd9Sstevel@tonic-gate }
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate int
171*7c478bd9Sstevel@tonic-gate zone_list(zoneid_t *zonelist, uint_t *numzones)
172*7c478bd9Sstevel@tonic-gate {
173*7c478bd9Sstevel@tonic-gate 	return (syscall(SYS_zone, ZONE_LIST, zonelist, numzones));
174*7c478bd9Sstevel@tonic-gate }
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate /*
177*7c478bd9Sstevel@tonic-gate  * Underlying implementation for getzoneid and getzoneidbyname.
178*7c478bd9Sstevel@tonic-gate  */
179*7c478bd9Sstevel@tonic-gate static zoneid_t
180*7c478bd9Sstevel@tonic-gate zone_lookup(const char *name)
181*7c478bd9Sstevel@tonic-gate {
182*7c478bd9Sstevel@tonic-gate 	return ((zoneid_t)syscall(SYS_zone, ZONE_LOOKUP, name));
183*7c478bd9Sstevel@tonic-gate }
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate zoneid_t
186*7c478bd9Sstevel@tonic-gate getzoneid(void)
187*7c478bd9Sstevel@tonic-gate {
188*7c478bd9Sstevel@tonic-gate 	return (zone_lookup(NULL));
189*7c478bd9Sstevel@tonic-gate }
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate zoneid_t
192*7c478bd9Sstevel@tonic-gate getzoneidbyname(const char *zonename)
193*7c478bd9Sstevel@tonic-gate {
194*7c478bd9Sstevel@tonic-gate 	return (zone_lookup(zonename));
195*7c478bd9Sstevel@tonic-gate }
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate ssize_t
198*7c478bd9Sstevel@tonic-gate getzonenamebyid(zoneid_t zoneid, char *buf, size_t buflen)
199*7c478bd9Sstevel@tonic-gate {
200*7c478bd9Sstevel@tonic-gate 	return (zone_getattr(zoneid, ZONE_ATTR_NAME, buf, buflen));
201*7c478bd9Sstevel@tonic-gate }
202