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, ®, 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, ®32, 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