1*9acbbeafSnn /*
2*9acbbeafSnn  * CDDL HEADER START
3*9acbbeafSnn  *
4*9acbbeafSnn  * The contents of this file are subject to the terms of the
5*9acbbeafSnn  * Common Development and Distribution License (the "License").
6*9acbbeafSnn  * You may not use this file except in compliance with the License.
7*9acbbeafSnn  *
8*9acbbeafSnn  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9acbbeafSnn  * or http://www.opensolaris.org/os/licensing.
10*9acbbeafSnn  * See the License for the specific language governing permissions
11*9acbbeafSnn  * and limitations under the License.
12*9acbbeafSnn  *
13*9acbbeafSnn  * When distributing Covered Code, include this CDDL HEADER in each
14*9acbbeafSnn  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9acbbeafSnn  * If applicable, add the following below this CDDL HEADER, with the
16*9acbbeafSnn  * fields enclosed by brackets "[]" replaced with your own identifying
17*9acbbeafSnn  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9acbbeafSnn  *
19*9acbbeafSnn  * CDDL HEADER END
20*9acbbeafSnn  */
21*9acbbeafSnn /*
22*9acbbeafSnn  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*9acbbeafSnn  * Use is subject to license terms.
24*9acbbeafSnn  */
25*9acbbeafSnn 
26*9acbbeafSnn #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*9acbbeafSnn 
28*9acbbeafSnn #include <sys/errno.h>
29*9acbbeafSnn #include <sys/exec.h>
30*9acbbeafSnn #include <sys/kmem.h>
31*9acbbeafSnn #include <sys/modctl.h>
32*9acbbeafSnn #include <sys/model.h>
33*9acbbeafSnn #include <sys/proc.h>
34*9acbbeafSnn #include <sys/syscall.h>
35*9acbbeafSnn #include <sys/systm.h>
36*9acbbeafSnn #include <sys/thread.h>
37*9acbbeafSnn #include <sys/cmn_err.h>
38*9acbbeafSnn #include <sys/archsystm.h>
39*9acbbeafSnn 
40*9acbbeafSnn #include <sys/machbrand.h>
41*9acbbeafSnn #include <sys/brand.h>
42*9acbbeafSnn #include "sn1_brand.h"
43*9acbbeafSnn 
44*9acbbeafSnn char *sn1_emulation_table = NULL;
45*9acbbeafSnn 
46*9acbbeafSnn void	sn1_setbrand(proc_t *);
47*9acbbeafSnn int	sn1_getattr(zone_t *, int, void *, size_t *);
48*9acbbeafSnn int	sn1_setattr(zone_t *, int, void *, size_t);
49*9acbbeafSnn int	sn1_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t,
50*9acbbeafSnn 		uintptr_t, uintptr_t, uintptr_t);
51*9acbbeafSnn void	sn1_copy_procdata(proc_t *, proc_t *);
52*9acbbeafSnn void	sn1_proc_exit(struct proc *, klwp_t *);
53*9acbbeafSnn void	sn1_exec();
54*9acbbeafSnn int	sn1_initlwp(klwp_t *);
55*9acbbeafSnn void	sn1_forklwp(klwp_t *, klwp_t *);
56*9acbbeafSnn void	sn1_freelwp(klwp_t *);
57*9acbbeafSnn void	sn1_lwpexit(klwp_t *);
58*9acbbeafSnn int	sn1_elfexec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int,
59*9acbbeafSnn 	long *, int, caddr_t, cred_t *, int);
60*9acbbeafSnn 
61*9acbbeafSnn /* sn1 brand */
62*9acbbeafSnn struct brand_ops sn1_brops = {
63*9acbbeafSnn 	sn1_brandsys,
64*9acbbeafSnn 	sn1_setbrand,
65*9acbbeafSnn 	sn1_getattr,
66*9acbbeafSnn 	sn1_setattr,
67*9acbbeafSnn 	sn1_copy_procdata,
68*9acbbeafSnn 	sn1_proc_exit,
69*9acbbeafSnn 	sn1_exec,
70*9acbbeafSnn 	lwp_setrval,
71*9acbbeafSnn 	sn1_initlwp,
72*9acbbeafSnn 	sn1_forklwp,
73*9acbbeafSnn 	sn1_freelwp,
74*9acbbeafSnn 	sn1_lwpexit,
75*9acbbeafSnn 	sn1_elfexec
76*9acbbeafSnn };
77*9acbbeafSnn 
78*9acbbeafSnn #ifdef	sparc
79*9acbbeafSnn 
80*9acbbeafSnn struct brand_mach_ops sn1_mops = {
81*9acbbeafSnn 	sn1_brand_syscall_callback,
82*9acbbeafSnn 	sn1_brand_syscall_callback
83*9acbbeafSnn };
84*9acbbeafSnn 
85*9acbbeafSnn #else	/* sparc */
86*9acbbeafSnn 
87*9acbbeafSnn #ifdef	__amd64
88*9acbbeafSnn 
89*9acbbeafSnn struct brand_mach_ops sn1_mops = {
90*9acbbeafSnn 	sn1_brand_sysenter_callback,
91*9acbbeafSnn 	NULL,
92*9acbbeafSnn 	sn1_brand_int91_callback,
93*9acbbeafSnn 	sn1_brand_syscall_callback,
94*9acbbeafSnn 	sn1_brand_syscall32_callback,
95*9acbbeafSnn 	NULL
96*9acbbeafSnn };
97*9acbbeafSnn 
98*9acbbeafSnn #else	/* ! __amd64 */
99*9acbbeafSnn 
100*9acbbeafSnn struct brand_mach_ops sn1_mops = {
101*9acbbeafSnn 	sn1_brand_sysenter_callback,
102*9acbbeafSnn 	NULL,
103*9acbbeafSnn 	NULL,
104*9acbbeafSnn 	sn1_brand_syscall_callback,
105*9acbbeafSnn 	NULL,
106*9acbbeafSnn 	NULL
107*9acbbeafSnn };
108*9acbbeafSnn #endif	/* __amd64 */
109*9acbbeafSnn 
110*9acbbeafSnn #endif	/* _sparc */
111*9acbbeafSnn 
112*9acbbeafSnn struct brand	sn1_brand = {
113*9acbbeafSnn 	BRAND_VER_1,
114*9acbbeafSnn 	"sn1",
115*9acbbeafSnn 	&sn1_brops,
116*9acbbeafSnn 	&sn1_mops
117*9acbbeafSnn };
118*9acbbeafSnn 
119*9acbbeafSnn static struct modlbrand modlbrand = {
120*9acbbeafSnn 	&mod_brandops, "Solaris N-1 Brand %I%", &sn1_brand
121*9acbbeafSnn };
122*9acbbeafSnn 
123*9acbbeafSnn static struct modlinkage modlinkage = {
124*9acbbeafSnn 	MODREV_1, (void *)&modlbrand, NULL
125*9acbbeafSnn };
126*9acbbeafSnn 
127*9acbbeafSnn void
128*9acbbeafSnn sn1_setbrand(proc_t *p)
129*9acbbeafSnn {
130*9acbbeafSnn 	p->p_brand_data = NULL;
131*9acbbeafSnn 	p->p_brand = &sn1_brand;
132*9acbbeafSnn }
133*9acbbeafSnn 
134*9acbbeafSnn /* ARGSUSED */
135*9acbbeafSnn int
136*9acbbeafSnn sn1_getattr(zone_t *zone, int attr, void *buf, size_t *bufsize)
137*9acbbeafSnn {
138*9acbbeafSnn 	return (EINVAL);
139*9acbbeafSnn }
140*9acbbeafSnn 
141*9acbbeafSnn /* ARGSUSED */
142*9acbbeafSnn int
143*9acbbeafSnn sn1_setattr(zone_t *zone, int attr, void *buf, size_t bufsize)
144*9acbbeafSnn {
145*9acbbeafSnn 	return (EINVAL);
146*9acbbeafSnn }
147*9acbbeafSnn 
148*9acbbeafSnn /*
149*9acbbeafSnn  * Get the address of the user-space system call handler from the user
150*9acbbeafSnn  * process and attach it to the proc structure.
151*9acbbeafSnn  */
152*9acbbeafSnn /*ARGSUSED*/
153*9acbbeafSnn int
154*9acbbeafSnn sn1_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2,
155*9acbbeafSnn     uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6)
156*9acbbeafSnn {
157*9acbbeafSnn 	proc_t *p = curproc;
158*9acbbeafSnn 	*rval = 0;
159*9acbbeafSnn 
160*9acbbeafSnn 	if (cmd == B_REGISTER) {
161*9acbbeafSnn 		p->p_brand = &sn1_brand;
162*9acbbeafSnn 		p->p_brand_data = (void *) arg1;
163*9acbbeafSnn 		return (0);
164*9acbbeafSnn 	}
165*9acbbeafSnn 
166*9acbbeafSnn 	ASSERT(p->p_brand == &sn1_brand);
167*9acbbeafSnn 
168*9acbbeafSnn 	return (EINVAL);
169*9acbbeafSnn }
170*9acbbeafSnn 
171*9acbbeafSnn /*
172*9acbbeafSnn  * Copy the per-process brand data from a parent proc to a child.  In the
173*9acbbeafSnn  * sn1 brand, the only per-process state is the address of the user-space
174*9acbbeafSnn  * handler.
175*9acbbeafSnn  */
176*9acbbeafSnn void
177*9acbbeafSnn sn1_copy_procdata(proc_t *child, proc_t *parent)
178*9acbbeafSnn {
179*9acbbeafSnn 	child->p_brand_data = parent->p_brand_data;
180*9acbbeafSnn }
181*9acbbeafSnn 
182*9acbbeafSnn /*ARGSUSED*/
183*9acbbeafSnn void
184*9acbbeafSnn sn1_proc_exit(struct proc *p, klwp_t *l)
185*9acbbeafSnn {
186*9acbbeafSnn 	p->p_brand_data = NULL;
187*9acbbeafSnn 	p->p_brand = &native_brand;
188*9acbbeafSnn }
189*9acbbeafSnn 
190*9acbbeafSnn void
191*9acbbeafSnn sn1_exec()
192*9acbbeafSnn {
193*9acbbeafSnn 	curproc->p_brand_data = NULL;
194*9acbbeafSnn }
195*9acbbeafSnn 
196*9acbbeafSnn /*ARGSUSED*/
197*9acbbeafSnn int
198*9acbbeafSnn sn1_initlwp(klwp_t *l)
199*9acbbeafSnn {
200*9acbbeafSnn 	return (0);
201*9acbbeafSnn }
202*9acbbeafSnn 
203*9acbbeafSnn /*ARGSUSED*/
204*9acbbeafSnn void
205*9acbbeafSnn sn1_forklwp(klwp_t *p, klwp_t *c)
206*9acbbeafSnn {
207*9acbbeafSnn }
208*9acbbeafSnn 
209*9acbbeafSnn /*ARGSUSED*/
210*9acbbeafSnn void
211*9acbbeafSnn sn1_freelwp(klwp_t *l)
212*9acbbeafSnn {
213*9acbbeafSnn }
214*9acbbeafSnn 
215*9acbbeafSnn /*ARGSUSED*/
216*9acbbeafSnn void
217*9acbbeafSnn sn1_lwpexit(klwp_t *l)
218*9acbbeafSnn {
219*9acbbeafSnn }
220*9acbbeafSnn 
221*9acbbeafSnn int
222*9acbbeafSnn sn1_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
223*9acbbeafSnn 	int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred,
224*9acbbeafSnn 	int brand_action)
225*9acbbeafSnn {
226*9acbbeafSnn 	args->brandname = "sn1";
227*9acbbeafSnn 	return ((args->execswp->exec_func)(vp, uap, args, idatap, level + 1,
228*9acbbeafSnn 	    execsz, setid, exec_file, cred, brand_action));
229*9acbbeafSnn }
230*9acbbeafSnn 
231*9acbbeafSnn 
232*9acbbeafSnn int
233*9acbbeafSnn _init(void)
234*9acbbeafSnn {
235*9acbbeafSnn 	int err;
236*9acbbeafSnn 
237*9acbbeafSnn #if defined(sparc) && !defined(DEBUG)
238*9acbbeafSnn 	cmn_err(CE_WARN, "The sn1 brand is only supported on DEBUG kernels.");
239*9acbbeafSnn 	return (ENOTSUP);
240*9acbbeafSnn #else
241*9acbbeafSnn 
242*9acbbeafSnn 	/*
243*9acbbeafSnn 	 * Set up the table indicating which system calls we want to
244*9acbbeafSnn 	 * interpose on.  We should probably build this automatically from
245*9acbbeafSnn 	 * a list of system calls that is shared with the user-space
246*9acbbeafSnn 	 * library.
247*9acbbeafSnn 	 */
248*9acbbeafSnn 	sn1_emulation_table = kmem_zalloc(NSYSCALL, KM_SLEEP);
249*9acbbeafSnn 	sn1_emulation_table[SYS_uname] = 1;
250*9acbbeafSnn 	sn1_emulation_table[SYS_fork1] = 1;
251*9acbbeafSnn 
252*9acbbeafSnn 	err = mod_install(&modlinkage);
253*9acbbeafSnn 	if (err) {
254*9acbbeafSnn 		cmn_err(CE_WARN, "Couldn't install brand module");
255*9acbbeafSnn 		kmem_free(sn1_emulation_table, NSYSCALL);
256*9acbbeafSnn 	}
257*9acbbeafSnn 
258*9acbbeafSnn 	return (err);
259*9acbbeafSnn #endif
260*9acbbeafSnn }
261*9acbbeafSnn 
262*9acbbeafSnn int
263*9acbbeafSnn _info(struct modinfo *modinfop)
264*9acbbeafSnn {
265*9acbbeafSnn 	return (mod_info(&modlinkage, modinfop));
266*9acbbeafSnn }
267*9acbbeafSnn 
268*9acbbeafSnn int
269*9acbbeafSnn _fini(void)
270*9acbbeafSnn {
271*9acbbeafSnn 	int err;
272*9acbbeafSnn 
273*9acbbeafSnn 	/*
274*9acbbeafSnn 	 * If there are any zones using this brand, we can't allow it to be
275*9acbbeafSnn 	 * unloaded.
276*9acbbeafSnn 	 */
277*9acbbeafSnn 	if (brand_zone_count(&sn1_brand))
278*9acbbeafSnn 		return (EBUSY);
279*9acbbeafSnn 
280*9acbbeafSnn 	kmem_free(sn1_emulation_table, NSYSCALL);
281*9acbbeafSnn 	sn1_emulation_table = NULL;
282*9acbbeafSnn 
283*9acbbeafSnn 	err = mod_remove(&modlinkage);
284*9acbbeafSnn 	if (err)
285*9acbbeafSnn 		cmn_err(CE_WARN, "Couldn't unload sn1 brand module");
286*9acbbeafSnn 
287*9acbbeafSnn 	return (err);
288*9acbbeafSnn }
289