12712Snn35248 /*
22712Snn35248 * CDDL HEADER START
32712Snn35248 *
42712Snn35248 * The contents of this file are subject to the terms of the
52712Snn35248 * Common Development and Distribution License (the "License").
62712Snn35248 * You may not use this file except in compliance with the License.
72712Snn35248 *
82712Snn35248 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92712Snn35248 * or http://www.opensolaris.org/os/licensing.
102712Snn35248 * See the License for the specific language governing permissions
112712Snn35248 * and limitations under the License.
122712Snn35248 *
132712Snn35248 * When distributing Covered Code, include this CDDL HEADER in each
142712Snn35248 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152712Snn35248 * If applicable, add the following below this CDDL HEADER, with the
162712Snn35248 * fields enclosed by brackets "[]" replaced with your own identifying
172712Snn35248 * information: Portions Copyright [yyyy] [name of copyright owner]
182712Snn35248 *
192712Snn35248 * CDDL HEADER END
202712Snn35248 */
212712Snn35248 /*
2212199Sgerald.jelinek@sun.com * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
232712Snn35248 */
242712Snn35248
252712Snn35248 #include <sys/kmem.h>
262712Snn35248 #include <sys/errno.h>
272712Snn35248 #include <sys/systm.h>
282712Snn35248 #include <sys/cmn_err.h>
292712Snn35248 #include <sys/brand.h>
302712Snn35248 #include <sys/machbrand.h>
312712Snn35248 #include <sys/modctl.h>
322712Snn35248 #include <sys/rwlock.h>
332712Snn35248 #include <sys/zone.h>
3412199Sgerald.jelinek@sun.com #include <sys/pathname.h>
352712Snn35248
362712Snn35248 #define SUPPORTED_BRAND_VERSION BRAND_VER_1
372712Snn35248
382712Snn35248 #if defined(__sparcv9)
394246Sedp /* sparcv9 uses system wide brand interposition hooks */
404246Sedp static void brand_plat_interposition_enable(void);
414246Sedp static void brand_plat_interposition_disable(void);
424246Sedp
432712Snn35248 struct brand_mach_ops native_mach_ops = {
442712Snn35248 NULL, NULL
452712Snn35248 };
464141Sedp #else /* !__sparcv9 */
472712Snn35248 struct brand_mach_ops native_mach_ops = {
4812613SSurya.Prakki@Sun.COM NULL, NULL, NULL, NULL
492712Snn35248 };
504141Sedp #endif /* !__sparcv9 */
512712Snn35248
522712Snn35248 brand_t native_brand = {
532712Snn35248 BRAND_VER_1,
542712Snn35248 "native",
552712Snn35248 NULL,
562712Snn35248 &native_mach_ops
572712Snn35248 };
582712Snn35248
592712Snn35248 /*
602712Snn35248 * Used to maintain a list of all the brands currently loaded into the
612712Snn35248 * kernel.
622712Snn35248 */
632712Snn35248 struct brand_list {
642712Snn35248 int bl_refcnt;
652712Snn35248 struct brand_list *bl_next;
662712Snn35248 brand_t *bl_brand;
672712Snn35248 };
682712Snn35248
692712Snn35248 static struct brand_list *brand_list = NULL;
702712Snn35248
712712Snn35248 /*
722712Snn35248 * This lock protects the integrity of the brand list.
732712Snn35248 */
742712Snn35248 static kmutex_t brand_list_lock;
752712Snn35248
762712Snn35248 void
brand_init()772712Snn35248 brand_init()
782712Snn35248 {
792712Snn35248 mutex_init(&brand_list_lock, NULL, MUTEX_DEFAULT, NULL);
802712Snn35248 p0.p_brand = &native_brand;
812712Snn35248 }
822712Snn35248
832712Snn35248 int
brand_register(brand_t * brand)842712Snn35248 brand_register(brand_t *brand)
852712Snn35248 {
862712Snn35248 struct brand_list *list, *scan;
872712Snn35248
882712Snn35248 if (brand == NULL)
892712Snn35248 return (EINVAL);
902712Snn35248
912712Snn35248 if (brand->b_version != SUPPORTED_BRAND_VERSION) {
922712Snn35248 if (brand->b_version < SUPPORTED_BRAND_VERSION) {
932712Snn35248 cmn_err(CE_WARN,
942712Snn35248 "brand '%s' was built to run on older versions "
952712Snn35248 "of Solaris.",
962712Snn35248 brand->b_name);
972712Snn35248 } else {
982712Snn35248 cmn_err(CE_WARN,
992712Snn35248 "brand '%s' was built to run on a newer version "
1002712Snn35248 "of Solaris.",
1012712Snn35248 brand->b_name);
1022712Snn35248 }
1032712Snn35248 return (EINVAL);
1042712Snn35248 }
1052712Snn35248
1062712Snn35248 /* Sanity checks */
1072712Snn35248 if (brand->b_name == NULL || brand->b_ops == NULL ||
1082712Snn35248 brand->b_ops->b_brandsys == NULL) {
1092712Snn35248 cmn_err(CE_WARN, "Malformed brand");
1102712Snn35248 return (EINVAL);
1112712Snn35248 }
1122712Snn35248
1132712Snn35248 list = kmem_alloc(sizeof (struct brand_list), KM_SLEEP);
1142712Snn35248
1152712Snn35248 /* Add the brand to the list of loaded brands. */
1162712Snn35248 mutex_enter(&brand_list_lock);
1172712Snn35248
1182712Snn35248 /*
1192712Snn35248 * Check to be sure we haven't already registered this brand.
1202712Snn35248 */
1212712Snn35248 for (scan = brand_list; scan != NULL; scan = scan->bl_next) {
1222712Snn35248 if (strcmp(brand->b_name, scan->bl_brand->b_name) == 0) {
1232712Snn35248 cmn_err(CE_WARN,
1242712Snn35248 "Invalid attempt to load a second instance of "
1252712Snn35248 "brand %s", brand->b_name);
1262712Snn35248 mutex_exit(&brand_list_lock);
1272712Snn35248 kmem_free(list, sizeof (struct brand_list));
1282712Snn35248 return (EINVAL);
1292712Snn35248 }
1302712Snn35248 }
1312712Snn35248
1324246Sedp #if defined(__sparcv9)
1334246Sedp /* sparcv9 uses system wide brand interposition hooks */
1344246Sedp if (brand_list == NULL)
1354246Sedp brand_plat_interposition_enable();
1364246Sedp #endif /* __sparcv9 */
1374246Sedp
1382712Snn35248 list->bl_brand = brand;
1392712Snn35248 list->bl_refcnt = 0;
1402712Snn35248 list->bl_next = brand_list;
1412712Snn35248 brand_list = list;
1424246Sedp
1432712Snn35248 mutex_exit(&brand_list_lock);
1442712Snn35248
1452712Snn35248 return (0);
1462712Snn35248 }
1472712Snn35248
1482712Snn35248 /*
1492712Snn35248 * The kernel module implementing this brand is being unloaded, so remove
1502712Snn35248 * it from the list of active brands.
1512712Snn35248 */
1522712Snn35248 int
brand_unregister(brand_t * brand)1532712Snn35248 brand_unregister(brand_t *brand)
1542712Snn35248 {
1552712Snn35248 struct brand_list *list, *prev;
1562712Snn35248
1572712Snn35248 /* Sanity checks */
1582712Snn35248 if (brand == NULL || brand->b_name == NULL) {
1592712Snn35248 cmn_err(CE_WARN, "Malformed brand");
1602712Snn35248 return (EINVAL);
1612712Snn35248 }
1622712Snn35248
1632712Snn35248 prev = NULL;
1642712Snn35248 mutex_enter(&brand_list_lock);
1652712Snn35248
1662712Snn35248 for (list = brand_list; list != NULL; list = list->bl_next) {
1672712Snn35248 if (list->bl_brand == brand)
1682712Snn35248 break;
1692712Snn35248 prev = list;
1702712Snn35248 }
1712712Snn35248
1722712Snn35248 if (list == NULL) {
1732712Snn35248 cmn_err(CE_WARN, "Brand %s wasn't registered", brand->b_name);
1742712Snn35248 mutex_exit(&brand_list_lock);
1752712Snn35248 return (EINVAL);
1762712Snn35248 }
1772712Snn35248
1782712Snn35248 if (list->bl_refcnt > 0) {
1792712Snn35248 cmn_err(CE_WARN, "Unregistering brand %s which is still in use",
1802712Snn35248 brand->b_name);
1812712Snn35248 mutex_exit(&brand_list_lock);
1822712Snn35248 return (EBUSY);
1832712Snn35248 }
1842712Snn35248
1852712Snn35248 /* Remove brand from the list */
1862712Snn35248 if (prev != NULL)
1872712Snn35248 prev->bl_next = list->bl_next;
1882712Snn35248 else
1892712Snn35248 brand_list = list->bl_next;
1902712Snn35248
1914246Sedp #if defined(__sparcv9)
1924246Sedp /* sparcv9 uses system wide brand interposition hooks */
1934246Sedp if (brand_list == NULL)
1944246Sedp brand_plat_interposition_disable();
1954246Sedp #endif /* __sparcv9 */
1964246Sedp
1972712Snn35248 mutex_exit(&brand_list_lock);
1982712Snn35248
1992712Snn35248 kmem_free(list, sizeof (struct brand_list));
2002712Snn35248
2012712Snn35248 return (0);
2022712Snn35248 }
2032712Snn35248
2042712Snn35248 /*
2052712Snn35248 * Record that a zone of this brand has been instantiated. If the kernel
2062712Snn35248 * module implementing this brand's functionality is not present, this
2072712Snn35248 * routine attempts to load the module as a side effect.
2082712Snn35248 */
2092712Snn35248 brand_t *
brand_register_zone(struct brand_attr * attr)2102712Snn35248 brand_register_zone(struct brand_attr *attr)
2112712Snn35248 {
2122712Snn35248 struct brand_list *l = NULL;
2132712Snn35248 ddi_modhandle_t hdl = NULL;
2142712Snn35248 char *modname;
2152712Snn35248 int err = 0;
2162712Snn35248
2172712Snn35248 if (is_system_labeled()) {
2182712Snn35248 cmn_err(CE_WARN,
2192712Snn35248 "Branded zones are not allowed on labeled systems.");
2202712Snn35248 return (NULL);
2212712Snn35248 }
2222712Snn35248
2232712Snn35248 /*
2242712Snn35248 * We make at most two passes through this loop. The first time
2252712Snn35248 * through, we're looking to see if this is a new user of an
2262712Snn35248 * already loaded brand. If the brand hasn't been loaded, we
2272712Snn35248 * call ddi_modopen() to force it to be loaded and then make a
2282712Snn35248 * second pass through the list of brands. If we don't find the
2292712Snn35248 * brand the second time through it means that the modname
2302712Snn35248 * specified in the brand_attr structure doesn't provide the brand
2312712Snn35248 * specified in the brandname field. This would suggest a bug in
2322712Snn35248 * the brand's config.xml file. We close the module and return
2332712Snn35248 * 'NULL' to the caller.
2342712Snn35248 */
2352712Snn35248 for (;;) {
2362712Snn35248 /*
2372712Snn35248 * Search list of loaded brands
2382712Snn35248 */
2392712Snn35248 mutex_enter(&brand_list_lock);
2402712Snn35248 for (l = brand_list; l != NULL; l = l->bl_next)
2412712Snn35248 if (strcmp(attr->ba_brandname,
2422712Snn35248 l->bl_brand->b_name) == 0)
2432712Snn35248 break;
2442712Snn35248 if ((l != NULL) || (hdl != NULL))
2452712Snn35248 break;
2462712Snn35248 mutex_exit(&brand_list_lock);
2472712Snn35248
2482712Snn35248 /*
2492712Snn35248 * We didn't find that the requested brand has been loaded
2502712Snn35248 * yet, so we trigger the load of the appropriate kernel
2512712Snn35248 * module and search the list again.
2522712Snn35248 */
2532712Snn35248 modname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
2542712Snn35248 (void) strcpy(modname, "brand/");
2552712Snn35248 (void) strcat(modname, attr->ba_modname);
2562712Snn35248 hdl = ddi_modopen(modname, KRTLD_MODE_FIRST, &err);
2572712Snn35248 kmem_free(modname, MAXPATHLEN);
2582712Snn35248
2592712Snn35248 if (err != 0)
2602712Snn35248 return (NULL);
2612712Snn35248 }
2622712Snn35248
2632712Snn35248 /*
2642712Snn35248 * If we found the matching brand, bump its reference count.
2652712Snn35248 */
2662712Snn35248 if (l != NULL)
2672712Snn35248 l->bl_refcnt++;
2682712Snn35248
2692712Snn35248 mutex_exit(&brand_list_lock);
2702712Snn35248
2712712Snn35248 if (hdl != NULL)
2722712Snn35248 (void) ddi_modclose(hdl);
2732712Snn35248
2742712Snn35248 return ((l != NULL) ? l->bl_brand : NULL);
2752712Snn35248 }
2762712Snn35248
2772712Snn35248 /*
2782712Snn35248 * Return the number of zones currently using this brand.
2792712Snn35248 */
2802712Snn35248 int
brand_zone_count(struct brand * bp)2812712Snn35248 brand_zone_count(struct brand *bp)
2822712Snn35248 {
2832712Snn35248 struct brand_list *l;
2842712Snn35248 int cnt = 0;
2852712Snn35248
2862712Snn35248 mutex_enter(&brand_list_lock);
2872712Snn35248 for (l = brand_list; l != NULL; l = l->bl_next)
2882712Snn35248 if (l->bl_brand == bp) {
2892712Snn35248 cnt = l->bl_refcnt;
2902712Snn35248 break;
2912712Snn35248 }
2922712Snn35248 mutex_exit(&brand_list_lock);
2932712Snn35248
2942712Snn35248 return (cnt);
2952712Snn35248 }
2962712Snn35248
2972712Snn35248 void
brand_unregister_zone(struct brand * bp)2982712Snn35248 brand_unregister_zone(struct brand *bp)
2992712Snn35248 {
3002712Snn35248 struct brand_list *list;
3012712Snn35248
3022712Snn35248 mutex_enter(&brand_list_lock);
3032712Snn35248 for (list = brand_list; list != NULL; list = list->bl_next) {
3042712Snn35248 if (list->bl_brand == bp) {
3052712Snn35248 ASSERT(list->bl_refcnt > 0);
3062712Snn35248 list->bl_refcnt--;
3072712Snn35248 break;
3082712Snn35248 }
3092712Snn35248 }
3102712Snn35248 mutex_exit(&brand_list_lock);
3112712Snn35248 }
3122712Snn35248
3132712Snn35248 void
brand_setbrand(proc_t * p)3142712Snn35248 brand_setbrand(proc_t *p)
3152712Snn35248 {
3162712Snn35248 brand_t *bp = p->p_zone->zone_brand;
3172712Snn35248
3182712Snn35248 ASSERT(bp != NULL);
3192712Snn35248 ASSERT(p->p_brand == &native_brand);
3202712Snn35248
3212712Snn35248 /*
3222712Snn35248 * We should only be called from exec(), when we know the process
3232712Snn35248 * is single-threaded.
3242712Snn35248 */
3252712Snn35248 ASSERT(p->p_tlist == p->p_tlist->t_forw);
3262712Snn35248
3272712Snn35248 p->p_brand = bp;
3286994Sedp ASSERT(PROC_IS_BRANDED(p));
3296994Sedp BROP(p)->b_setbrand(p);
3306994Sedp }
3316994Sedp
3326994Sedp void
brand_clearbrand(proc_t * p,boolean_t no_lwps)333*13045SVamsi.Krishna@Sun.COM brand_clearbrand(proc_t *p, boolean_t no_lwps)
3346994Sedp {
3356994Sedp brand_t *bp = p->p_zone->zone_brand;
336*13045SVamsi.Krishna@Sun.COM klwp_t *lwp = NULL;
3376994Sedp ASSERT(bp != NULL);
338*13045SVamsi.Krishna@Sun.COM ASSERT(!no_lwps || (p->p_tlist == NULL));
3396994Sedp
3406994Sedp /*
341*13045SVamsi.Krishna@Sun.COM * If called from exec_common() or proc_exit(),
342*13045SVamsi.Krishna@Sun.COM * we know the process is single-threaded.
343*13045SVamsi.Krishna@Sun.COM * If called from fork_fail, p_tlist is NULL.
3446994Sedp */
345*13045SVamsi.Krishna@Sun.COM if (!no_lwps) {
346*13045SVamsi.Krishna@Sun.COM ASSERT(p->p_tlist == p->p_tlist->t_forw);
347*13045SVamsi.Krishna@Sun.COM lwp = p->p_tlist->t_lwp;
348*13045SVamsi.Krishna@Sun.COM }
3496994Sedp
3506994Sedp ASSERT(PROC_IS_BRANDED(p));
351*13045SVamsi.Krishna@Sun.COM BROP(p)->b_proc_exit(p, lwp);
3526994Sedp p->p_brand = &native_brand;
3532712Snn35248 }
3544141Sedp
3554141Sedp #if defined(__sparcv9)
3564141Sedp /*
3574246Sedp * Currently, only sparc has system level brand syscall interposition.
3584141Sedp * On x86 we're able to enable syscall interposition on a per-cpu basis
3594141Sedp * when a branded thread is scheduled to run on a cpu.
3604141Sedp */
3614141Sedp
3624141Sedp /* Local variables needed for dynamic syscall interposition support */
3634141Sedp static uint32_t syscall_trap_patch_instr_orig;
3644141Sedp static uint32_t syscall_trap32_patch_instr_orig;
3654141Sedp
3664141Sedp /* Trap Table syscall entry hot patch points */
3674141Sedp extern void syscall_trap_patch_point(void);
3684141Sedp extern void syscall_trap32_patch_point(void);
3694141Sedp
3704141Sedp /* Alternate syscall entry handlers used when branded zones are running */
3714141Sedp extern void syscall_wrapper(void);
3724141Sedp extern void syscall_wrapper32(void);
3734141Sedp
3744141Sedp /* Macros used to facilitate sparcv9 instruction generation */
3754141Sedp #define BA_A_INSTR 0x30800000 /* ba,a addr */
3764141Sedp #define DISP22(from, to) \
3774141Sedp ((((uintptr_t)(to) - (uintptr_t)(from)) >> 2) & 0x3fffff)
3784141Sedp
3794246Sedp /*ARGSUSED*/
3804246Sedp static void
brand_plat_interposition_enable(void)3814246Sedp brand_plat_interposition_enable(void)
3824141Sedp {
3834246Sedp ASSERT(MUTEX_HELD(&brand_list_lock));
3844141Sedp
3854141Sedp /*
3864141Sedp * Before we hot patch the kernel save the current instructions
3874246Sedp * so that we can restore them later.
3884141Sedp */
3894141Sedp syscall_trap_patch_instr_orig =
3904141Sedp *(uint32_t *)syscall_trap_patch_point;
3914141Sedp syscall_trap32_patch_instr_orig =
3924141Sedp *(uint32_t *)syscall_trap32_patch_point;
3934141Sedp
3944141Sedp /*
3954141Sedp * Modify the trap table at the patch points.
3964141Sedp *
3974141Sedp * We basically replace the first instruction at the patch
3984141Sedp * point with a ba,a instruction that will transfer control
3994141Sedp * to syscall_wrapper or syscall_wrapper32 for 64-bit and
4004141Sedp * 32-bit syscalls respectively. It's important to note that
4014141Sedp * the annul bit is set in the branch so we don't execute
4024141Sedp * the instruction directly following the one we're patching
4034141Sedp * during the branch's delay slot.
4044141Sedp *
4054141Sedp * It also doesn't matter that we're not atomically updating both
4064141Sedp * the 64 and 32 bit syscall paths at the same time since there's
4074141Sedp * no actual branded processes running on the system yet.
4084141Sedp */
4094141Sedp hot_patch_kernel_text((caddr_t)syscall_trap_patch_point,
4104141Sedp BA_A_INSTR | DISP22(syscall_trap_patch_point, syscall_wrapper),
4114141Sedp 4);
4124141Sedp hot_patch_kernel_text((caddr_t)syscall_trap32_patch_point,
4134141Sedp BA_A_INSTR | DISP22(syscall_trap32_patch_point, syscall_wrapper32),
4144141Sedp 4);
4154141Sedp }
4164141Sedp
4174141Sedp /*ARGSUSED*/
4184246Sedp static void
brand_plat_interposition_disable(void)4194246Sedp brand_plat_interposition_disable(void)
4204141Sedp {
4214246Sedp ASSERT(MUTEX_HELD(&brand_list_lock));
4224141Sedp
4234141Sedp /*
4244141Sedp * Restore the original instructions at the trap table syscall
4254141Sedp * patch points to disable the brand syscall interposition
4264141Sedp * mechanism.
4274141Sedp */
4284141Sedp hot_patch_kernel_text((caddr_t)syscall_trap_patch_point,
4294141Sedp syscall_trap_patch_instr_orig, 4);
4304141Sedp hot_patch_kernel_text((caddr_t)syscall_trap32_patch_point,
4314141Sedp syscall_trap32_patch_instr_orig, 4);
4324141Sedp }
4334141Sedp #endif /* __sparcv9 */
43412199Sgerald.jelinek@sun.com
43512199Sgerald.jelinek@sun.com /*
43612199Sgerald.jelinek@sun.com * The following functions can be shared among kernel brand modules which
43712199Sgerald.jelinek@sun.com * implement Solaris-derived brands, all of which need to do similar tasks
43812199Sgerald.jelinek@sun.com * to manage the brand.
43912199Sgerald.jelinek@sun.com */
44012199Sgerald.jelinek@sun.com
44112199Sgerald.jelinek@sun.com #if defined(_LP64)
44212199Sgerald.jelinek@sun.com static void
Ehdr32to64(Elf32_Ehdr * src,Ehdr * dst)44312199Sgerald.jelinek@sun.com Ehdr32to64(Elf32_Ehdr *src, Ehdr *dst)
44412199Sgerald.jelinek@sun.com {
44512199Sgerald.jelinek@sun.com bcopy(src->e_ident, dst->e_ident, sizeof (src->e_ident));
44612199Sgerald.jelinek@sun.com dst->e_type = src->e_type;
44712199Sgerald.jelinek@sun.com dst->e_machine = src->e_machine;
44812199Sgerald.jelinek@sun.com dst->e_version = src->e_version;
44912199Sgerald.jelinek@sun.com dst->e_entry = src->e_entry;
45012199Sgerald.jelinek@sun.com dst->e_phoff = src->e_phoff;
45112199Sgerald.jelinek@sun.com dst->e_shoff = src->e_shoff;
45212199Sgerald.jelinek@sun.com dst->e_flags = src->e_flags;
45312199Sgerald.jelinek@sun.com dst->e_ehsize = src->e_ehsize;
45412199Sgerald.jelinek@sun.com dst->e_phentsize = src->e_phentsize;
45512199Sgerald.jelinek@sun.com dst->e_phnum = src->e_phnum;
45612199Sgerald.jelinek@sun.com dst->e_shentsize = src->e_shentsize;
45712199Sgerald.jelinek@sun.com dst->e_shnum = src->e_shnum;
45812199Sgerald.jelinek@sun.com dst->e_shstrndx = src->e_shstrndx;
45912199Sgerald.jelinek@sun.com }
46012199Sgerald.jelinek@sun.com #endif /* _LP64 */
46112199Sgerald.jelinek@sun.com
46212199Sgerald.jelinek@sun.com /*
46312199Sgerald.jelinek@sun.com * Return -1 if the cmd was not handled by this function.
46412199Sgerald.jelinek@sun.com */
46512199Sgerald.jelinek@sun.com /*ARGSUSED*/
46612199Sgerald.jelinek@sun.com int
brand_solaris_cmd(int cmd,uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,struct brand * pbrand,int brandvers)46712199Sgerald.jelinek@sun.com brand_solaris_cmd(int cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3,
46812199Sgerald.jelinek@sun.com struct brand *pbrand, int brandvers)
46912199Sgerald.jelinek@sun.com {
47012199Sgerald.jelinek@sun.com brand_proc_data_t *spd;
47112199Sgerald.jelinek@sun.com brand_proc_reg_t reg;
47212199Sgerald.jelinek@sun.com proc_t *p = curproc;
47312199Sgerald.jelinek@sun.com int err;
47412199Sgerald.jelinek@sun.com
47512199Sgerald.jelinek@sun.com /*
47612199Sgerald.jelinek@sun.com * There is one operation that is supported for a native
47712199Sgerald.jelinek@sun.com * process; B_EXEC_BRAND. This brand operaion is redundant
47812199Sgerald.jelinek@sun.com * since the kernel assumes a native process doing an exec
47912199Sgerald.jelinek@sun.com * in a branded zone is going to run a branded processes.
48012199Sgerald.jelinek@sun.com * hence we don't support this operation.
48112199Sgerald.jelinek@sun.com */
48212199Sgerald.jelinek@sun.com if (cmd == B_EXEC_BRAND)
48312199Sgerald.jelinek@sun.com return (ENOSYS);
48412199Sgerald.jelinek@sun.com
48512199Sgerald.jelinek@sun.com /* For all other operations this must be a branded process. */
48612199Sgerald.jelinek@sun.com if (p->p_brand == &native_brand)
48712199Sgerald.jelinek@sun.com return (ENOSYS);
48812199Sgerald.jelinek@sun.com
48912199Sgerald.jelinek@sun.com ASSERT(p->p_brand == pbrand);
49012199Sgerald.jelinek@sun.com ASSERT(p->p_brand_data != NULL);
49112199Sgerald.jelinek@sun.com
49212199Sgerald.jelinek@sun.com spd = (brand_proc_data_t *)p->p_brand_data;
49312199Sgerald.jelinek@sun.com
49412199Sgerald.jelinek@sun.com switch ((cmd)) {
49512199Sgerald.jelinek@sun.com case B_EXEC_NATIVE:
49612199Sgerald.jelinek@sun.com err = exec_common((char *)arg1, (const char **)arg2,
49712199Sgerald.jelinek@sun.com (const char **)arg3, EBA_NATIVE);
49812199Sgerald.jelinek@sun.com return (err);
49912199Sgerald.jelinek@sun.com
50012199Sgerald.jelinek@sun.com /*
50112199Sgerald.jelinek@sun.com * Get the address of the user-space system call handler from
50212199Sgerald.jelinek@sun.com * the user process and attach it to the proc structure.
50312199Sgerald.jelinek@sun.com */
50412199Sgerald.jelinek@sun.com case B_REGISTER:
50512199Sgerald.jelinek@sun.com if (p->p_model == DATAMODEL_NATIVE) {
50612199Sgerald.jelinek@sun.com if (copyin((void *)arg1, ®, sizeof (reg)) != 0)
50712199Sgerald.jelinek@sun.com return (EFAULT);
50812199Sgerald.jelinek@sun.com }
50912199Sgerald.jelinek@sun.com #if defined(_LP64)
51012199Sgerald.jelinek@sun.com else {
51112199Sgerald.jelinek@sun.com brand_common_reg32_t reg32;
51212199Sgerald.jelinek@sun.com
51312199Sgerald.jelinek@sun.com if (copyin((void *)arg1, ®32, sizeof (reg32)) != 0)
51412199Sgerald.jelinek@sun.com return (EFAULT);
51512199Sgerald.jelinek@sun.com reg.sbr_version = reg32.sbr_version;
51612199Sgerald.jelinek@sun.com reg.sbr_handler = (caddr_t)(uintptr_t)reg32.sbr_handler;
51712199Sgerald.jelinek@sun.com }
51812199Sgerald.jelinek@sun.com #endif /* _LP64 */
51912199Sgerald.jelinek@sun.com
52012199Sgerald.jelinek@sun.com if (reg.sbr_version != brandvers)
52112199Sgerald.jelinek@sun.com return (ENOTSUP);
52212199Sgerald.jelinek@sun.com spd->spd_handler = reg.sbr_handler;
52312199Sgerald.jelinek@sun.com return (0);
52412199Sgerald.jelinek@sun.com
52512199Sgerald.jelinek@sun.com case B_ELFDATA:
52612199Sgerald.jelinek@sun.com if (p->p_model == DATAMODEL_NATIVE) {
52712199Sgerald.jelinek@sun.com if (copyout(&spd->spd_elf_data, (void *)arg1,
52812199Sgerald.jelinek@sun.com sizeof (brand_elf_data_t)) != 0)
52912199Sgerald.jelinek@sun.com return (EFAULT);
53012199Sgerald.jelinek@sun.com }
53112199Sgerald.jelinek@sun.com #if defined(_LP64)
53212199Sgerald.jelinek@sun.com else {
53312199Sgerald.jelinek@sun.com brand_elf_data32_t sed32;
53412199Sgerald.jelinek@sun.com
53512199Sgerald.jelinek@sun.com sed32.sed_phdr = spd->spd_elf_data.sed_phdr;
53612199Sgerald.jelinek@sun.com sed32.sed_phent = spd->spd_elf_data.sed_phent;
53712199Sgerald.jelinek@sun.com sed32.sed_phnum = spd->spd_elf_data.sed_phnum;
53812199Sgerald.jelinek@sun.com sed32.sed_entry = spd->spd_elf_data.sed_entry;
53912199Sgerald.jelinek@sun.com sed32.sed_base = spd->spd_elf_data.sed_base;
54012199Sgerald.jelinek@sun.com sed32.sed_ldentry = spd->spd_elf_data.sed_ldentry;
54112199Sgerald.jelinek@sun.com sed32.sed_lddata = spd->spd_elf_data.sed_lddata;
54212199Sgerald.jelinek@sun.com if (copyout(&sed32, (void *)arg1, sizeof (sed32))
54312199Sgerald.jelinek@sun.com != 0)
54412199Sgerald.jelinek@sun.com return (EFAULT);
54512199Sgerald.jelinek@sun.com }
54612199Sgerald.jelinek@sun.com #endif /* _LP64 */
54712199Sgerald.jelinek@sun.com return (0);
54812199Sgerald.jelinek@sun.com
54912199Sgerald.jelinek@sun.com /*
55012199Sgerald.jelinek@sun.com * The B_TRUSS_POINT subcommand exists so that we can see
55112199Sgerald.jelinek@sun.com * truss output from interposed system calls that return
55212199Sgerald.jelinek@sun.com * without first calling any other system call, meaning they
55312199Sgerald.jelinek@sun.com * would be invisible to truss(1).
55412199Sgerald.jelinek@sun.com * If the second argument is set non-zero, set errno to that
55512199Sgerald.jelinek@sun.com * value as well.
55612199Sgerald.jelinek@sun.com *
55712199Sgerald.jelinek@sun.com * Common arguments seen with truss are:
55812199Sgerald.jelinek@sun.com *
55912199Sgerald.jelinek@sun.com * arg1: syscall number
56012199Sgerald.jelinek@sun.com * arg2: errno
56112199Sgerald.jelinek@sun.com */
56212199Sgerald.jelinek@sun.com case B_TRUSS_POINT:
56312199Sgerald.jelinek@sun.com return ((arg2 == 0) ? 0 : set_errno((uint_t)arg2));
56412199Sgerald.jelinek@sun.com }
56512199Sgerald.jelinek@sun.com
56612199Sgerald.jelinek@sun.com return (-1);
56712199Sgerald.jelinek@sun.com }
56812199Sgerald.jelinek@sun.com
56912199Sgerald.jelinek@sun.com /*ARGSUSED*/
57012199Sgerald.jelinek@sun.com void
brand_solaris_copy_procdata(proc_t * child,proc_t * parent,struct brand * pbrand)57112199Sgerald.jelinek@sun.com brand_solaris_copy_procdata(proc_t *child, proc_t *parent, struct brand *pbrand)
57212199Sgerald.jelinek@sun.com {
57312199Sgerald.jelinek@sun.com brand_proc_data_t *spd;
57412199Sgerald.jelinek@sun.com
57512199Sgerald.jelinek@sun.com ASSERT(parent->p_brand == pbrand);
57612199Sgerald.jelinek@sun.com ASSERT(child->p_brand == pbrand);
57712199Sgerald.jelinek@sun.com ASSERT(parent->p_brand_data != NULL);
57812199Sgerald.jelinek@sun.com ASSERT(child->p_brand_data == NULL);
57912199Sgerald.jelinek@sun.com
58012199Sgerald.jelinek@sun.com /*
58112199Sgerald.jelinek@sun.com * Just duplicate all the proc data of the parent for the
58212199Sgerald.jelinek@sun.com * child
58312199Sgerald.jelinek@sun.com */
58412199Sgerald.jelinek@sun.com spd = kmem_alloc(sizeof (brand_proc_data_t), KM_SLEEP);
58512199Sgerald.jelinek@sun.com bcopy(parent->p_brand_data, spd, sizeof (brand_proc_data_t));
58612199Sgerald.jelinek@sun.com child->p_brand_data = spd;
58712199Sgerald.jelinek@sun.com }
58812199Sgerald.jelinek@sun.com
58912621Sgerald.jelinek@sun.com static void
restoreexecenv(struct execenv * ep,stack_t * sp)59012621Sgerald.jelinek@sun.com restoreexecenv(struct execenv *ep, stack_t *sp)
59112621Sgerald.jelinek@sun.com {
59212621Sgerald.jelinek@sun.com klwp_t *lwp = ttolwp(curthread);
59312621Sgerald.jelinek@sun.com
59412621Sgerald.jelinek@sun.com setexecenv(ep);
59512621Sgerald.jelinek@sun.com lwp->lwp_sigaltstack.ss_sp = sp->ss_sp;
59612621Sgerald.jelinek@sun.com lwp->lwp_sigaltstack.ss_size = sp->ss_size;
59712621Sgerald.jelinek@sun.com lwp->lwp_sigaltstack.ss_flags = sp->ss_flags;
59812621Sgerald.jelinek@sun.com }
59912621Sgerald.jelinek@sun.com
60012199Sgerald.jelinek@sun.com /*ARGSUSED*/
60112199Sgerald.jelinek@sun.com int
brand_solaris_elfexec(vnode_t * vp,execa_t * uap,uarg_t * args,intpdata_t * idatap,int level,long * execsz,int setid,caddr_t exec_file,cred_t * cred,int brand_action,struct brand * pbrand,char * bname,char * brandlib,char * brandlib32,char * brandlinker,char * brandlinker32)60212199Sgerald.jelinek@sun.com brand_solaris_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args,
60312199Sgerald.jelinek@sun.com intpdata_t *idatap, int level, long *execsz, int setid, caddr_t exec_file,
60412199Sgerald.jelinek@sun.com cred_t *cred, int brand_action, struct brand *pbrand, char *bname,
60512199Sgerald.jelinek@sun.com char *brandlib, char *brandlib32, char *brandlinker, char *brandlinker32)
60612199Sgerald.jelinek@sun.com {
60712199Sgerald.jelinek@sun.com
60812199Sgerald.jelinek@sun.com vnode_t *nvp;
60912199Sgerald.jelinek@sun.com Ehdr ehdr;
61012199Sgerald.jelinek@sun.com Addr uphdr_vaddr;
61112199Sgerald.jelinek@sun.com intptr_t voffset;
61212199Sgerald.jelinek@sun.com int interp;
61312199Sgerald.jelinek@sun.com int i, err;
61412199Sgerald.jelinek@sun.com struct execenv env;
61512621Sgerald.jelinek@sun.com struct execenv origenv;
61612621Sgerald.jelinek@sun.com stack_t orig_sigaltstack;
61712199Sgerald.jelinek@sun.com struct user *up = PTOU(curproc);
61812621Sgerald.jelinek@sun.com proc_t *p = ttoproc(curthread);
61912621Sgerald.jelinek@sun.com klwp_t *lwp = ttolwp(curthread);
62012199Sgerald.jelinek@sun.com brand_proc_data_t *spd;
62112199Sgerald.jelinek@sun.com brand_elf_data_t sed, *sedp;
62212199Sgerald.jelinek@sun.com char *linker;
62312199Sgerald.jelinek@sun.com uintptr_t lddata; /* lddata of executable's linker */
62412199Sgerald.jelinek@sun.com
62512199Sgerald.jelinek@sun.com ASSERT(curproc->p_brand == pbrand);
62612199Sgerald.jelinek@sun.com ASSERT(curproc->p_brand_data != NULL);
62712199Sgerald.jelinek@sun.com
62812199Sgerald.jelinek@sun.com spd = (brand_proc_data_t *)curproc->p_brand_data;
62912199Sgerald.jelinek@sun.com sedp = &spd->spd_elf_data;
63012199Sgerald.jelinek@sun.com
63112199Sgerald.jelinek@sun.com args->brandname = bname;
63212199Sgerald.jelinek@sun.com
63312199Sgerald.jelinek@sun.com /*
63412199Sgerald.jelinek@sun.com * We will exec the brand library and then map in the target
63512199Sgerald.jelinek@sun.com * application and (optionally) the brand's default linker.
63612199Sgerald.jelinek@sun.com */
63712199Sgerald.jelinek@sun.com if (args->to_model == DATAMODEL_NATIVE) {
63812199Sgerald.jelinek@sun.com args->emulator = brandlib;
63912199Sgerald.jelinek@sun.com linker = brandlinker;
64012199Sgerald.jelinek@sun.com }
64112199Sgerald.jelinek@sun.com #if defined(_LP64)
64212199Sgerald.jelinek@sun.com else {
64312199Sgerald.jelinek@sun.com args->emulator = brandlib32;
64412199Sgerald.jelinek@sun.com linker = brandlinker32;
64512199Sgerald.jelinek@sun.com }
64612199Sgerald.jelinek@sun.com #endif /* _LP64 */
64712199Sgerald.jelinek@sun.com
64812199Sgerald.jelinek@sun.com if ((err = lookupname(args->emulator, UIO_SYSSPACE, FOLLOW,
64912199Sgerald.jelinek@sun.com NULLVPP, &nvp)) != 0) {
65012199Sgerald.jelinek@sun.com uprintf("%s: not found.", args->emulator);
65112199Sgerald.jelinek@sun.com return (err);
65212199Sgerald.jelinek@sun.com }
65312199Sgerald.jelinek@sun.com
65412621Sgerald.jelinek@sun.com /*
65512621Sgerald.jelinek@sun.com * The following elf{32}exec call changes the execenv in the proc
65612621Sgerald.jelinek@sun.com * struct which includes changing the p_exec member to be the vnode
65712621Sgerald.jelinek@sun.com * for the brand library (e.g. /.SUNWnative/usr/lib/s10_brand.so.1).
65812621Sgerald.jelinek@sun.com * We will eventually set the p_exec member to be the vnode for the new
65912621Sgerald.jelinek@sun.com * executable when we call setexecenv(). However, if we get an error
66012621Sgerald.jelinek@sun.com * before that call we need to restore the execenv to its original
66112621Sgerald.jelinek@sun.com * values so that when we return to the caller fop_close() works
66212621Sgerald.jelinek@sun.com * properly while cleaning up from the failed exec(). Restoring the
66312621Sgerald.jelinek@sun.com * original value will also properly decrement the 2nd VN_RELE that we
66412621Sgerald.jelinek@sun.com * took on the brand library.
66512621Sgerald.jelinek@sun.com */
66612621Sgerald.jelinek@sun.com origenv.ex_bssbase = p->p_bssbase;
66712621Sgerald.jelinek@sun.com origenv.ex_brkbase = p->p_brkbase;
66812621Sgerald.jelinek@sun.com origenv.ex_brksize = p->p_brksize;
66912621Sgerald.jelinek@sun.com origenv.ex_vp = p->p_exec;
67012621Sgerald.jelinek@sun.com orig_sigaltstack.ss_sp = lwp->lwp_sigaltstack.ss_sp;
67112621Sgerald.jelinek@sun.com orig_sigaltstack.ss_size = lwp->lwp_sigaltstack.ss_size;
67212621Sgerald.jelinek@sun.com orig_sigaltstack.ss_flags = lwp->lwp_sigaltstack.ss_flags;
67312621Sgerald.jelinek@sun.com
67412199Sgerald.jelinek@sun.com if (args->to_model == DATAMODEL_NATIVE) {
67512199Sgerald.jelinek@sun.com err = elfexec(nvp, uap, args, idatap, level + 1, execsz,
67612199Sgerald.jelinek@sun.com setid, exec_file, cred, brand_action);
67712199Sgerald.jelinek@sun.com }
67812199Sgerald.jelinek@sun.com #if defined(_LP64)
67912199Sgerald.jelinek@sun.com else {
68012199Sgerald.jelinek@sun.com err = elf32exec(nvp, uap, args, idatap, level + 1, execsz,
68112199Sgerald.jelinek@sun.com setid, exec_file, cred, brand_action);
68212199Sgerald.jelinek@sun.com }
68312199Sgerald.jelinek@sun.com #endif /* _LP64 */
68412199Sgerald.jelinek@sun.com VN_RELE(nvp);
68512621Sgerald.jelinek@sun.com if (err != 0) {
68612621Sgerald.jelinek@sun.com restoreexecenv(&origenv, &orig_sigaltstack);
68712199Sgerald.jelinek@sun.com return (err);
68812621Sgerald.jelinek@sun.com }
68912199Sgerald.jelinek@sun.com
69012199Sgerald.jelinek@sun.com /*
69112199Sgerald.jelinek@sun.com * The u_auxv veCTors are set up by elfexec to point to the
69212199Sgerald.jelinek@sun.com * brand emulation library and linker. Save these so they can
69312199Sgerald.jelinek@sun.com * be copied to the specific brand aux vectors.
69412199Sgerald.jelinek@sun.com */
69512199Sgerald.jelinek@sun.com bzero(&sed, sizeof (sed));
69612199Sgerald.jelinek@sun.com for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
69712199Sgerald.jelinek@sun.com switch (up->u_auxv[i].a_type) {
69812199Sgerald.jelinek@sun.com case AT_SUN_LDDATA:
69912199Sgerald.jelinek@sun.com sed.sed_lddata = up->u_auxv[i].a_un.a_val;
70012199Sgerald.jelinek@sun.com break;
70112199Sgerald.jelinek@sun.com case AT_BASE:
70212199Sgerald.jelinek@sun.com sed.sed_base = up->u_auxv[i].a_un.a_val;
70312199Sgerald.jelinek@sun.com break;
70412199Sgerald.jelinek@sun.com case AT_ENTRY:
70512199Sgerald.jelinek@sun.com sed.sed_entry = up->u_auxv[i].a_un.a_val;
70612199Sgerald.jelinek@sun.com break;
70712199Sgerald.jelinek@sun.com case AT_PHDR:
70812199Sgerald.jelinek@sun.com sed.sed_phdr = up->u_auxv[i].a_un.a_val;
70912199Sgerald.jelinek@sun.com break;
71012199Sgerald.jelinek@sun.com case AT_PHENT:
71112199Sgerald.jelinek@sun.com sed.sed_phent = up->u_auxv[i].a_un.a_val;
71212199Sgerald.jelinek@sun.com break;
71312199Sgerald.jelinek@sun.com case AT_PHNUM:
71412199Sgerald.jelinek@sun.com sed.sed_phnum = up->u_auxv[i].a_un.a_val;
71512199Sgerald.jelinek@sun.com break;
71612199Sgerald.jelinek@sun.com default:
71712199Sgerald.jelinek@sun.com break;
71812199Sgerald.jelinek@sun.com }
71912199Sgerald.jelinek@sun.com }
72012199Sgerald.jelinek@sun.com /* Make sure the emulator has an entry point */
72112199Sgerald.jelinek@sun.com ASSERT(sed.sed_entry != NULL);
72212199Sgerald.jelinek@sun.com ASSERT(sed.sed_phdr != NULL);
72312199Sgerald.jelinek@sun.com
72412199Sgerald.jelinek@sun.com bzero(&env, sizeof (env));
72512199Sgerald.jelinek@sun.com if (args->to_model == DATAMODEL_NATIVE) {
72612199Sgerald.jelinek@sun.com err = mapexec_brand(vp, args, &ehdr, &uphdr_vaddr,
72712199Sgerald.jelinek@sun.com &voffset, exec_file, &interp, &env.ex_bssbase,
72812199Sgerald.jelinek@sun.com &env.ex_brkbase, &env.ex_brksize, NULL);
72912199Sgerald.jelinek@sun.com }
73012199Sgerald.jelinek@sun.com #if defined(_LP64)
73112199Sgerald.jelinek@sun.com else {
73212199Sgerald.jelinek@sun.com Elf32_Ehdr ehdr32;
73312199Sgerald.jelinek@sun.com Elf32_Addr uphdr_vaddr32;
73412199Sgerald.jelinek@sun.com err = mapexec32_brand(vp, args, &ehdr32, &uphdr_vaddr32,
73512199Sgerald.jelinek@sun.com &voffset, exec_file, &interp, &env.ex_bssbase,
73612199Sgerald.jelinek@sun.com &env.ex_brkbase, &env.ex_brksize, NULL);
73712199Sgerald.jelinek@sun.com Ehdr32to64(&ehdr32, &ehdr);
73812199Sgerald.jelinek@sun.com
73912199Sgerald.jelinek@sun.com if (uphdr_vaddr32 == (Elf32_Addr)-1)
74012199Sgerald.jelinek@sun.com uphdr_vaddr = (Addr)-1;
74112199Sgerald.jelinek@sun.com else
74212199Sgerald.jelinek@sun.com uphdr_vaddr = uphdr_vaddr32;
74312199Sgerald.jelinek@sun.com }
74412199Sgerald.jelinek@sun.com #endif /* _LP64 */
74512621Sgerald.jelinek@sun.com if (err != 0) {
74612621Sgerald.jelinek@sun.com restoreexecenv(&origenv, &orig_sigaltstack);
74712199Sgerald.jelinek@sun.com return (err);
74812621Sgerald.jelinek@sun.com }
74912199Sgerald.jelinek@sun.com
75012199Sgerald.jelinek@sun.com /*
75112199Sgerald.jelinek@sun.com * Save off the important properties of the executable. The
75212199Sgerald.jelinek@sun.com * brand library will ask us for this data later, when it is
75312199Sgerald.jelinek@sun.com * initializing and getting ready to transfer control to the
75412199Sgerald.jelinek@sun.com * brand application.
75512199Sgerald.jelinek@sun.com */
75612199Sgerald.jelinek@sun.com if (uphdr_vaddr == (Addr)-1)
75712199Sgerald.jelinek@sun.com sedp->sed_phdr = voffset + ehdr.e_phoff;
75812199Sgerald.jelinek@sun.com else
75912199Sgerald.jelinek@sun.com sedp->sed_phdr = voffset + uphdr_vaddr;
76012199Sgerald.jelinek@sun.com sedp->sed_entry = voffset + ehdr.e_entry;
76112199Sgerald.jelinek@sun.com sedp->sed_phent = ehdr.e_phentsize;
76212199Sgerald.jelinek@sun.com sedp->sed_phnum = ehdr.e_phnum;
76312199Sgerald.jelinek@sun.com
76412199Sgerald.jelinek@sun.com if (interp) {
76512199Sgerald.jelinek@sun.com if (ehdr.e_type == ET_DYN) {
76612199Sgerald.jelinek@sun.com /*
76712199Sgerald.jelinek@sun.com * This is a shared object executable, so we
76812199Sgerald.jelinek@sun.com * need to pick a reasonable place to put the
76912199Sgerald.jelinek@sun.com * heap. Just don't use the first page.
77012199Sgerald.jelinek@sun.com */
77112199Sgerald.jelinek@sun.com env.ex_brkbase = (caddr_t)PAGESIZE;
77212199Sgerald.jelinek@sun.com env.ex_bssbase = (caddr_t)PAGESIZE;
77312199Sgerald.jelinek@sun.com }
77412199Sgerald.jelinek@sun.com
77512199Sgerald.jelinek@sun.com /*
77612199Sgerald.jelinek@sun.com * If the program needs an interpreter (most do), map
77712199Sgerald.jelinek@sun.com * it in and store relevant information about it in the
77812199Sgerald.jelinek@sun.com * aux vector, where the brand library can find it.
77912199Sgerald.jelinek@sun.com */
78012199Sgerald.jelinek@sun.com if ((err = lookupname(linker, UIO_SYSSPACE,
78112199Sgerald.jelinek@sun.com FOLLOW, NULLVPP, &nvp)) != 0) {
78212199Sgerald.jelinek@sun.com uprintf("%s: not found.", brandlinker);
78312621Sgerald.jelinek@sun.com restoreexecenv(&origenv, &orig_sigaltstack);
78412199Sgerald.jelinek@sun.com return (err);
78512199Sgerald.jelinek@sun.com }
78612199Sgerald.jelinek@sun.com if (args->to_model == DATAMODEL_NATIVE) {
78712199Sgerald.jelinek@sun.com err = mapexec_brand(nvp, args, &ehdr,
78812199Sgerald.jelinek@sun.com &uphdr_vaddr, &voffset, exec_file, &interp,
78912199Sgerald.jelinek@sun.com NULL, NULL, NULL, &lddata);
79012199Sgerald.jelinek@sun.com }
79112199Sgerald.jelinek@sun.com #if defined(_LP64)
79212199Sgerald.jelinek@sun.com else {
79312199Sgerald.jelinek@sun.com Elf32_Ehdr ehdr32;
79412199Sgerald.jelinek@sun.com Elf32_Addr uphdr_vaddr32;
79512199Sgerald.jelinek@sun.com err = mapexec32_brand(nvp, args, &ehdr32,
79612199Sgerald.jelinek@sun.com &uphdr_vaddr32, &voffset, exec_file, &interp,
79712199Sgerald.jelinek@sun.com NULL, NULL, NULL, &lddata);
79812199Sgerald.jelinek@sun.com Ehdr32to64(&ehdr32, &ehdr);
79912199Sgerald.jelinek@sun.com
80012199Sgerald.jelinek@sun.com if (uphdr_vaddr32 == (Elf32_Addr)-1)
80112199Sgerald.jelinek@sun.com uphdr_vaddr = (Addr)-1;
80212199Sgerald.jelinek@sun.com else
80312199Sgerald.jelinek@sun.com uphdr_vaddr = uphdr_vaddr32;
80412199Sgerald.jelinek@sun.com }
80512199Sgerald.jelinek@sun.com #endif /* _LP64 */
80612199Sgerald.jelinek@sun.com VN_RELE(nvp);
80712621Sgerald.jelinek@sun.com if (err != 0) {
80812621Sgerald.jelinek@sun.com restoreexecenv(&origenv, &orig_sigaltstack);
80912199Sgerald.jelinek@sun.com return (err);
81012621Sgerald.jelinek@sun.com }
81112199Sgerald.jelinek@sun.com
81212199Sgerald.jelinek@sun.com /*
81312199Sgerald.jelinek@sun.com * Now that we know the base address of the brand's
81412199Sgerald.jelinek@sun.com * linker, place it in the aux vector.
81512199Sgerald.jelinek@sun.com */
81612199Sgerald.jelinek@sun.com sedp->sed_base = voffset;
81712199Sgerald.jelinek@sun.com sedp->sed_ldentry = voffset + ehdr.e_entry;
81812199Sgerald.jelinek@sun.com sedp->sed_lddata = voffset + lddata;
81912199Sgerald.jelinek@sun.com } else {
82012199Sgerald.jelinek@sun.com /*
82112199Sgerald.jelinek@sun.com * This program has no interpreter. The brand library
82212199Sgerald.jelinek@sun.com * will jump to the address in the AT_SUN_BRAND_LDENTRY
82312199Sgerald.jelinek@sun.com * aux vector, so in this case, put the entry point of
82412199Sgerald.jelinek@sun.com * the main executable there.
82512199Sgerald.jelinek@sun.com */
82612199Sgerald.jelinek@sun.com if (ehdr.e_type == ET_EXEC) {
82712199Sgerald.jelinek@sun.com /*
82812199Sgerald.jelinek@sun.com * An executable with no interpreter, this must
82912199Sgerald.jelinek@sun.com * be a statically linked executable, which
83012199Sgerald.jelinek@sun.com * means we loaded it at the address specified
83112199Sgerald.jelinek@sun.com * in the elf header, in which case the e_entry
83212199Sgerald.jelinek@sun.com * field of the elf header is an absolute
83312199Sgerald.jelinek@sun.com * address.
83412199Sgerald.jelinek@sun.com */
83512199Sgerald.jelinek@sun.com sedp->sed_ldentry = ehdr.e_entry;
83612199Sgerald.jelinek@sun.com sedp->sed_entry = ehdr.e_entry;
83712199Sgerald.jelinek@sun.com sedp->sed_lddata = NULL;
83812199Sgerald.jelinek@sun.com sedp->sed_base = NULL;
83912199Sgerald.jelinek@sun.com } else {
84012199Sgerald.jelinek@sun.com /*
84112199Sgerald.jelinek@sun.com * A shared object with no interpreter, we use
84212199Sgerald.jelinek@sun.com * the calculated address from above.
84312199Sgerald.jelinek@sun.com */
84412199Sgerald.jelinek@sun.com sedp->sed_ldentry = sedp->sed_entry;
84512199Sgerald.jelinek@sun.com sedp->sed_entry = NULL;
84612199Sgerald.jelinek@sun.com sedp->sed_phdr = NULL;
84712199Sgerald.jelinek@sun.com sedp->sed_phent = NULL;
84812199Sgerald.jelinek@sun.com sedp->sed_phnum = NULL;
84912199Sgerald.jelinek@sun.com sedp->sed_lddata = NULL;
85012199Sgerald.jelinek@sun.com sedp->sed_base = voffset;
85112199Sgerald.jelinek@sun.com
85212199Sgerald.jelinek@sun.com if (ehdr.e_type == ET_DYN) {
85312199Sgerald.jelinek@sun.com /*
85412199Sgerald.jelinek@sun.com * Delay setting the brkbase until the
85512199Sgerald.jelinek@sun.com * first call to brk(); see elfexec()
85612199Sgerald.jelinek@sun.com * for details.
85712199Sgerald.jelinek@sun.com */
85812199Sgerald.jelinek@sun.com env.ex_bssbase = (caddr_t)0;
85912199Sgerald.jelinek@sun.com env.ex_brkbase = (caddr_t)0;
86012199Sgerald.jelinek@sun.com env.ex_brksize = 0;
86112199Sgerald.jelinek@sun.com }
86212199Sgerald.jelinek@sun.com }
86312199Sgerald.jelinek@sun.com }
86412199Sgerald.jelinek@sun.com
86512199Sgerald.jelinek@sun.com env.ex_magic = elfmagic;
86612199Sgerald.jelinek@sun.com env.ex_vp = vp;
86712199Sgerald.jelinek@sun.com setexecenv(&env);
86812199Sgerald.jelinek@sun.com
86912199Sgerald.jelinek@sun.com /*
87012199Sgerald.jelinek@sun.com * It's time to manipulate the process aux vectors. First
87112199Sgerald.jelinek@sun.com * we need to update the AT_SUN_AUXFLAGS aux vector to set
87212199Sgerald.jelinek@sun.com * the AF_SUN_NOPLM flag.
87312199Sgerald.jelinek@sun.com */
87412199Sgerald.jelinek@sun.com if (args->to_model == DATAMODEL_NATIVE) {
87512199Sgerald.jelinek@sun.com auxv_t auxflags_auxv;
87612199Sgerald.jelinek@sun.com
87712199Sgerald.jelinek@sun.com if (copyin(args->auxp_auxflags, &auxflags_auxv,
87812199Sgerald.jelinek@sun.com sizeof (auxflags_auxv)) != 0)
87912199Sgerald.jelinek@sun.com return (EFAULT);
88012199Sgerald.jelinek@sun.com
88112199Sgerald.jelinek@sun.com ASSERT(auxflags_auxv.a_type == AT_SUN_AUXFLAGS);
88212199Sgerald.jelinek@sun.com auxflags_auxv.a_un.a_val |= AF_SUN_NOPLM;
88312199Sgerald.jelinek@sun.com if (copyout(&auxflags_auxv, args->auxp_auxflags,
88412199Sgerald.jelinek@sun.com sizeof (auxflags_auxv)) != 0)
88512199Sgerald.jelinek@sun.com return (EFAULT);
88612199Sgerald.jelinek@sun.com }
88712199Sgerald.jelinek@sun.com #if defined(_LP64)
88812199Sgerald.jelinek@sun.com else {
88912199Sgerald.jelinek@sun.com auxv32_t auxflags_auxv32;
89012199Sgerald.jelinek@sun.com
89112199Sgerald.jelinek@sun.com if (copyin(args->auxp_auxflags, &auxflags_auxv32,
89212199Sgerald.jelinek@sun.com sizeof (auxflags_auxv32)) != 0)
89312199Sgerald.jelinek@sun.com return (EFAULT);
89412199Sgerald.jelinek@sun.com
89512199Sgerald.jelinek@sun.com ASSERT(auxflags_auxv32.a_type == AT_SUN_AUXFLAGS);
89612199Sgerald.jelinek@sun.com auxflags_auxv32.a_un.a_val |= AF_SUN_NOPLM;
89712199Sgerald.jelinek@sun.com if (copyout(&auxflags_auxv32, args->auxp_auxflags,
89812199Sgerald.jelinek@sun.com sizeof (auxflags_auxv32)) != 0)
89912199Sgerald.jelinek@sun.com return (EFAULT);
90012199Sgerald.jelinek@sun.com }
90112199Sgerald.jelinek@sun.com #endif /* _LP64 */
90212199Sgerald.jelinek@sun.com
90312199Sgerald.jelinek@sun.com /* Second, copy out the brand specific aux vectors. */
90412199Sgerald.jelinek@sun.com if (args->to_model == DATAMODEL_NATIVE) {
90512199Sgerald.jelinek@sun.com auxv_t brand_auxv[] = {
90612199Sgerald.jelinek@sun.com { AT_SUN_BRAND_AUX1, 0 },
90712199Sgerald.jelinek@sun.com { AT_SUN_BRAND_AUX2, 0 },
90812199Sgerald.jelinek@sun.com { AT_SUN_BRAND_AUX3, 0 }
90912199Sgerald.jelinek@sun.com };
91012199Sgerald.jelinek@sun.com
91112199Sgerald.jelinek@sun.com ASSERT(brand_auxv[0].a_type ==
91212199Sgerald.jelinek@sun.com AT_SUN_BRAND_COMMON_LDDATA);
91312199Sgerald.jelinek@sun.com brand_auxv[0].a_un.a_val = sed.sed_lddata;
91412199Sgerald.jelinek@sun.com
91512199Sgerald.jelinek@sun.com if (copyout(&brand_auxv, args->auxp_brand,
91612199Sgerald.jelinek@sun.com sizeof (brand_auxv)) != 0)
91712199Sgerald.jelinek@sun.com return (EFAULT);
91812199Sgerald.jelinek@sun.com }
91912199Sgerald.jelinek@sun.com #if defined(_LP64)
92012199Sgerald.jelinek@sun.com else {
92112199Sgerald.jelinek@sun.com auxv32_t brand_auxv32[] = {
92212199Sgerald.jelinek@sun.com { AT_SUN_BRAND_AUX1, 0 },
92312199Sgerald.jelinek@sun.com { AT_SUN_BRAND_AUX2, 0 },
92412199Sgerald.jelinek@sun.com { AT_SUN_BRAND_AUX3, 0 }
92512199Sgerald.jelinek@sun.com };
92612199Sgerald.jelinek@sun.com
92712199Sgerald.jelinek@sun.com ASSERT(brand_auxv32[0].a_type == AT_SUN_BRAND_COMMON_LDDATA);
92812199Sgerald.jelinek@sun.com brand_auxv32[0].a_un.a_val = (uint32_t)sed.sed_lddata;
92912199Sgerald.jelinek@sun.com if (copyout(&brand_auxv32, args->auxp_brand,
93012199Sgerald.jelinek@sun.com sizeof (brand_auxv32)) != 0)
93112199Sgerald.jelinek@sun.com return (EFAULT);
93212199Sgerald.jelinek@sun.com }
93312199Sgerald.jelinek@sun.com #endif /* _LP64 */
93412199Sgerald.jelinek@sun.com
93512199Sgerald.jelinek@sun.com /*
93612199Sgerald.jelinek@sun.com * Third, the /proc aux vectors set up by elfexec() point to
93712199Sgerald.jelinek@sun.com * brand emulation library and it's linker. Copy these to the
93812199Sgerald.jelinek@sun.com * /proc brand specific aux vector, and update the regular
93912199Sgerald.jelinek@sun.com * /proc aux vectors to point to the executable (and it's
94012199Sgerald.jelinek@sun.com * linker). This will enable debuggers to access the
94112199Sgerald.jelinek@sun.com * executable via the usual /proc or elf notes aux vectors.
94212199Sgerald.jelinek@sun.com *
94312199Sgerald.jelinek@sun.com * The brand emulation library's linker will get it's aux
94412199Sgerald.jelinek@sun.com * vectors off the stack, and then update the stack with the
94512199Sgerald.jelinek@sun.com * executable's aux vectors before jumping to the executable's
94612199Sgerald.jelinek@sun.com * linker.
94712199Sgerald.jelinek@sun.com *
94812199Sgerald.jelinek@sun.com * Debugging the brand emulation library must be done from
94912199Sgerald.jelinek@sun.com * the global zone, where the librtld_db module knows how to
95012199Sgerald.jelinek@sun.com * fetch the brand specific aux vectors to access the brand
95112199Sgerald.jelinek@sun.com * emulation libraries linker.
95212199Sgerald.jelinek@sun.com */
95312199Sgerald.jelinek@sun.com for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
95412199Sgerald.jelinek@sun.com ulong_t val;
95512199Sgerald.jelinek@sun.com
95612199Sgerald.jelinek@sun.com switch (up->u_auxv[i].a_type) {
95712199Sgerald.jelinek@sun.com case AT_SUN_BRAND_COMMON_LDDATA:
95812199Sgerald.jelinek@sun.com up->u_auxv[i].a_un.a_val = sed.sed_lddata;
95912199Sgerald.jelinek@sun.com continue;
96012199Sgerald.jelinek@sun.com case AT_BASE:
96112199Sgerald.jelinek@sun.com val = sedp->sed_base;
96212199Sgerald.jelinek@sun.com break;
96312199Sgerald.jelinek@sun.com case AT_ENTRY:
96412199Sgerald.jelinek@sun.com val = sedp->sed_entry;
96512199Sgerald.jelinek@sun.com break;
96612199Sgerald.jelinek@sun.com case AT_PHDR:
96712199Sgerald.jelinek@sun.com val = sedp->sed_phdr;
96812199Sgerald.jelinek@sun.com break;
96912199Sgerald.jelinek@sun.com case AT_PHENT:
97012199Sgerald.jelinek@sun.com val = sedp->sed_phent;
97112199Sgerald.jelinek@sun.com break;
97212199Sgerald.jelinek@sun.com case AT_PHNUM:
97312199Sgerald.jelinek@sun.com val = sedp->sed_phnum;
97412199Sgerald.jelinek@sun.com break;
97512199Sgerald.jelinek@sun.com case AT_SUN_LDDATA:
97612199Sgerald.jelinek@sun.com val = sedp->sed_lddata;
97712199Sgerald.jelinek@sun.com break;
97812199Sgerald.jelinek@sun.com default:
97912199Sgerald.jelinek@sun.com continue;
98012199Sgerald.jelinek@sun.com }
98112199Sgerald.jelinek@sun.com
98212199Sgerald.jelinek@sun.com up->u_auxv[i].a_un.a_val = val;
98312199Sgerald.jelinek@sun.com if (val == NULL) {
98412199Sgerald.jelinek@sun.com /* Hide the entry for static binaries */
98512199Sgerald.jelinek@sun.com up->u_auxv[i].a_type = AT_IGNORE;
98612199Sgerald.jelinek@sun.com }
98712199Sgerald.jelinek@sun.com }
98812199Sgerald.jelinek@sun.com
98912199Sgerald.jelinek@sun.com /*
99012199Sgerald.jelinek@sun.com * The last thing we do here is clear spd->spd_handler. This
99112199Sgerald.jelinek@sun.com * is important because if we're already a branded process and
99212199Sgerald.jelinek@sun.com * if this exec succeeds, there is a window between when the
99312199Sgerald.jelinek@sun.com * exec() first returns to the userland of the new process and
99412199Sgerald.jelinek@sun.com * when our brand library get's initialized, during which we
99512199Sgerald.jelinek@sun.com * don't want system calls to be re-directed to our brand
99612199Sgerald.jelinek@sun.com * library since it hasn't been initialized yet.
99712199Sgerald.jelinek@sun.com */
99812199Sgerald.jelinek@sun.com spd->spd_handler = NULL;
99912199Sgerald.jelinek@sun.com
100012199Sgerald.jelinek@sun.com return (0);
100112199Sgerald.jelinek@sun.com }
100212199Sgerald.jelinek@sun.com
100312199Sgerald.jelinek@sun.com void
brand_solaris_exec(struct brand * pbrand)100412199Sgerald.jelinek@sun.com brand_solaris_exec(struct brand *pbrand)
100512199Sgerald.jelinek@sun.com {
100612199Sgerald.jelinek@sun.com brand_proc_data_t *spd = curproc->p_brand_data;
100712199Sgerald.jelinek@sun.com
100812199Sgerald.jelinek@sun.com ASSERT(curproc->p_brand == pbrand);
100912199Sgerald.jelinek@sun.com ASSERT(curproc->p_brand_data != NULL);
101012199Sgerald.jelinek@sun.com ASSERT(ttolwp(curthread)->lwp_brand != NULL);
101112199Sgerald.jelinek@sun.com
101212199Sgerald.jelinek@sun.com /*
101312199Sgerald.jelinek@sun.com * We should only be called from exec(), when we know the process
101412199Sgerald.jelinek@sun.com * is single-threaded.
101512199Sgerald.jelinek@sun.com */
101612199Sgerald.jelinek@sun.com ASSERT(curproc->p_tlist == curproc->p_tlist->t_forw);
101712199Sgerald.jelinek@sun.com
101812199Sgerald.jelinek@sun.com /* Upon exec, reset our lwp brand data. */
101912199Sgerald.jelinek@sun.com (void) brand_solaris_freelwp(ttolwp(curthread), pbrand);
102012199Sgerald.jelinek@sun.com (void) brand_solaris_initlwp(ttolwp(curthread), pbrand);
102112199Sgerald.jelinek@sun.com
102212199Sgerald.jelinek@sun.com /*
102312199Sgerald.jelinek@sun.com * Upon exec, reset all the proc brand data, except for the elf
102412199Sgerald.jelinek@sun.com * data associated with the executable we are exec'ing.
102512199Sgerald.jelinek@sun.com */
102612199Sgerald.jelinek@sun.com spd->spd_handler = NULL;
102712199Sgerald.jelinek@sun.com }
102812199Sgerald.jelinek@sun.com
102912199Sgerald.jelinek@sun.com int
brand_solaris_fini(char ** emul_table,struct modlinkage * modlinkage,struct brand * pbrand)103012199Sgerald.jelinek@sun.com brand_solaris_fini(char **emul_table, struct modlinkage *modlinkage,
103112199Sgerald.jelinek@sun.com struct brand *pbrand)
103212199Sgerald.jelinek@sun.com {
103312199Sgerald.jelinek@sun.com int err;
103412199Sgerald.jelinek@sun.com
103512199Sgerald.jelinek@sun.com /*
103612199Sgerald.jelinek@sun.com * If there are any zones using this brand, we can't allow it
103712199Sgerald.jelinek@sun.com * to be unloaded.
103812199Sgerald.jelinek@sun.com */
103912199Sgerald.jelinek@sun.com if (brand_zone_count(pbrand))
104012199Sgerald.jelinek@sun.com return (EBUSY);
104112199Sgerald.jelinek@sun.com
104212199Sgerald.jelinek@sun.com kmem_free(*emul_table, NSYSCALL);
104312199Sgerald.jelinek@sun.com *emul_table = NULL;
104412199Sgerald.jelinek@sun.com
104512199Sgerald.jelinek@sun.com err = mod_remove(modlinkage);
104612199Sgerald.jelinek@sun.com if (err)
104712199Sgerald.jelinek@sun.com cmn_err(CE_WARN, "Couldn't unload brand module");
104812199Sgerald.jelinek@sun.com
104912199Sgerald.jelinek@sun.com return (err);
105012199Sgerald.jelinek@sun.com }
105112199Sgerald.jelinek@sun.com
105212199Sgerald.jelinek@sun.com /*ARGSUSED*/
105312199Sgerald.jelinek@sun.com void
brand_solaris_forklwp(klwp_t * p,klwp_t * c,struct brand * pbrand)105412199Sgerald.jelinek@sun.com brand_solaris_forklwp(klwp_t *p, klwp_t *c, struct brand *pbrand)
105512199Sgerald.jelinek@sun.com {
105612199Sgerald.jelinek@sun.com ASSERT(p->lwp_procp->p_brand == pbrand);
105712199Sgerald.jelinek@sun.com ASSERT(c->lwp_procp->p_brand == pbrand);
105812199Sgerald.jelinek@sun.com
105912199Sgerald.jelinek@sun.com ASSERT(p->lwp_procp->p_brand_data != NULL);
106012199Sgerald.jelinek@sun.com ASSERT(c->lwp_procp->p_brand_data != NULL);
106112199Sgerald.jelinek@sun.com
106212199Sgerald.jelinek@sun.com /*
106312199Sgerald.jelinek@sun.com * Both LWPs have already had been initialized via
106412199Sgerald.jelinek@sun.com * brand_solaris_initlwp().
106512199Sgerald.jelinek@sun.com */
106612199Sgerald.jelinek@sun.com ASSERT(p->lwp_brand != NULL);
106712199Sgerald.jelinek@sun.com ASSERT(c->lwp_brand != NULL);
106812199Sgerald.jelinek@sun.com }
106912199Sgerald.jelinek@sun.com
107012199Sgerald.jelinek@sun.com /*ARGSUSED*/
107112199Sgerald.jelinek@sun.com void
brand_solaris_freelwp(klwp_t * l,struct brand * pbrand)107212199Sgerald.jelinek@sun.com brand_solaris_freelwp(klwp_t *l, struct brand *pbrand)
107312199Sgerald.jelinek@sun.com {
107412199Sgerald.jelinek@sun.com ASSERT(l->lwp_procp->p_brand == pbrand);
107512199Sgerald.jelinek@sun.com ASSERT(l->lwp_procp->p_brand_data != NULL);
107612199Sgerald.jelinek@sun.com ASSERT(l->lwp_brand != NULL);
107712199Sgerald.jelinek@sun.com l->lwp_brand = NULL;
107812199Sgerald.jelinek@sun.com }
107912199Sgerald.jelinek@sun.com
108012199Sgerald.jelinek@sun.com /*ARGSUSED*/
108112199Sgerald.jelinek@sun.com int
brand_solaris_initlwp(klwp_t * l,struct brand * pbrand)108212199Sgerald.jelinek@sun.com brand_solaris_initlwp(klwp_t *l, struct brand *pbrand)
108312199Sgerald.jelinek@sun.com {
108412199Sgerald.jelinek@sun.com ASSERT(l->lwp_procp->p_brand == pbrand);
108512199Sgerald.jelinek@sun.com ASSERT(l->lwp_procp->p_brand_data != NULL);
108612199Sgerald.jelinek@sun.com ASSERT(l->lwp_brand == NULL);
108712199Sgerald.jelinek@sun.com l->lwp_brand = (void *)-1;
108812199Sgerald.jelinek@sun.com return (0);
108912199Sgerald.jelinek@sun.com }
109012199Sgerald.jelinek@sun.com
109112199Sgerald.jelinek@sun.com /*ARGSUSED*/
109212199Sgerald.jelinek@sun.com void
brand_solaris_lwpexit(klwp_t * l,struct brand * pbrand)109312199Sgerald.jelinek@sun.com brand_solaris_lwpexit(klwp_t *l, struct brand *pbrand)
109412199Sgerald.jelinek@sun.com {
109512199Sgerald.jelinek@sun.com proc_t *p = l->lwp_procp;
109612199Sgerald.jelinek@sun.com
109712199Sgerald.jelinek@sun.com ASSERT(l->lwp_procp->p_brand == pbrand);
109812199Sgerald.jelinek@sun.com ASSERT(l->lwp_procp->p_brand_data != NULL);
109912199Sgerald.jelinek@sun.com ASSERT(l->lwp_brand != NULL);
110012199Sgerald.jelinek@sun.com
110112199Sgerald.jelinek@sun.com /*
110212199Sgerald.jelinek@sun.com * We should never be called for the last thread in a process.
110312199Sgerald.jelinek@sun.com * (That case is handled by brand_solaris_proc_exit().)
110412199Sgerald.jelinek@sun.com * Therefore this lwp must be exiting from a multi-threaded
110512199Sgerald.jelinek@sun.com * process.
110612199Sgerald.jelinek@sun.com */
110712199Sgerald.jelinek@sun.com ASSERT(p->p_tlist != p->p_tlist->t_forw);
110812199Sgerald.jelinek@sun.com
110912199Sgerald.jelinek@sun.com l->lwp_brand = NULL;
111012199Sgerald.jelinek@sun.com }
111112199Sgerald.jelinek@sun.com
111212199Sgerald.jelinek@sun.com /*ARGSUSED*/
111312199Sgerald.jelinek@sun.com void
brand_solaris_proc_exit(struct proc * p,klwp_t * l,struct brand * pbrand)111412199Sgerald.jelinek@sun.com brand_solaris_proc_exit(struct proc *p, klwp_t *l, struct brand *pbrand)
111512199Sgerald.jelinek@sun.com {
111612199Sgerald.jelinek@sun.com ASSERT(p->p_brand == pbrand);
111712199Sgerald.jelinek@sun.com ASSERT(p->p_brand_data != NULL);
111812199Sgerald.jelinek@sun.com
111912199Sgerald.jelinek@sun.com /*
1120*13045SVamsi.Krishna@Sun.COM * When called from proc_exit(), we know that process is
1121*13045SVamsi.Krishna@Sun.COM * single-threaded and free our lwp brand data.
1122*13045SVamsi.Krishna@Sun.COM * otherwise just free p_brand_data and return.
112312199Sgerald.jelinek@sun.com */
1124*13045SVamsi.Krishna@Sun.COM if (l != NULL) {
1125*13045SVamsi.Krishna@Sun.COM ASSERT(p->p_tlist == p->p_tlist->t_forw);
1126*13045SVamsi.Krishna@Sun.COM ASSERT(p->p_tlist->t_lwp == l);
1127*13045SVamsi.Krishna@Sun.COM (void) brand_solaris_freelwp(l, pbrand);
1128*13045SVamsi.Krishna@Sun.COM }
112912199Sgerald.jelinek@sun.com
113012199Sgerald.jelinek@sun.com /* upon exit, free our proc brand data */
113112199Sgerald.jelinek@sun.com kmem_free(p->p_brand_data, sizeof (brand_proc_data_t));
113212199Sgerald.jelinek@sun.com p->p_brand_data = NULL;
113312199Sgerald.jelinek@sun.com }
113412199Sgerald.jelinek@sun.com
113512199Sgerald.jelinek@sun.com void
brand_solaris_setbrand(proc_t * p,struct brand * pbrand)113612199Sgerald.jelinek@sun.com brand_solaris_setbrand(proc_t *p, struct brand *pbrand)
113712199Sgerald.jelinek@sun.com {
113812199Sgerald.jelinek@sun.com ASSERT(p->p_brand == pbrand);
113912199Sgerald.jelinek@sun.com ASSERT(p->p_brand_data == NULL);
114012199Sgerald.jelinek@sun.com
114112199Sgerald.jelinek@sun.com /*
114212199Sgerald.jelinek@sun.com * We should only be called from exec(), when we know the process
114312199Sgerald.jelinek@sun.com * is single-threaded.
114412199Sgerald.jelinek@sun.com */
114512199Sgerald.jelinek@sun.com ASSERT(p->p_tlist == p->p_tlist->t_forw);
114612199Sgerald.jelinek@sun.com
114712199Sgerald.jelinek@sun.com p->p_brand_data = kmem_zalloc(sizeof (brand_proc_data_t), KM_SLEEP);
114812199Sgerald.jelinek@sun.com (void) brand_solaris_initlwp(p->p_tlist->t_lwp, pbrand);
114912199Sgerald.jelinek@sun.com }
1150