19acbbeafSnn /*
29acbbeafSnn  * CDDL HEADER START
39acbbeafSnn  *
49acbbeafSnn  * The contents of this file are subject to the terms of the
59acbbeafSnn  * Common Development and Distribution License (the "License").
69acbbeafSnn  * You may not use this file except in compliance with the License.
79acbbeafSnn  *
89acbbeafSnn  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99acbbeafSnn  * or http://www.opensolaris.org/os/licensing.
109acbbeafSnn  * See the License for the specific language governing permissions
119acbbeafSnn  * and limitations under the License.
129acbbeafSnn  *
139acbbeafSnn  * When distributing Covered Code, include this CDDL HEADER in each
149acbbeafSnn  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159acbbeafSnn  * If applicable, add the following below this CDDL HEADER, with the
169acbbeafSnn  * fields enclosed by brackets "[]" replaced with your own identifying
179acbbeafSnn  * information: Portions Copyright [yyyy] [name of copyright owner]
189acbbeafSnn  *
199acbbeafSnn  * CDDL HEADER END
209acbbeafSnn  */
219acbbeafSnn /*
228fd04b83SRoger A. Faulkner  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
239acbbeafSnn  * Use is subject to license terms.
249acbbeafSnn  */
259acbbeafSnn 
269acbbeafSnn #include <sys/errno.h>
279acbbeafSnn #include <sys/exec.h>
289acbbeafSnn #include <sys/kmem.h>
299acbbeafSnn #include <sys/modctl.h>
309acbbeafSnn #include <sys/model.h>
319acbbeafSnn #include <sys/proc.h>
329acbbeafSnn #include <sys/syscall.h>
339acbbeafSnn #include <sys/systm.h>
349acbbeafSnn #include <sys/thread.h>
359acbbeafSnn #include <sys/cmn_err.h>
369acbbeafSnn #include <sys/archsystm.h>
37628e3cbeSEdward Pilatowicz #include <sys/pathname.h>
389acbbeafSnn 
399acbbeafSnn #include <sys/machbrand.h>
409acbbeafSnn #include <sys/brand.h>
419acbbeafSnn #include "sn1_brand.h"
429acbbeafSnn 
439acbbeafSnn char *sn1_emulation_table = NULL;
449acbbeafSnn 
45319378d9Seh void	sn1_init_brand_data(zone_t *);
46319378d9Seh void	sn1_free_brand_data(zone_t *);
479acbbeafSnn void	sn1_setbrand(proc_t *);
489acbbeafSnn int	sn1_getattr(zone_t *, int, void *, size_t *);
499acbbeafSnn int	sn1_setattr(zone_t *, int, void *, size_t);
509acbbeafSnn int	sn1_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t,
519acbbeafSnn 		uintptr_t, uintptr_t, uintptr_t);
529acbbeafSnn void	sn1_copy_procdata(proc_t *, proc_t *);
539acbbeafSnn void	sn1_proc_exit(struct proc *, klwp_t *);
549acbbeafSnn void	sn1_exec();
559acbbeafSnn int	sn1_initlwp(klwp_t *);
569acbbeafSnn void	sn1_forklwp(klwp_t *, klwp_t *);
579acbbeafSnn void	sn1_freelwp(klwp_t *);
589acbbeafSnn void	sn1_lwpexit(klwp_t *);
599acbbeafSnn int	sn1_elfexec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int,
609acbbeafSnn 	long *, int, caddr_t, cred_t *, int);
619acbbeafSnn 
629acbbeafSnn /* sn1 brand */
639acbbeafSnn struct brand_ops sn1_brops = {
64319378d9Seh 	sn1_init_brand_data,
65319378d9Seh 	sn1_free_brand_data,
669acbbeafSnn 	sn1_brandsys,
679acbbeafSnn 	sn1_setbrand,
689acbbeafSnn 	sn1_getattr,
699acbbeafSnn 	sn1_setattr,
709acbbeafSnn 	sn1_copy_procdata,
719acbbeafSnn 	sn1_proc_exit,
729acbbeafSnn 	sn1_exec,
739acbbeafSnn 	lwp_setrval,
749acbbeafSnn 	sn1_initlwp,
759acbbeafSnn 	sn1_forklwp,
769acbbeafSnn 	sn1_freelwp,
779acbbeafSnn 	sn1_lwpexit,
78eb9dbf0cSRoger A. Faulkner 	sn1_elfexec,
79*8f798d3aSRoger A. Faulkner 	NULL,
80*8f798d3aSRoger A. Faulkner 	NULL,
81*8f798d3aSRoger A. Faulkner 	NSIG,
829acbbeafSnn };
839acbbeafSnn 
849acbbeafSnn #ifdef	sparc
859acbbeafSnn 
869acbbeafSnn struct brand_mach_ops sn1_mops = {
879acbbeafSnn 	sn1_brand_syscall_callback,
88628e3cbeSEdward Pilatowicz 	sn1_brand_syscall32_callback
899acbbeafSnn };
909acbbeafSnn 
919acbbeafSnn #else	/* sparc */
929acbbeafSnn 
939acbbeafSnn #ifdef	__amd64
949acbbeafSnn 
959acbbeafSnn struct brand_mach_ops sn1_mops = {
969acbbeafSnn 	sn1_brand_sysenter_callback,
979acbbeafSnn 	NULL,
989acbbeafSnn 	sn1_brand_int91_callback,
999acbbeafSnn 	sn1_brand_syscall_callback,
1009acbbeafSnn 	sn1_brand_syscall32_callback,
1019acbbeafSnn 	NULL
1029acbbeafSnn };
1039acbbeafSnn 
1049acbbeafSnn #else	/* ! __amd64 */
1059acbbeafSnn 
1069acbbeafSnn struct brand_mach_ops sn1_mops = {
1079acbbeafSnn 	sn1_brand_sysenter_callback,
1089acbbeafSnn 	NULL,
1099acbbeafSnn 	NULL,
1109acbbeafSnn 	sn1_brand_syscall_callback,
1119acbbeafSnn 	NULL,
1129acbbeafSnn 	NULL
1139acbbeafSnn };
1149acbbeafSnn #endif	/* __amd64 */
1159acbbeafSnn 
1169acbbeafSnn #endif	/* _sparc */
1179acbbeafSnn 
1189acbbeafSnn struct brand	sn1_brand = {
1199acbbeafSnn 	BRAND_VER_1,
1209acbbeafSnn 	"sn1",
1219acbbeafSnn 	&sn1_brops,
1229acbbeafSnn 	&sn1_mops
1239acbbeafSnn };
1249acbbeafSnn 
1259acbbeafSnn static struct modlbrand modlbrand = {
126c6f42f0eSedp 	&mod_brandops,		/* type of module */
127c6f42f0eSedp 	"Solaris N-1 Brand",	/* description of module */
128c6f42f0eSedp 	&sn1_brand		/* driver ops */
1299acbbeafSnn };
1309acbbeafSnn 
1319acbbeafSnn static struct modlinkage modlinkage = {
1329acbbeafSnn 	MODREV_1, (void *)&modlbrand, NULL
1339acbbeafSnn };
1349acbbeafSnn 
1359acbbeafSnn void
1369acbbeafSnn sn1_setbrand(proc_t *p)
1379acbbeafSnn {
138fd9e7635Sedp 	ASSERT(p->p_brand == &sn1_brand);
139fd9e7635Sedp 	ASSERT(p->p_brand_data == NULL);
140fd9e7635Sedp 
141fd9e7635Sedp 	/*
142fd9e7635Sedp 	 * We should only be called from exec(), when we know the process
143fd9e7635Sedp 	 * is single-threaded.
144fd9e7635Sedp 	 */
145fd9e7635Sedp 	ASSERT(p->p_tlist == p->p_tlist->t_forw);
146628e3cbeSEdward Pilatowicz 
147628e3cbeSEdward Pilatowicz 	p->p_brand_data = kmem_zalloc(sizeof (sn1_proc_data_t), KM_SLEEP);
148fd9e7635Sedp 	(void) sn1_initlwp(p->p_tlist->t_lwp);
1499acbbeafSnn }
1509acbbeafSnn 
1519acbbeafSnn /* ARGSUSED */
1529acbbeafSnn int
1539acbbeafSnn sn1_getattr(zone_t *zone, int attr, void *buf, size_t *bufsize)
1549acbbeafSnn {
1559acbbeafSnn 	return (EINVAL);
1569acbbeafSnn }
1579acbbeafSnn 
1589acbbeafSnn /* ARGSUSED */
1599acbbeafSnn int
1609acbbeafSnn sn1_setattr(zone_t *zone, int attr, void *buf, size_t bufsize)
1619acbbeafSnn {
1629acbbeafSnn 	return (EINVAL);
1639acbbeafSnn }
1649acbbeafSnn 
1659acbbeafSnn /*
1669acbbeafSnn  * Get the address of the user-space system call handler from the user
1679acbbeafSnn  * process and attach it to the proc structure.
1689acbbeafSnn  */
1699acbbeafSnn /*ARGSUSED*/
1709acbbeafSnn int
1719acbbeafSnn sn1_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2,
1729acbbeafSnn     uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6)
1739acbbeafSnn {
174628e3cbeSEdward Pilatowicz 	sn1_proc_data_t	*spd;
175628e3cbeSEdward Pilatowicz 	sn1_brand_reg_t	reg;
176628e3cbeSEdward Pilatowicz 	proc_t		*p = curproc;
177628e3cbeSEdward Pilatowicz 	int		err;
178628e3cbeSEdward Pilatowicz 
1799acbbeafSnn 	*rval = 0;
1809acbbeafSnn 
181fd9e7635Sedp 	/*
182fd9e7635Sedp 	 * There is one operation that is suppored for non-branded
183fd9e7635Sedp 	 * process.  B_EXEC_BRAND.  This brand operaion is redundant
184fd9e7635Sedp 	 * since the kernel assumes a native process doing an exec
185fd9e7635Sedp 	 * in a branded zone is going to run a branded processes.
186fd9e7635Sedp 	 * hence we don't support this operation.
187fd9e7635Sedp 	 */
188fd9e7635Sedp 	if (cmd == B_EXEC_BRAND)
189fd9e7635Sedp 		return (ENOSYS);
190fd9e7635Sedp 
191fd9e7635Sedp 	/* For all other operations this must be a branded process. */
192fd9e7635Sedp 	if (p->p_brand == &native_brand)
193fd9e7635Sedp 		return (ENOSYS);
194fd9e7635Sedp 
195fd9e7635Sedp 	ASSERT(p->p_brand == &sn1_brand);
196628e3cbeSEdward Pilatowicz 	ASSERT(p->p_brand_data != NULL);
197628e3cbeSEdward Pilatowicz 
198628e3cbeSEdward Pilatowicz 	spd = (sn1_proc_data_t *)p->p_brand_data;
199628e3cbeSEdward Pilatowicz 
200628e3cbeSEdward Pilatowicz 	switch (cmd) {
201628e3cbeSEdward Pilatowicz 	case B_EXEC_NATIVE:
202628e3cbeSEdward Pilatowicz 		err = exec_common(
203628e3cbeSEdward Pilatowicz 		    (char *)arg1, (const char **)arg2, (const char **)arg3,
204628e3cbeSEdward Pilatowicz 		    EBA_NATIVE);
205628e3cbeSEdward Pilatowicz 		return (err);
206628e3cbeSEdward Pilatowicz 
207628e3cbeSEdward Pilatowicz 	case B_REGISTER:
208628e3cbeSEdward Pilatowicz 		if (p->p_model == DATAMODEL_NATIVE) {
209628e3cbeSEdward Pilatowicz 			if (copyin((void *)arg1, &reg, sizeof (reg)) != 0)
210628e3cbeSEdward Pilatowicz 				return (EFAULT);
211628e3cbeSEdward Pilatowicz #if defined(_LP64)
212628e3cbeSEdward Pilatowicz 		} else {
213628e3cbeSEdward Pilatowicz 			sn1_brand_reg32_t reg32;
214628e3cbeSEdward Pilatowicz 
215628e3cbeSEdward Pilatowicz 			if (copyin((void *)arg1, &reg32, sizeof (reg32)) != 0)
216628e3cbeSEdward Pilatowicz 				return (EFAULT);
217628e3cbeSEdward Pilatowicz 			reg.sbr_version = reg32.sbr_version;
218628e3cbeSEdward Pilatowicz 			reg.sbr_handler = (caddr_t)(uintptr_t)reg32.sbr_handler;
219628e3cbeSEdward Pilatowicz #endif /* _LP64 */
220628e3cbeSEdward Pilatowicz 		}
221628e3cbeSEdward Pilatowicz 
222628e3cbeSEdward Pilatowicz 		if (reg.sbr_version != SN1_VERSION)
223628e3cbeSEdward Pilatowicz 			return (ENOTSUP);
224628e3cbeSEdward Pilatowicz 		spd->spd_handler = reg.sbr_handler;
225628e3cbeSEdward Pilatowicz 		return (0);
226628e3cbeSEdward Pilatowicz 	case B_ELFDATA:
227628e3cbeSEdward Pilatowicz 		if (p->p_model == DATAMODEL_NATIVE) {
228628e3cbeSEdward Pilatowicz 			if (copyout(&spd->spd_elf_data, (void *)arg1,
229628e3cbeSEdward Pilatowicz 			    sizeof (sn1_elf_data_t)) != 0)
230628e3cbeSEdward Pilatowicz 				return (EFAULT);
231628e3cbeSEdward Pilatowicz #if defined(_LP64)
232628e3cbeSEdward Pilatowicz 		} else {
233628e3cbeSEdward Pilatowicz 			sn1_elf_data32_t sed32;
234628e3cbeSEdward Pilatowicz 
235628e3cbeSEdward Pilatowicz 			sed32.sed_phdr = spd->spd_elf_data.sed_phdr;
236628e3cbeSEdward Pilatowicz 			sed32.sed_phent = spd->spd_elf_data.sed_phent;
237628e3cbeSEdward Pilatowicz 			sed32.sed_phnum = spd->spd_elf_data.sed_phnum;
238628e3cbeSEdward Pilatowicz 			sed32.sed_entry = spd->spd_elf_data.sed_entry;
239628e3cbeSEdward Pilatowicz 			sed32.sed_base = spd->spd_elf_data.sed_base;
240628e3cbeSEdward Pilatowicz 			sed32.sed_ldentry = spd->spd_elf_data.sed_ldentry;
241628e3cbeSEdward Pilatowicz 			sed32.sed_lddata = spd->spd_elf_data.sed_lddata;
242628e3cbeSEdward Pilatowicz 			if (copyout(&sed32, (void *)arg1, sizeof (sed32)) != 0)
243628e3cbeSEdward Pilatowicz 				return (EFAULT);
244628e3cbeSEdward Pilatowicz #endif /* _LP64 */
245628e3cbeSEdward Pilatowicz 		}
2469acbbeafSnn 		return (0);
2479acbbeafSnn 	}
2489acbbeafSnn 
2499acbbeafSnn 	return (EINVAL);
2509acbbeafSnn }
2519acbbeafSnn 
2529acbbeafSnn /*
253628e3cbeSEdward Pilatowicz  * Copy the per-process brand data from a parent proc to a child.
2549acbbeafSnn  */
2559acbbeafSnn void
2569acbbeafSnn sn1_copy_procdata(proc_t *child, proc_t *parent)
2579acbbeafSnn {
258628e3cbeSEdward Pilatowicz 	sn1_proc_data_t	*spd;
259628e3cbeSEdward Pilatowicz 
260fd9e7635Sedp 	ASSERT(parent->p_brand == &sn1_brand);
261fd9e7635Sedp 	ASSERT(child->p_brand == &sn1_brand);
262628e3cbeSEdward Pilatowicz 	ASSERT(parent->p_brand_data != NULL);
263628e3cbeSEdward Pilatowicz 	ASSERT(child->p_brand_data == NULL);
264fd9e7635Sedp 
265628e3cbeSEdward Pilatowicz 	/* Just duplicate all the proc data of the parent for the child */
266628e3cbeSEdward Pilatowicz 	spd = kmem_alloc(sizeof (sn1_proc_data_t), KM_SLEEP);
267628e3cbeSEdward Pilatowicz 	bcopy(parent->p_brand_data, spd, sizeof (sn1_proc_data_t));
268628e3cbeSEdward Pilatowicz 	child->p_brand_data = spd;
2699acbbeafSnn }
2709acbbeafSnn 
2719acbbeafSnn /*ARGSUSED*/
2729acbbeafSnn void
2739acbbeafSnn sn1_proc_exit(struct proc *p, klwp_t *l)
2749acbbeafSnn {
275fd9e7635Sedp 	ASSERT(p->p_brand == &sn1_brand);
276628e3cbeSEdward Pilatowicz 	ASSERT(p->p_brand_data != NULL);
277fd9e7635Sedp 
278fd9e7635Sedp 	/*
279fd9e7635Sedp 	 * We should only be called from proc_exit(), when we know that
280fd9e7635Sedp 	 * process is single-threaded.
281fd9e7635Sedp 	 */
282fd9e7635Sedp 	ASSERT(p->p_tlist == p->p_tlist->t_forw);
283fd9e7635Sedp 
284628e3cbeSEdward Pilatowicz 	/* upon exit, free our lwp brand data */
285628e3cbeSEdward Pilatowicz 	(void) sn1_freelwp(ttolwp(curthread));
286628e3cbeSEdward Pilatowicz 
287628e3cbeSEdward Pilatowicz 	/* upon exit, free our proc brand data */
288628e3cbeSEdward Pilatowicz 	kmem_free(p->p_brand_data, sizeof (sn1_proc_data_t));
2899acbbeafSnn 	p->p_brand_data = NULL;
2909acbbeafSnn }
2919acbbeafSnn 
2929acbbeafSnn void
2939acbbeafSnn sn1_exec()
2949acbbeafSnn {
295628e3cbeSEdward Pilatowicz 	sn1_proc_data_t	*spd = curproc->p_brand_data;
296628e3cbeSEdward Pilatowicz 
297fd9e7635Sedp 	ASSERT(curproc->p_brand == &sn1_brand);
298628e3cbeSEdward Pilatowicz 	ASSERT(curproc->p_brand_data != NULL);
299fd9e7635Sedp 	ASSERT(ttolwp(curthread)->lwp_brand != NULL);
300fd9e7635Sedp 
301fd9e7635Sedp 	/*
302fd9e7635Sedp 	 * We should only be called from exec(), when we know the process
303fd9e7635Sedp 	 * is single-threaded.
304fd9e7635Sedp 	 */
305fd9e7635Sedp 	ASSERT(curproc->p_tlist == curproc->p_tlist->t_forw);
306fd9e7635Sedp 
307628e3cbeSEdward Pilatowicz 	/* Upon exec, reset our lwp brand data. */
308628e3cbeSEdward Pilatowicz 	(void) sn1_freelwp(ttolwp(curthread));
309628e3cbeSEdward Pilatowicz 	(void) sn1_initlwp(ttolwp(curthread));
310628e3cbeSEdward Pilatowicz 
311628e3cbeSEdward Pilatowicz 	/*
312628e3cbeSEdward Pilatowicz 	 * Upon exec, reset all the proc brand data, except for the elf
313628e3cbeSEdward Pilatowicz 	 * data associated with the executable we are exec'ing.
314628e3cbeSEdward Pilatowicz 	 */
315628e3cbeSEdward Pilatowicz 	spd->spd_handler = NULL;
3169acbbeafSnn }
3179acbbeafSnn 
3189acbbeafSnn /*ARGSUSED*/
3199acbbeafSnn int
3209acbbeafSnn sn1_initlwp(klwp_t *l)
3219acbbeafSnn {
322fd9e7635Sedp 	ASSERT(l->lwp_procp->p_brand == &sn1_brand);
323628e3cbeSEdward Pilatowicz 	ASSERT(l->lwp_procp->p_brand_data != NULL);
324fd9e7635Sedp 	ASSERT(l->lwp_brand == NULL);
325fd9e7635Sedp 	l->lwp_brand = (void *)-1;
3269acbbeafSnn 	return (0);
3279acbbeafSnn }
3289acbbeafSnn 
329319378d9Seh /*ARGSUSED*/
330319378d9Seh void
331fd9e7635Sedp sn1_forklwp(klwp_t *p, klwp_t *c)
332319378d9Seh {
333fd9e7635Sedp 	ASSERT(p->lwp_procp->p_brand == &sn1_brand);
334fd9e7635Sedp 	ASSERT(c->lwp_procp->p_brand == &sn1_brand);
335fd9e7635Sedp 
336628e3cbeSEdward Pilatowicz 	ASSERT(p->lwp_procp->p_brand_data != NULL);
337628e3cbeSEdward Pilatowicz 	ASSERT(c->lwp_procp->p_brand_data != NULL);
338628e3cbeSEdward Pilatowicz 
339fd9e7635Sedp 	/* Both LWPs have already had been initialized via sn1_initlwp() */
340fd9e7635Sedp 	ASSERT(p->lwp_brand != NULL);
341fd9e7635Sedp 	ASSERT(c->lwp_brand != NULL);
342319378d9Seh }
343319378d9Seh 
344319378d9Seh /*ARGSUSED*/
345319378d9Seh void
346fd9e7635Sedp sn1_freelwp(klwp_t *l)
347319378d9Seh {
348fd9e7635Sedp 	ASSERT(l->lwp_procp->p_brand == &sn1_brand);
349628e3cbeSEdward Pilatowicz 	ASSERT(l->lwp_procp->p_brand_data != NULL);
350fd9e7635Sedp 	ASSERT(l->lwp_brand != NULL);
351fd9e7635Sedp 	l->lwp_brand = NULL;
352319378d9Seh }
353319378d9Seh 
3549acbbeafSnn /*ARGSUSED*/
3559acbbeafSnn void
356fd9e7635Sedp sn1_lwpexit(klwp_t *l)
3579acbbeafSnn {
358fd9e7635Sedp 	proc_t	*p = l->lwp_procp;
359fd9e7635Sedp 
360fd9e7635Sedp 	ASSERT(l->lwp_procp->p_brand == &sn1_brand);
361628e3cbeSEdward Pilatowicz 	ASSERT(l->lwp_procp->p_brand_data != NULL);
362fd9e7635Sedp 	ASSERT(l->lwp_brand != NULL);
363fd9e7635Sedp 
364fd9e7635Sedp 	/*
365fd9e7635Sedp 	 * We should never be called for the last thread in a process.
366fd9e7635Sedp 	 * (That case is handled by sn1_proc_exit().)  There for this lwp
367fd9e7635Sedp 	 * must be exiting from a multi-threaded process.
368fd9e7635Sedp 	 */
369fd9e7635Sedp 	ASSERT(p->p_tlist != p->p_tlist->t_forw);
370fd9e7635Sedp 
371fd9e7635Sedp 	l->lwp_brand = NULL;
3729acbbeafSnn }
3739acbbeafSnn 
3749acbbeafSnn /*ARGSUSED*/
3759acbbeafSnn void
376628e3cbeSEdward Pilatowicz sn1_free_brand_data(zone_t *zone)
3779acbbeafSnn {
3789acbbeafSnn }
3799acbbeafSnn 
3809acbbeafSnn /*ARGSUSED*/
3819acbbeafSnn void
382628e3cbeSEdward Pilatowicz sn1_init_brand_data(zone_t *zone)
383628e3cbeSEdward Pilatowicz {
384628e3cbeSEdward Pilatowicz }
385628e3cbeSEdward Pilatowicz 
386628e3cbeSEdward Pilatowicz #if defined(_LP64)
387628e3cbeSEdward Pilatowicz static void
388628e3cbeSEdward Pilatowicz Ehdr32to64(Elf32_Ehdr *src, Ehdr *dst)
3899acbbeafSnn {
390628e3cbeSEdward Pilatowicz 	bcopy(src->e_ident, dst->e_ident, sizeof (src->e_ident));
391628e3cbeSEdward Pilatowicz 	dst->e_type =		src->e_type;
392628e3cbeSEdward Pilatowicz 	dst->e_machine =	src->e_machine;
393628e3cbeSEdward Pilatowicz 	dst->e_version =	src->e_version;
394628e3cbeSEdward Pilatowicz 	dst->e_entry =		src->e_entry;
395628e3cbeSEdward Pilatowicz 	dst->e_phoff =		src->e_phoff;
396628e3cbeSEdward Pilatowicz 	dst->e_shoff =		src->e_shoff;
397628e3cbeSEdward Pilatowicz 	dst->e_flags =		src->e_flags;
398628e3cbeSEdward Pilatowicz 	dst->e_ehsize =		src->e_ehsize;
399628e3cbeSEdward Pilatowicz 	dst->e_phentsize =	src->e_phentsize;
400628e3cbeSEdward Pilatowicz 	dst->e_phnum =		src->e_phnum;
401628e3cbeSEdward Pilatowicz 	dst->e_shentsize =	src->e_shentsize;
402628e3cbeSEdward Pilatowicz 	dst->e_shnum =		src->e_shnum;
403628e3cbeSEdward Pilatowicz 	dst->e_shstrndx =	src->e_shstrndx;
4049acbbeafSnn }
405628e3cbeSEdward Pilatowicz #endif /* _LP64 */
4069acbbeafSnn 
4079acbbeafSnn int
4089acbbeafSnn sn1_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
4099acbbeafSnn 	int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred,
4109acbbeafSnn 	int brand_action)
4119acbbeafSnn {
412628e3cbeSEdward Pilatowicz 	vnode_t		*nvp;
413628e3cbeSEdward Pilatowicz 	Ehdr		ehdr;
414628e3cbeSEdward Pilatowicz 	Addr		uphdr_vaddr;
415628e3cbeSEdward Pilatowicz 	intptr_t	voffset;
416628e3cbeSEdward Pilatowicz 	int		interp;
417628e3cbeSEdward Pilatowicz 	int		i, err;
418628e3cbeSEdward Pilatowicz 	struct execenv	env;
419628e3cbeSEdward Pilatowicz 	struct user	*up = PTOU(curproc);
420628e3cbeSEdward Pilatowicz 	sn1_proc_data_t	*spd;
421628e3cbeSEdward Pilatowicz 	sn1_elf_data_t	sed, *sedp;
422628e3cbeSEdward Pilatowicz 	char		*linker;
423628e3cbeSEdward Pilatowicz 	uintptr_t	lddata; /* lddata of executable's linker */
424628e3cbeSEdward Pilatowicz 
425628e3cbeSEdward Pilatowicz 	ASSERT(curproc->p_brand == &sn1_brand);
426628e3cbeSEdward Pilatowicz 	ASSERT(curproc->p_brand_data != NULL);
427628e3cbeSEdward Pilatowicz 
428628e3cbeSEdward Pilatowicz 	spd = (sn1_proc_data_t *)curproc->p_brand_data;
429628e3cbeSEdward Pilatowicz 	sedp = &spd->spd_elf_data;
430628e3cbeSEdward Pilatowicz 
431628e3cbeSEdward Pilatowicz 	args->brandname = SN1_BRANDNAME;
432628e3cbeSEdward Pilatowicz 
433628e3cbeSEdward Pilatowicz 	/*
434628e3cbeSEdward Pilatowicz 	 * We will exec the brand library and then map in the target
435628e3cbeSEdward Pilatowicz 	 * application and (optionally) the brand's default linker.
436628e3cbeSEdward Pilatowicz 	 */
437628e3cbeSEdward Pilatowicz 	if (args->to_model == DATAMODEL_NATIVE) {
438628e3cbeSEdward Pilatowicz 		args->emulator = SN1_LIB;
439628e3cbeSEdward Pilatowicz 		linker = SN1_LINKER;
440628e3cbeSEdward Pilatowicz #if defined(_LP64)
441628e3cbeSEdward Pilatowicz 	} else {
442628e3cbeSEdward Pilatowicz 		args->emulator = SN1_LIB32;
443628e3cbeSEdward Pilatowicz 		linker = SN1_LINKER32;
444628e3cbeSEdward Pilatowicz #endif /* _LP64 */
445628e3cbeSEdward Pilatowicz 	}
446628e3cbeSEdward Pilatowicz 
447628e3cbeSEdward Pilatowicz 	if ((err = lookupname(args->emulator, UIO_SYSSPACE, FOLLOW, NULLVPP,
448628e3cbeSEdward Pilatowicz 	    &nvp)) != 0) {
449628e3cbeSEdward Pilatowicz 		uprintf("%s: not found.", args->emulator);
450628e3cbeSEdward Pilatowicz 		return (err);
451628e3cbeSEdward Pilatowicz 	}
452628e3cbeSEdward Pilatowicz 
453628e3cbeSEdward Pilatowicz 	if (args->to_model == DATAMODEL_NATIVE) {
454628e3cbeSEdward Pilatowicz 		err = elfexec(nvp, uap, args, idatap, level + 1, execsz,
455628e3cbeSEdward Pilatowicz 		    setid, exec_file, cred, brand_action);
456628e3cbeSEdward Pilatowicz #if defined(_LP64)
457628e3cbeSEdward Pilatowicz 	} else {
458628e3cbeSEdward Pilatowicz 		err = elf32exec(nvp, uap, args, idatap, level + 1, execsz,
459628e3cbeSEdward Pilatowicz 		    setid, exec_file, cred, brand_action);
460628e3cbeSEdward Pilatowicz #endif /* _LP64 */
461628e3cbeSEdward Pilatowicz 	}
462628e3cbeSEdward Pilatowicz 	VN_RELE(nvp);
463628e3cbeSEdward Pilatowicz 	if (err != 0)
464628e3cbeSEdward Pilatowicz 		return (err);
465628e3cbeSEdward Pilatowicz 
466628e3cbeSEdward Pilatowicz 	/*
467628e3cbeSEdward Pilatowicz 	 * The u_auxv vectors are set up by elfexec to point to the brand
468628e3cbeSEdward Pilatowicz 	 * emulation library and linker.  Save these so they can be copied to
469628e3cbeSEdward Pilatowicz 	 * the specific brand aux vectors.
470628e3cbeSEdward Pilatowicz 	 */
471628e3cbeSEdward Pilatowicz 	bzero(&sed, sizeof (sed));
472628e3cbeSEdward Pilatowicz 	for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
473628e3cbeSEdward Pilatowicz 		switch (up->u_auxv[i].a_type) {
474628e3cbeSEdward Pilatowicz 		case AT_SUN_LDDATA:
475628e3cbeSEdward Pilatowicz 			sed.sed_lddata = up->u_auxv[i].a_un.a_val;
476628e3cbeSEdward Pilatowicz 			break;
477628e3cbeSEdward Pilatowicz 		case AT_BASE:
478628e3cbeSEdward Pilatowicz 			sed.sed_base = up->u_auxv[i].a_un.a_val;
479628e3cbeSEdward Pilatowicz 			break;
480628e3cbeSEdward Pilatowicz 		case AT_ENTRY:
481628e3cbeSEdward Pilatowicz 			sed.sed_entry = up->u_auxv[i].a_un.a_val;
482628e3cbeSEdward Pilatowicz 			break;
483628e3cbeSEdward Pilatowicz 		case AT_PHDR:
484628e3cbeSEdward Pilatowicz 			sed.sed_phdr = up->u_auxv[i].a_un.a_val;
485628e3cbeSEdward Pilatowicz 			break;
486628e3cbeSEdward Pilatowicz 		case AT_PHENT:
487628e3cbeSEdward Pilatowicz 			sed.sed_phent = up->u_auxv[i].a_un.a_val;
488628e3cbeSEdward Pilatowicz 			break;
489628e3cbeSEdward Pilatowicz 		case AT_PHNUM:
490628e3cbeSEdward Pilatowicz 			sed.sed_phnum = up->u_auxv[i].a_un.a_val;
491628e3cbeSEdward Pilatowicz 			break;
492628e3cbeSEdward Pilatowicz 		default:
493628e3cbeSEdward Pilatowicz 			break;
494628e3cbeSEdward Pilatowicz 		}
495628e3cbeSEdward Pilatowicz 	}
496628e3cbeSEdward Pilatowicz 	/* Make sure the emulator has an entry point */
497628e3cbeSEdward Pilatowicz 	ASSERT(sed.sed_entry != NULL);
498628e3cbeSEdward Pilatowicz 	ASSERT(sed.sed_phdr != NULL);
499628e3cbeSEdward Pilatowicz 
500628e3cbeSEdward Pilatowicz 	bzero(&env, sizeof (env));
501628e3cbeSEdward Pilatowicz 	if (args->to_model == DATAMODEL_NATIVE) {
502628e3cbeSEdward Pilatowicz 		err = mapexec_brand(vp, args, &ehdr, &uphdr_vaddr, &voffset,
503628e3cbeSEdward Pilatowicz 		    exec_file, &interp, &env.ex_bssbase, &env.ex_brkbase,
504628e3cbeSEdward Pilatowicz 		    &env.ex_brksize, NULL);
505628e3cbeSEdward Pilatowicz #if defined(_LP64)
506628e3cbeSEdward Pilatowicz 	} else {
507628e3cbeSEdward Pilatowicz 		Elf32_Ehdr ehdr32;
508628e3cbeSEdward Pilatowicz 		Elf32_Addr uphdr_vaddr32;
509628e3cbeSEdward Pilatowicz 		err = mapexec32_brand(vp, args, &ehdr32, &uphdr_vaddr32,
510628e3cbeSEdward Pilatowicz 		    &voffset, exec_file, &interp, &env.ex_bssbase,
511628e3cbeSEdward Pilatowicz 		    &env.ex_brkbase, &env.ex_brksize, NULL);
512628e3cbeSEdward Pilatowicz 		Ehdr32to64(&ehdr32, &ehdr);
513628e3cbeSEdward Pilatowicz 		if (uphdr_vaddr32 == (Elf32_Addr)-1)
514628e3cbeSEdward Pilatowicz 			uphdr_vaddr = (Addr)-1;
515628e3cbeSEdward Pilatowicz 		else
516628e3cbeSEdward Pilatowicz 			uphdr_vaddr = uphdr_vaddr32;
517628e3cbeSEdward Pilatowicz #endif /* _LP64 */
518628e3cbeSEdward Pilatowicz 	}
519628e3cbeSEdward Pilatowicz 	if (err != 0)
520628e3cbeSEdward Pilatowicz 		return (err);
521628e3cbeSEdward Pilatowicz 
522628e3cbeSEdward Pilatowicz 	/*
523628e3cbeSEdward Pilatowicz 	 * Save off the important properties of the executable. The brand
524628e3cbeSEdward Pilatowicz 	 * library will ask us for this data later, when it is initializing
525628e3cbeSEdward Pilatowicz 	 * and getting ready to transfer control to the brand application.
526628e3cbeSEdward Pilatowicz 	 */
527628e3cbeSEdward Pilatowicz 	if (uphdr_vaddr == (Addr)-1)
528628e3cbeSEdward Pilatowicz 		sedp->sed_phdr = voffset + ehdr.e_phoff;
529628e3cbeSEdward Pilatowicz 	else
530628e3cbeSEdward Pilatowicz 		sedp->sed_phdr = voffset + uphdr_vaddr;
531628e3cbeSEdward Pilatowicz 	sedp->sed_entry = voffset + ehdr.e_entry;
532628e3cbeSEdward Pilatowicz 	sedp->sed_phent = ehdr.e_phentsize;
533628e3cbeSEdward Pilatowicz 	sedp->sed_phnum = ehdr.e_phnum;
534628e3cbeSEdward Pilatowicz 
535628e3cbeSEdward Pilatowicz 	if (interp) {
536628e3cbeSEdward Pilatowicz 		if (ehdr.e_type == ET_DYN) {
537628e3cbeSEdward Pilatowicz 			/*
538628e3cbeSEdward Pilatowicz 			 * This is a shared object executable, so we need to
539628e3cbeSEdward Pilatowicz 			 * pick a reasonable place to put the heap. Just don't
540628e3cbeSEdward Pilatowicz 			 * use the first page.
541628e3cbeSEdward Pilatowicz 			 */
542628e3cbeSEdward Pilatowicz 			env.ex_brkbase = (caddr_t)PAGESIZE;
543628e3cbeSEdward Pilatowicz 			env.ex_bssbase = (caddr_t)PAGESIZE;
544628e3cbeSEdward Pilatowicz 		}
545628e3cbeSEdward Pilatowicz 
546628e3cbeSEdward Pilatowicz 		/*
547628e3cbeSEdward Pilatowicz 		 * If the program needs an interpreter (most do), map it in and
548628e3cbeSEdward Pilatowicz 		 * store relevant information about it in the aux vector, where
549628e3cbeSEdward Pilatowicz 		 * the brand library can find it.
550628e3cbeSEdward Pilatowicz 		 */
551628e3cbeSEdward Pilatowicz 		if ((err = lookupname(linker, UIO_SYSSPACE,
552628e3cbeSEdward Pilatowicz 		    FOLLOW, NULLVPP, &nvp)) != 0) {
553628e3cbeSEdward Pilatowicz 			uprintf("%s: not found.", SN1_LINKER);
554628e3cbeSEdward Pilatowicz 			return (err);
555628e3cbeSEdward Pilatowicz 		}
556628e3cbeSEdward Pilatowicz 		if (args->to_model == DATAMODEL_NATIVE) {
557628e3cbeSEdward Pilatowicz 			err = mapexec_brand(nvp, args, &ehdr,
558628e3cbeSEdward Pilatowicz 			    &uphdr_vaddr, &voffset, exec_file, &interp,
559628e3cbeSEdward Pilatowicz 			    NULL, NULL, NULL, &lddata);
560628e3cbeSEdward Pilatowicz #if defined(_LP64)
561628e3cbeSEdward Pilatowicz 		} else {
562628e3cbeSEdward Pilatowicz 			Elf32_Ehdr ehdr32;
563628e3cbeSEdward Pilatowicz 			Elf32_Addr uphdr_vaddr32;
564628e3cbeSEdward Pilatowicz 			err = mapexec32_brand(nvp, args, &ehdr32,
565628e3cbeSEdward Pilatowicz 			    &uphdr_vaddr32, &voffset, exec_file, &interp,
566628e3cbeSEdward Pilatowicz 			    NULL, NULL, NULL, &lddata);
567628e3cbeSEdward Pilatowicz 			Ehdr32to64(&ehdr32, &ehdr);
568628e3cbeSEdward Pilatowicz 			if (uphdr_vaddr32 == (Elf32_Addr)-1)
569628e3cbeSEdward Pilatowicz 				uphdr_vaddr = (Addr)-1;
570628e3cbeSEdward Pilatowicz 			else
571628e3cbeSEdward Pilatowicz 				uphdr_vaddr = uphdr_vaddr32;
572628e3cbeSEdward Pilatowicz #endif /* _LP64 */
573628e3cbeSEdward Pilatowicz 		}
574628e3cbeSEdward Pilatowicz 		VN_RELE(nvp);
575628e3cbeSEdward Pilatowicz 		if (err != 0)
576628e3cbeSEdward Pilatowicz 			return (err);
577628e3cbeSEdward Pilatowicz 
578628e3cbeSEdward Pilatowicz 		/*
579628e3cbeSEdward Pilatowicz 		 * Now that we know the base address of the brand's linker,
580628e3cbeSEdward Pilatowicz 		 * place it in the aux vector.
581628e3cbeSEdward Pilatowicz 		 */
582628e3cbeSEdward Pilatowicz 		sedp->sed_base = voffset;
583628e3cbeSEdward Pilatowicz 		sedp->sed_ldentry = voffset + ehdr.e_entry;
584628e3cbeSEdward Pilatowicz 		sedp->sed_lddata = voffset + lddata;
585628e3cbeSEdward Pilatowicz 	} else {
586628e3cbeSEdward Pilatowicz 		/*
587628e3cbeSEdward Pilatowicz 		 * This program has no interpreter. The brand library will
588628e3cbeSEdward Pilatowicz 		 * jump to the address in the AT_SUN_BRAND_LDENTRY aux vector,
589628e3cbeSEdward Pilatowicz 		 * so in this case, put the entry point of the main executable
590628e3cbeSEdward Pilatowicz 		 * there.
591628e3cbeSEdward Pilatowicz 		 */
592628e3cbeSEdward Pilatowicz 		if (ehdr.e_type == ET_EXEC) {
593628e3cbeSEdward Pilatowicz 			/*
594628e3cbeSEdward Pilatowicz 			 * An executable with no interpreter, this must be a
595628e3cbeSEdward Pilatowicz 			 * statically linked executable, which means we loaded
596628e3cbeSEdward Pilatowicz 			 * it at the address specified in the elf header, in
597628e3cbeSEdward Pilatowicz 			 * which case the e_entry field of the elf header is an
598628e3cbeSEdward Pilatowicz 			 * absolute address.
599628e3cbeSEdward Pilatowicz 			 */
600628e3cbeSEdward Pilatowicz 			sedp->sed_ldentry = ehdr.e_entry;
601628e3cbeSEdward Pilatowicz 			sedp->sed_entry = ehdr.e_entry;
602628e3cbeSEdward Pilatowicz 			sedp->sed_lddata = NULL;
603628e3cbeSEdward Pilatowicz 			sedp->sed_base = NULL;
604628e3cbeSEdward Pilatowicz 		} else {
605628e3cbeSEdward Pilatowicz 			/*
606628e3cbeSEdward Pilatowicz 			 * A shared object with no interpreter, we use the
607628e3cbeSEdward Pilatowicz 			 * calculated address from above.
608628e3cbeSEdward Pilatowicz 			 */
609628e3cbeSEdward Pilatowicz 			sedp->sed_ldentry = sedp->sed_entry;
610e71ca95cSGerald Jelinek 			sedp->sed_entry = NULL;
611e71ca95cSGerald Jelinek 			sedp->sed_phdr = NULL;
612e71ca95cSGerald Jelinek 			sedp->sed_phent = NULL;
613e71ca95cSGerald Jelinek 			sedp->sed_phnum = NULL;
614628e3cbeSEdward Pilatowicz 			sedp->sed_lddata = NULL;
615e71ca95cSGerald Jelinek 			sedp->sed_base = voffset;
616e71ca95cSGerald Jelinek 
617e71ca95cSGerald Jelinek 			if (ehdr.e_type == ET_DYN) {
618e71ca95cSGerald Jelinek 				/*
619e71ca95cSGerald Jelinek 				 * Delay setting the brkbase until the first
620e71ca95cSGerald Jelinek 				 * call to brk(); see elfexec() for details.
621e71ca95cSGerald Jelinek 				 */
622e71ca95cSGerald Jelinek 				env.ex_bssbase = (caddr_t)0;
623e71ca95cSGerald Jelinek 				env.ex_brkbase = (caddr_t)0;
624e71ca95cSGerald Jelinek 				env.ex_brksize = 0;
625e71ca95cSGerald Jelinek 			}
626628e3cbeSEdward Pilatowicz 		}
627628e3cbeSEdward Pilatowicz 	}
628628e3cbeSEdward Pilatowicz 
629628e3cbeSEdward Pilatowicz 	env.ex_magic = elfmagic;
630628e3cbeSEdward Pilatowicz 	env.ex_vp = vp;
631628e3cbeSEdward Pilatowicz 	setexecenv(&env);
632628e3cbeSEdward Pilatowicz 
633628e3cbeSEdward Pilatowicz 	/*
634628e3cbeSEdward Pilatowicz 	 * It's time to manipulate the process aux vectors.  First
635628e3cbeSEdward Pilatowicz 	 * we need to update the AT_SUN_AUXFLAGS aux vector to set
636628e3cbeSEdward Pilatowicz 	 * the AF_SUN_NOPLM flag.
637628e3cbeSEdward Pilatowicz 	 */
638628e3cbeSEdward Pilatowicz 	if (args->to_model == DATAMODEL_NATIVE) {
639628e3cbeSEdward Pilatowicz 		auxv_t		auxflags_auxv;
640628e3cbeSEdward Pilatowicz 
641628e3cbeSEdward Pilatowicz 		if (copyin(args->auxp_auxflags, &auxflags_auxv,
642628e3cbeSEdward Pilatowicz 		    sizeof (auxflags_auxv)) != 0)
643628e3cbeSEdward Pilatowicz 			return (EFAULT);
644628e3cbeSEdward Pilatowicz 
645628e3cbeSEdward Pilatowicz 		ASSERT(auxflags_auxv.a_type == AT_SUN_AUXFLAGS);
646628e3cbeSEdward Pilatowicz 		auxflags_auxv.a_un.a_val |= AF_SUN_NOPLM;
647628e3cbeSEdward Pilatowicz 		if (copyout(&auxflags_auxv, args->auxp_auxflags,
648628e3cbeSEdward Pilatowicz 		    sizeof (auxflags_auxv)) != 0)
649628e3cbeSEdward Pilatowicz 			return (EFAULT);
650628e3cbeSEdward Pilatowicz #if defined(_LP64)
651628e3cbeSEdward Pilatowicz 	} else {
652628e3cbeSEdward Pilatowicz 		auxv32_t	auxflags_auxv32;
653628e3cbeSEdward Pilatowicz 
654628e3cbeSEdward Pilatowicz 		if (copyin(args->auxp_auxflags, &auxflags_auxv32,
655628e3cbeSEdward Pilatowicz 		    sizeof (auxflags_auxv32)) != 0)
656628e3cbeSEdward Pilatowicz 			return (EFAULT);
657628e3cbeSEdward Pilatowicz 
658628e3cbeSEdward Pilatowicz 		ASSERT(auxflags_auxv32.a_type == AT_SUN_AUXFLAGS);
659628e3cbeSEdward Pilatowicz 		auxflags_auxv32.a_un.a_val |= AF_SUN_NOPLM;
660628e3cbeSEdward Pilatowicz 		if (copyout(&auxflags_auxv32, args->auxp_auxflags,
661628e3cbeSEdward Pilatowicz 		    sizeof (auxflags_auxv32)) != 0)
662628e3cbeSEdward Pilatowicz 			return (EFAULT);
663628e3cbeSEdward Pilatowicz #endif /* _LP64 */
664628e3cbeSEdward Pilatowicz 	}
665628e3cbeSEdward Pilatowicz 
666628e3cbeSEdward Pilatowicz 	/* Second, copy out the brand specific aux vectors. */
667628e3cbeSEdward Pilatowicz 	if (args->to_model == DATAMODEL_NATIVE) {
668628e3cbeSEdward Pilatowicz 		auxv_t sn1_auxv[] = {
669628e3cbeSEdward Pilatowicz 		    { AT_SUN_BRAND_AUX1, 0 },
670628e3cbeSEdward Pilatowicz 		    { AT_SUN_BRAND_AUX2, 0 },
671628e3cbeSEdward Pilatowicz 		    { AT_SUN_BRAND_AUX3, 0 }
672628e3cbeSEdward Pilatowicz 		};
673628e3cbeSEdward Pilatowicz 
674628e3cbeSEdward Pilatowicz 		ASSERT(sn1_auxv[0].a_type == AT_SUN_BRAND_SN1_LDDATA);
675628e3cbeSEdward Pilatowicz 		sn1_auxv[0].a_un.a_val = sed.sed_lddata;
676628e3cbeSEdward Pilatowicz 
677628e3cbeSEdward Pilatowicz 		if (copyout(&sn1_auxv, args->auxp_brand,
678628e3cbeSEdward Pilatowicz 		    sizeof (sn1_auxv)) != 0)
679628e3cbeSEdward Pilatowicz 			return (EFAULT);
680628e3cbeSEdward Pilatowicz #if defined(_LP64)
681628e3cbeSEdward Pilatowicz 	} else {
682628e3cbeSEdward Pilatowicz 		auxv32_t sn1_auxv32[] = {
683628e3cbeSEdward Pilatowicz 		    { AT_SUN_BRAND_AUX1, 0 },
684628e3cbeSEdward Pilatowicz 		    { AT_SUN_BRAND_AUX2, 0 },
685628e3cbeSEdward Pilatowicz 		    { AT_SUN_BRAND_AUX3, 0 }
686628e3cbeSEdward Pilatowicz 		};
687628e3cbeSEdward Pilatowicz 
688628e3cbeSEdward Pilatowicz 		ASSERT(sn1_auxv32[0].a_type == AT_SUN_BRAND_SN1_LDDATA);
689628e3cbeSEdward Pilatowicz 		sn1_auxv32[0].a_un.a_val = (uint32_t)sed.sed_lddata;
690628e3cbeSEdward Pilatowicz 		if (copyout(&sn1_auxv32, args->auxp_brand,
691628e3cbeSEdward Pilatowicz 		    sizeof (sn1_auxv32)) != 0)
692628e3cbeSEdward Pilatowicz 			return (EFAULT);
693628e3cbeSEdward Pilatowicz #endif /* _LP64 */
694628e3cbeSEdward Pilatowicz 	}
695628e3cbeSEdward Pilatowicz 
696628e3cbeSEdward Pilatowicz 	/*
697628e3cbeSEdward Pilatowicz 	 * Third, the the /proc aux vectors set up by elfexec() point to brand
698628e3cbeSEdward Pilatowicz 	 * emulation library and it's linker.  Copy these to the /proc brand
699628e3cbeSEdward Pilatowicz 	 * specific aux vector, and update the regular /proc aux vectors to
700628e3cbeSEdward Pilatowicz 	 * point to the executable (and it's linker).  This will enable
701628e3cbeSEdward Pilatowicz 	 * debuggers to access the executable via the usual /proc or elf notes
702628e3cbeSEdward Pilatowicz 	 * aux vectors.
703628e3cbeSEdward Pilatowicz 	 *
704628e3cbeSEdward Pilatowicz 	 * The brand emulation library's linker will get it's aux vectors off
705628e3cbeSEdward Pilatowicz 	 * the stack, and then update the stack with the executable's aux
706628e3cbeSEdward Pilatowicz 	 * vectors before jumping to the executable's linker.
707628e3cbeSEdward Pilatowicz 	 *
708628e3cbeSEdward Pilatowicz 	 * Debugging the brand emulation library must be done from
709628e3cbeSEdward Pilatowicz 	 * the global zone, where the librtld_db module knows how to fetch the
710628e3cbeSEdward Pilatowicz 	 * brand specific aux vectors to access the brand emulation libraries
711628e3cbeSEdward Pilatowicz 	 * linker.
712628e3cbeSEdward Pilatowicz 	 */
713628e3cbeSEdward Pilatowicz 	for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
714e71ca95cSGerald Jelinek 		ulong_t val;
715e71ca95cSGerald Jelinek 
716628e3cbeSEdward Pilatowicz 		switch (up->u_auxv[i].a_type) {
717628e3cbeSEdward Pilatowicz 		case AT_SUN_BRAND_SN1_LDDATA:
718628e3cbeSEdward Pilatowicz 			up->u_auxv[i].a_un.a_val = sed.sed_lddata;
719e71ca95cSGerald Jelinek 			continue;
720628e3cbeSEdward Pilatowicz 		case AT_BASE:
721e71ca95cSGerald Jelinek 			val = sedp->sed_base;
722628e3cbeSEdward Pilatowicz 			break;
723628e3cbeSEdward Pilatowicz 		case AT_ENTRY:
724e71ca95cSGerald Jelinek 			val = sedp->sed_entry;
725628e3cbeSEdward Pilatowicz 			break;
726628e3cbeSEdward Pilatowicz 		case AT_PHDR:
727e71ca95cSGerald Jelinek 			val = sedp->sed_phdr;
728628e3cbeSEdward Pilatowicz 			break;
729628e3cbeSEdward Pilatowicz 		case AT_PHENT:
730e71ca95cSGerald Jelinek 			val = sedp->sed_phent;
731628e3cbeSEdward Pilatowicz 			break;
732628e3cbeSEdward Pilatowicz 		case AT_PHNUM:
733e71ca95cSGerald Jelinek 			val = sedp->sed_phnum;
734628e3cbeSEdward Pilatowicz 			break;
735628e3cbeSEdward Pilatowicz 		case AT_SUN_LDDATA:
736e71ca95cSGerald Jelinek 			val = sedp->sed_lddata;
737628e3cbeSEdward Pilatowicz 			break;
738628e3cbeSEdward Pilatowicz 		default:
739e71ca95cSGerald Jelinek 			continue;
740e71ca95cSGerald Jelinek 		}
741e71ca95cSGerald Jelinek 
742e71ca95cSGerald Jelinek 		up->u_auxv[i].a_un.a_val = val;
743e71ca95cSGerald Jelinek 		if (val == NULL) {
744e71ca95cSGerald Jelinek 			/* Hide the entry for static binaries */
745e71ca95cSGerald Jelinek 			up->u_auxv[i].a_type = AT_IGNORE;
746628e3cbeSEdward Pilatowicz 		}
747628e3cbeSEdward Pilatowicz 	}
748628e3cbeSEdward Pilatowicz 
749628e3cbeSEdward Pilatowicz 	/*
750628e3cbeSEdward Pilatowicz 	 * The last thing we do here is clear spd->spd_handler.  This is
751628e3cbeSEdward Pilatowicz 	 * important because if we're already a branded process and if this
752628e3cbeSEdward Pilatowicz 	 * exec succeeds, there is a window between when the exec() first
753628e3cbeSEdward Pilatowicz 	 * returns to the userland of the new process and when our brand
754628e3cbeSEdward Pilatowicz 	 * library get's initialized, during which we don't want system
755628e3cbeSEdward Pilatowicz 	 * calls to be re-directed to our brand library since it hasn't
756628e3cbeSEdward Pilatowicz 	 * been initialized yet.
757628e3cbeSEdward Pilatowicz 	 */
758628e3cbeSEdward Pilatowicz 	spd->spd_handler = NULL;
759628e3cbeSEdward Pilatowicz 
760628e3cbeSEdward Pilatowicz 	return (0);
7619acbbeafSnn }
7629acbbeafSnn 
7639acbbeafSnn 
7649acbbeafSnn int
7659acbbeafSnn _init(void)
7669acbbeafSnn {
7679acbbeafSnn 	int err;
7689acbbeafSnn 
7699acbbeafSnn 	/*
7709acbbeafSnn 	 * Set up the table indicating which system calls we want to
7719acbbeafSnn 	 * interpose on.  We should probably build this automatically from
7729acbbeafSnn 	 * a list of system calls that is shared with the user-space
7739acbbeafSnn 	 * library.
7749acbbeafSnn 	 */
7759acbbeafSnn 	sn1_emulation_table = kmem_zalloc(NSYSCALL, KM_SLEEP);
776628e3cbeSEdward Pilatowicz 	sn1_emulation_table[SYS_read] = 1;			/*   3 */
777628e3cbeSEdward Pilatowicz 	sn1_emulation_table[SYS_write] = 1;			/*   4 */
778628e3cbeSEdward Pilatowicz 	sn1_emulation_table[SYS_time] = 1;			/*  13 */
779628e3cbeSEdward Pilatowicz 	sn1_emulation_table[SYS_getpid] = 1;			/*  20 */
780628e3cbeSEdward Pilatowicz 	sn1_emulation_table[SYS_mount] = 1;			/*  21 */
781628e3cbeSEdward Pilatowicz 	sn1_emulation_table[SYS_getuid] = 1;			/*  24 */
782628e3cbeSEdward Pilatowicz 	sn1_emulation_table[SYS_times] = 1;			/*  43 */
783628e3cbeSEdward Pilatowicz 	sn1_emulation_table[SYS_getgid] = 1;			/*  47 */
784628e3cbeSEdward Pilatowicz 	sn1_emulation_table[SYS_utssys] = 1;			/*  57 */
785628e3cbeSEdward Pilatowicz 	sn1_emulation_table[SYS_readlink] = 1;			/*  90 */
7868fd04b83SRoger A. Faulkner 	sn1_emulation_table[SYS_waitid] = 1;			/* 107 */
787628e3cbeSEdward Pilatowicz 	sn1_emulation_table[SYS_uname] = 1;			/* 135 */
7889acbbeafSnn 
7899acbbeafSnn 	err = mod_install(&modlinkage);
7909acbbeafSnn 	if (err) {
7919acbbeafSnn 		cmn_err(CE_WARN, "Couldn't install brand module");
7929acbbeafSnn 		kmem_free(sn1_emulation_table, NSYSCALL);
7939acbbeafSnn 	}
7949acbbeafSnn 
7959acbbeafSnn 	return (err);
7969acbbeafSnn }
7979acbbeafSnn 
7989acbbeafSnn int
7999acbbeafSnn _info(struct modinfo *modinfop)
8009acbbeafSnn {
8019acbbeafSnn 	return (mod_info(&modlinkage, modinfop));
8029acbbeafSnn }
8039acbbeafSnn 
8049acbbeafSnn int
8059acbbeafSnn _fini(void)
8069acbbeafSnn {
8079acbbeafSnn 	int err;
8089acbbeafSnn 
8099acbbeafSnn 	/*
8109acbbeafSnn 	 * If there are any zones using this brand, we can't allow it to be
8119acbbeafSnn 	 * unloaded.
8129acbbeafSnn 	 */
8139acbbeafSnn 	if (brand_zone_count(&sn1_brand))
8149acbbeafSnn 		return (EBUSY);
8159acbbeafSnn 
8169acbbeafSnn 	kmem_free(sn1_emulation_table, NSYSCALL);
8179acbbeafSnn 	sn1_emulation_table = NULL;
8189acbbeafSnn 
8199acbbeafSnn 	err = mod_remove(&modlinkage);
8209acbbeafSnn 	if (err)
8219acbbeafSnn 		cmn_err(CE_WARN, "Couldn't unload sn1 brand module");
8229acbbeafSnn 
8239acbbeafSnn 	return (err);
8249acbbeafSnn }
825