9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn/*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * CDDL HEADER START
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn *
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * The contents of this file are subject to the terms of the
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * Common Development and Distribution License (the "License").
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * You may not use this file except in compliance with the License.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn *
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * or http://www.opensolaris.org/os/licensing.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * See the License for the specific language governing permissions
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * and limitations under the License.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn *
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * When distributing Covered Code, include this CDDL HEADER in each
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * If applicable, add the following below this CDDL HEADER, with the
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * fields enclosed by brackets "[]" replaced with your own identifying
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * information: Portions Copyright [yyyy] [name of copyright owner]
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn *
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * CDDL HEADER END
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn/*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn#include <sys/kmem.h>
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn#include <sys/errno.h>
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn#include <sys/systm.h>
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn#include <sys/cmn_err.h>
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn#include <sys/brand.h>
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn#include <sys/machbrand.h>
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn#include <sys/modctl.h>
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn#include <sys/rwlock.h>
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn#include <sys/zone.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <sys/pathname.h>
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn#define SUPPORTED_BRAND_VERSION BRAND_VER_1
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn#if defined(__sparcv9)
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp/* sparcv9 uses system wide brand interposition hooks */
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edpstatic void brand_plat_interposition_enable(void);
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edpstatic void brand_plat_interposition_disable(void);
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnstruct brand_mach_ops native_mach_ops = {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn NULL, NULL
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn};
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp#else /* !__sparcv9 */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnstruct brand_mach_ops native_mach_ops = {
eb5a5c7888f20ad6fa4580e785308db395ef6dfcSurya Prakki NULL, NULL, NULL, NULL
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn};
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp#endif /* !__sparcv9 */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnbrand_t native_brand = {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn BRAND_VER_1,
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn "native",
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn NULL,
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn &native_mach_ops
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn};
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn/*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * Used to maintain a list of all the brands currently loaded into the
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * kernel.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnstruct brand_list {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn int bl_refcnt;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn struct brand_list *bl_next;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn brand_t *bl_brand;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn};
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnstatic struct brand_list *brand_list = NULL;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn/*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * This lock protects the integrity of the brand list.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnstatic kmutex_t brand_list_lock;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnvoid
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnbrand_init()
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn{
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_init(&brand_list_lock, NULL, MUTEX_DEFAULT, NULL);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn p0.p_brand = &native_brand;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn}
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnint
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnbrand_register(brand_t *brand)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn{
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn struct brand_list *list, *scan;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (brand == NULL)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (EINVAL);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (brand->b_version != SUPPORTED_BRAND_VERSION) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (brand->b_version < SUPPORTED_BRAND_VERSION) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn cmn_err(CE_WARN,
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn "brand '%s' was built to run on older versions "
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn "of Solaris.",
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn brand->b_name);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn } else {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn cmn_err(CE_WARN,
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn "brand '%s' was built to run on a newer version "
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn "of Solaris.",
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn brand->b_name);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (EINVAL);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn /* Sanity checks */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (brand->b_name == NULL || brand->b_ops == NULL ||
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn brand->b_ops->b_brandsys == NULL) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn cmn_err(CE_WARN, "Malformed brand");
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (EINVAL);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn list = kmem_alloc(sizeof (struct brand_list), KM_SLEEP);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn /* Add the brand to the list of loaded brands. */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_enter(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn /*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * Check to be sure we haven't already registered this brand.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn for (scan = brand_list; scan != NULL; scan = scan->bl_next) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (strcmp(brand->b_name, scan->bl_brand->b_name) == 0) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn cmn_err(CE_WARN,
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn "Invalid attempt to load a second instance of "
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn "brand %s", brand->b_name);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_exit(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn kmem_free(list, sizeof (struct brand_list));
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (EINVAL);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp#if defined(__sparcv9)
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp /* sparcv9 uses system wide brand interposition hooks */
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp if (brand_list == NULL)
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp brand_plat_interposition_enable();
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp#endif /* __sparcv9 */
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn list->bl_brand = brand;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn list->bl_refcnt = 0;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn list->bl_next = brand_list;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn brand_list = list;
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_exit(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (0);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn}
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn/*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * The kernel module implementing this brand is being unloaded, so remove
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * it from the list of active brands.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnint
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnbrand_unregister(brand_t *brand)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn{
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn struct brand_list *list, *prev;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn /* Sanity checks */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (brand == NULL || brand->b_name == NULL) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn cmn_err(CE_WARN, "Malformed brand");
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (EINVAL);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn prev = NULL;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_enter(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn for (list = brand_list; list != NULL; list = list->bl_next) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (list->bl_brand == brand)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn break;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn prev = list;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (list == NULL) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn cmn_err(CE_WARN, "Brand %s wasn't registered", brand->b_name);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_exit(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (EINVAL);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (list->bl_refcnt > 0) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn cmn_err(CE_WARN, "Unregistering brand %s which is still in use",
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn brand->b_name);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_exit(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (EBUSY);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn /* Remove brand from the list */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (prev != NULL)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn prev->bl_next = list->bl_next;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn else
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn brand_list = list->bl_next;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp#if defined(__sparcv9)
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp /* sparcv9 uses system wide brand interposition hooks */
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp if (brand_list == NULL)
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp brand_plat_interposition_disable();
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp#endif /* __sparcv9 */
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_exit(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn kmem_free(list, sizeof (struct brand_list));
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (0);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn}
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn/*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * Record that a zone of this brand has been instantiated. If the kernel
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * module implementing this brand's functionality is not present, this
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * routine attempts to load the module as a side effect.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnbrand_t *
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnbrand_register_zone(struct brand_attr *attr)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn{
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn struct brand_list *l = NULL;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn ddi_modhandle_t hdl = NULL;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn char *modname;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn int err = 0;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (is_system_labeled()) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn cmn_err(CE_WARN,
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn "Branded zones are not allowed on labeled systems.");
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (NULL);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn /*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * We make at most two passes through this loop. The first time
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * through, we're looking to see if this is a new user of an
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * already loaded brand. If the brand hasn't been loaded, we
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * call ddi_modopen() to force it to be loaded and then make a
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * second pass through the list of brands. If we don't find the
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * brand the second time through it means that the modname
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * specified in the brand_attr structure doesn't provide the brand
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * specified in the brandname field. This would suggest a bug in
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * the brand's config.xml file. We close the module and return
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * 'NULL' to the caller.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn for (;;) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn /*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * Search list of loaded brands
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_enter(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn for (l = brand_list; l != NULL; l = l->bl_next)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (strcmp(attr->ba_brandname,
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn l->bl_brand->b_name) == 0)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn break;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if ((l != NULL) || (hdl != NULL))
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn break;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_exit(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn /*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * We didn't find that the requested brand has been loaded
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * yet, so we trigger the load of the appropriate kernel
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * module and search the list again.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn modname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn (void) strcpy(modname, "brand/");
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn (void) strcat(modname, attr->ba_modname);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn hdl = ddi_modopen(modname, KRTLD_MODE_FIRST, &err);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn kmem_free(modname, MAXPATHLEN);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (err != 0)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (NULL);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn /*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * If we found the matching brand, bump its reference count.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (l != NULL)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn l->bl_refcnt++;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_exit(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (hdl != NULL)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn (void) ddi_modclose(hdl);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return ((l != NULL) ? l->bl_brand : NULL);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn}
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn/*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * Return the number of zones currently using this brand.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnint
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnbrand_zone_count(struct brand *bp)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn{
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn struct brand_list *l;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn int cnt = 0;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_enter(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn for (l = brand_list; l != NULL; l = l->bl_next)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (l->bl_brand == bp) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn cnt = l->bl_refcnt;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn break;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_exit(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn return (cnt);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn}
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnvoid
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnbrand_unregister_zone(struct brand *bp)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn{
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn struct brand_list *list;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_enter(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn for (list = brand_list; list != NULL; list = list->bl_next) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn if (list->bl_brand == bp) {
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn ASSERT(list->bl_refcnt > 0);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn list->bl_refcnt--;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn break;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn }
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn mutex_exit(&brand_list_lock);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn}
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnvoid
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnnbrand_setbrand(proc_t *p)
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn{
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn brand_t *bp = p->p_zone->zone_brand;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn ASSERT(bp != NULL);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn ASSERT(p->p_brand == &native_brand);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn /*
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * We should only be called from exec(), when we know the process
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn * is single-threaded.
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn */
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn ASSERT(p->p_tlist == p->p_tlist->t_forw);
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn p->p_brand = bp;
fd9e7635fa85e33de5aff912b955d797589f6f87edp ASSERT(PROC_IS_BRANDED(p));
fd9e7635fa85e33de5aff912b955d797589f6f87edp BROP(p)->b_setbrand(p);
fd9e7635fa85e33de5aff912b955d797589f6f87edp}
fd9e7635fa85e33de5aff912b955d797589f6f87edp
fd9e7635fa85e33de5aff912b955d797589f6f87edpvoid
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Naginenibrand_clearbrand(proc_t *p, boolean_t no_lwps)
fd9e7635fa85e33de5aff912b955d797589f6f87edp{
fd9e7635fa85e33de5aff912b955d797589f6f87edp brand_t *bp = p->p_zone->zone_brand;
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni klwp_t *lwp = NULL;
fd9e7635fa85e33de5aff912b955d797589f6f87edp ASSERT(bp != NULL);
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni ASSERT(!no_lwps || (p->p_tlist == NULL));
fd9e7635fa85e33de5aff912b955d797589f6f87edp
fd9e7635fa85e33de5aff912b955d797589f6f87edp /*
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni * If called from exec_common() or proc_exit(),
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni * we know the process is single-threaded.
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni * If called from fork_fail, p_tlist is NULL.
fd9e7635fa85e33de5aff912b955d797589f6f87edp */
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni if (!no_lwps) {
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni ASSERT(p->p_tlist == p->p_tlist->t_forw);
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni lwp = p->p_tlist->t_lwp;
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni }
fd9e7635fa85e33de5aff912b955d797589f6f87edp
fd9e7635fa85e33de5aff912b955d797589f6f87edp ASSERT(PROC_IS_BRANDED(p));
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni BROP(p)->b_proc_exit(p, lwp);
fd9e7635fa85e33de5aff912b955d797589f6f87edp p->p_brand = &native_brand;
9acbbeaf2a1ffe5c14b244867d427714fab43c5cnn}
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp#if defined(__sparcv9)
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp/*
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp * Currently, only sparc has system level brand syscall interposition.
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * On x86 we're able to enable syscall interposition on a per-cpu basis
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * when a branded thread is scheduled to run on a cpu.
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp */
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp/* Local variables needed for dynamic syscall interposition support */
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edpstatic uint32_t syscall_trap_patch_instr_orig;
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edpstatic uint32_t syscall_trap32_patch_instr_orig;
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp/* Trap Table syscall entry hot patch points */
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edpextern void syscall_trap_patch_point(void);
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edpextern void syscall_trap32_patch_point(void);
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp/* Alternate syscall entry handlers used when branded zones are running */
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edpextern void syscall_wrapper(void);
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edpextern void syscall_wrapper32(void);
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp/* Macros used to facilitate sparcv9 instruction generation */
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp#define BA_A_INSTR 0x30800000 /* ba,a addr */
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp#define DISP22(from, to) \
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp ((((uintptr_t)(to) - (uintptr_t)(from)) >> 2) & 0x3fffff)
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp/*ARGSUSED*/
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edpstatic void
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edpbrand_plat_interposition_enable(void)
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp{
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp ASSERT(MUTEX_HELD(&brand_list_lock));
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp /*
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * Before we hot patch the kernel save the current instructions
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp * so that we can restore them later.
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp */
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp syscall_trap_patch_instr_orig =
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp *(uint32_t *)syscall_trap_patch_point;
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp syscall_trap32_patch_instr_orig =
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp *(uint32_t *)syscall_trap32_patch_point;
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp /*
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * Modify the trap table at the patch points.
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp *
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * We basically replace the first instruction at the patch
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * point with a ba,a instruction that will transfer control
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * to syscall_wrapper or syscall_wrapper32 for 64-bit and
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * 32-bit syscalls respectively. It's important to note that
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * the annul bit is set in the branch so we don't execute
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * the instruction directly following the one we're patching
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * during the branch's delay slot.
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp *
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * It also doesn't matter that we're not atomically updating both
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * the 64 and 32 bit syscall paths at the same time since there's
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * no actual branded processes running on the system yet.
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp */
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp hot_patch_kernel_text((caddr_t)syscall_trap_patch_point,
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp BA_A_INSTR | DISP22(syscall_trap_patch_point, syscall_wrapper),
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp 4);
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp hot_patch_kernel_text((caddr_t)syscall_trap32_patch_point,
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp BA_A_INSTR | DISP22(syscall_trap32_patch_point, syscall_wrapper32),
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp 4);
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp}
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp/*ARGSUSED*/
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edpstatic void
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edpbrand_plat_interposition_disable(void)
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp{
725deb8fd64fbf9c978c9fe35c9d5cc1e4a7b6c2edp ASSERT(MUTEX_HELD(&brand_list_lock));
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp /*
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * Restore the original instructions at the trap table syscall
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * patch points to disable the brand syscall interposition
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp * mechanism.
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp */
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp hot_patch_kernel_text((caddr_t)syscall_trap_patch_point,
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp syscall_trap_patch_instr_orig, 4);
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp hot_patch_kernel_text((caddr_t)syscall_trap32_patch_point,
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp syscall_trap32_patch_instr_orig, 4);
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp}
59f2ff5c96304fcfa3d97e66fbe1c521f42ac103edp#endif /* __sparcv9 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * The following functions can be shared among kernel brand modules which
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * implement Solaris-derived brands, all of which need to do similar tasks
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * to manage the brand.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#if defined(_LP64)
80e2ca8596e3435bc3b76f3c597833ea0a87f85estatic void
80e2ca8596e3435bc3b76f3c597833ea0a87f85eEhdr32to64(Elf32_Ehdr *src, Ehdr *dst)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e bcopy(src->e_ident, dst->e_ident, sizeof (src->e_ident));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_type = src->e_type;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_machine = src->e_machine;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_version = src->e_version;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_entry = src->e_entry;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_phoff = src->e_phoff;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_shoff = src->e_shoff;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_flags = src->e_flags;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_ehsize = src->e_ehsize;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_phentsize = src->e_phentsize;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_phnum = src->e_phnum;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_shentsize = src->e_shentsize;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_shnum = src->e_shnum;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e dst->e_shstrndx = src->e_shstrndx;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#endif /* _LP64 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Return -1 if the cmd was not handled by this function.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85eint
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_solaris_cmd(int cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e struct brand *pbrand, int brandvers)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_proc_data_t *spd;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_proc_reg_t reg;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e proc_t *p = curproc;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e int err;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * There is one operation that is supported for a native
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * process; B_EXEC_BRAND. This brand operaion is redundant
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * since the kernel assumes a native process doing an exec
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * in a branded zone is going to run a branded processes.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * hence we don't support this operation.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (cmd == B_EXEC_BRAND)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (ENOSYS);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* For all other operations this must be a branded process. */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (p->p_brand == &native_brand)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (ENOSYS);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(p->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(p->p_brand_data != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e spd = (brand_proc_data_t *)p->p_brand_data;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e switch ((cmd)) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case B_EXEC_NATIVE:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e err = exec_common((char *)arg1, (const char **)arg2,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e (const char **)arg3, EBA_NATIVE);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (err);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Get the address of the user-space system call handler from
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * the user process and attach it to the proc structure.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case B_REGISTER:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (p->p_model == DATAMODEL_NATIVE) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (copyin((void *)arg1, &reg, sizeof (reg)) != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#if defined(_LP64)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e else {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_common_reg32_t reg32;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (copyin((void *)arg1, &reg32, sizeof (reg32)) != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e reg.sbr_version = reg32.sbr_version;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e reg.sbr_handler = (caddr_t)(uintptr_t)reg32.sbr_handler;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#endif /* _LP64 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (reg.sbr_version != brandvers)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (ENOTSUP);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e spd->spd_handler = reg.sbr_handler;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (0);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case B_ELFDATA:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (p->p_model == DATAMODEL_NATIVE) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (copyout(&spd->spd_elf_data, (void *)arg1,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sizeof (brand_elf_data_t)) != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#if defined(_LP64)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e else {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_elf_data32_t sed32;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed32.sed_phdr = spd->spd_elf_data.sed_phdr;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed32.sed_phent = spd->spd_elf_data.sed_phent;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed32.sed_phnum = spd->spd_elf_data.sed_phnum;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed32.sed_entry = spd->spd_elf_data.sed_entry;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed32.sed_base = spd->spd_elf_data.sed_base;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed32.sed_ldentry = spd->spd_elf_data.sed_ldentry;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed32.sed_lddata = spd->spd_elf_data.sed_lddata;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (copyout(&sed32, (void *)arg1, sizeof (sed32))
80e2ca8596e3435bc3b76f3c597833ea0a87f85e != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#endif /* _LP64 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (0);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * The B_TRUSS_POINT subcommand exists so that we can see
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * truss output from interposed system calls that return
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * without first calling any other system call, meaning they
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * would be invisible to truss(1).
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * If the second argument is set non-zero, set errno to that
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * value as well.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Common arguments seen with truss are:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * arg1: syscall number
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * arg2: errno
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case B_TRUSS_POINT:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return ((arg2 == 0) ? 0 : set_errno((uint_t)arg2));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (-1);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85evoid
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_solaris_copy_procdata(proc_t *child, proc_t *parent, struct brand *pbrand)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_proc_data_t *spd;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(parent->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(child->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(parent->p_brand_data != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(child->p_brand_data == NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Just duplicate all the proc data of the parent for the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * child
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e spd = kmem_alloc(sizeof (brand_proc_data_t), KM_SLEEP);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e bcopy(parent->p_brand_data, spd, sizeof (brand_proc_data_t));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e child->p_brand_data = spd;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65static void
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65restoreexecenv(struct execenv *ep, stack_t *sp)
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65{
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 klwp_t *lwp = ttolwp(curthread);
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 setexecenv(ep);
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 lwp->lwp_sigaltstack.ss_sp = sp->ss_sp;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 lwp->lwp_sigaltstack.ss_size = sp->ss_size;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 lwp->lwp_sigaltstack.ss_flags = sp->ss_flags;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65}
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85eint
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_solaris_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e intpdata_t *idatap, int level, long *execsz, int setid, caddr_t exec_file,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e cred_t *cred, int brand_action, struct brand *pbrand, char *bname,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e char *brandlib, char *brandlib32, char *brandlinker, char *brandlinker32)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e vnode_t *nvp;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e Ehdr ehdr;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e Addr uphdr_vaddr;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e intptr_t voffset;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e int interp;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e int i, err;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e struct execenv env;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 struct execenv origenv;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 stack_t orig_sigaltstack;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e struct user *up = PTOU(curproc);
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 proc_t *p = ttoproc(curthread);
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 klwp_t *lwp = ttolwp(curthread);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_proc_data_t *spd;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_elf_data_t sed, *sedp;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e char *linker;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e uintptr_t lddata; /* lddata of executable's linker */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(curproc->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(curproc->p_brand_data != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e spd = (brand_proc_data_t *)curproc->p_brand_data;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp = &spd->spd_elf_data;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e args->brandname = bname;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * We will exec the brand library and then map in the target
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * application and (optionally) the brand's default linker.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (args->to_model == DATAMODEL_NATIVE) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e args->emulator = brandlib;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e linker = brandlinker;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#if defined(_LP64)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e else {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e args->emulator = brandlib32;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e linker = brandlinker32;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#endif /* _LP64 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if ((err = lookupname(args->emulator, UIO_SYSSPACE, FOLLOW,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e NULLVPP, &nvp)) != 0) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e uprintf("%s: not found.", args->emulator);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (err);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 /*
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 * The following elf{32}exec call changes the execenv in the proc
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 * struct which includes changing the p_exec member to be the vnode
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 * for the brand library (e.g. /.SUNWnative/usr/lib/s10_brand.so.1).
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 * We will eventually set the p_exec member to be the vnode for the new
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 * executable when we call setexecenv(). However, if we get an error
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 * before that call we need to restore the execenv to its original
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 * values so that when we return to the caller fop_close() works
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 * properly while cleaning up from the failed exec(). Restoring the
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 * original value will also properly decrement the 2nd VN_RELE that we
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 * took on the brand library.
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 */
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 origenv.ex_bssbase = p->p_bssbase;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 origenv.ex_brkbase = p->p_brkbase;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 origenv.ex_brksize = p->p_brksize;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 origenv.ex_vp = p->p_exec;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 orig_sigaltstack.ss_sp = lwp->lwp_sigaltstack.ss_sp;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 orig_sigaltstack.ss_size = lwp->lwp_sigaltstack.ss_size;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 orig_sigaltstack.ss_flags = lwp->lwp_sigaltstack.ss_flags;
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (args->to_model == DATAMODEL_NATIVE) {
93cf283ac1d0119d2ee3842f515f8d0e1bc7cbdbJerry Jelinek err = elfexec(nvp, uap, args, idatap, INTP_MAXDEPTH + 1, execsz,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e setid, exec_file, cred, brand_action);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#if defined(_LP64)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e else {
93cf283ac1d0119d2ee3842f515f8d0e1bc7cbdbJerry Jelinek err = elf32exec(nvp, uap, args, idatap, INTP_MAXDEPTH + 1,
93cf283ac1d0119d2ee3842f515f8d0e1bc7cbdbJerry Jelinek execsz, setid, exec_file, cred, brand_action);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#endif /* _LP64 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e VN_RELE(nvp);
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 if (err != 0) {
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 restoreexecenv(&origenv, &orig_sigaltstack);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (err);
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * The u_auxv veCTors are set up by elfexec to point to the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * brand emulation library and linker. Save these so they can
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * be copied to the specific brand aux vectors.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e bzero(&sed, sizeof (sed));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e switch (up->u_auxv[i].a_type) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_SUN_LDDATA:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed.sed_lddata = up->u_auxv[i].a_un.a_val;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_BASE:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed.sed_base = up->u_auxv[i].a_un.a_val;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_ENTRY:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed.sed_entry = up->u_auxv[i].a_un.a_val;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_PHDR:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed.sed_phdr = up->u_auxv[i].a_un.a_val;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_PHENT:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed.sed_phent = up->u_auxv[i].a_un.a_val;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_PHNUM:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sed.sed_phnum = up->u_auxv[i].a_un.a_val;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e default:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* Make sure the emulator has an entry point */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(sed.sed_entry != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(sed.sed_phdr != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e bzero(&env, sizeof (env));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (args->to_model == DATAMODEL_NATIVE) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e err = mapexec_brand(vp, args, &ehdr, &uphdr_vaddr,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e &voffset, exec_file, &interp, &env.ex_bssbase,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e &env.ex_brkbase, &env.ex_brksize, NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#if defined(_LP64)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e else {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e Elf32_Ehdr ehdr32;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e Elf32_Addr uphdr_vaddr32;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e err = mapexec32_brand(vp, args, &ehdr32, &uphdr_vaddr32,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e &voffset, exec_file, &interp, &env.ex_bssbase,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e &env.ex_brkbase, &env.ex_brksize, NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e Ehdr32to64(&ehdr32, &ehdr);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (uphdr_vaddr32 == (Elf32_Addr)-1)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e uphdr_vaddr = (Addr)-1;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e else
80e2ca8596e3435bc3b76f3c597833ea0a87f85e uphdr_vaddr = uphdr_vaddr32;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#endif /* _LP64 */
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 if (err != 0) {
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 restoreexecenv(&origenv, &orig_sigaltstack);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (err);
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Save off the important properties of the executable. The
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * brand library will ask us for this data later, when it is
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * initializing and getting ready to transfer control to the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * brand application.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (uphdr_vaddr == (Addr)-1)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_phdr = voffset + ehdr.e_phoff;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e else
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_phdr = voffset + uphdr_vaddr;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_entry = voffset + ehdr.e_entry;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_phent = ehdr.e_phentsize;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_phnum = ehdr.e_phnum;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (interp) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (ehdr.e_type == ET_DYN) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * This is a shared object executable, so we
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * need to pick a reasonable place to put the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * heap. Just don't use the first page.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e env.ex_brkbase = (caddr_t)PAGESIZE;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e env.ex_bssbase = (caddr_t)PAGESIZE;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * If the program needs an interpreter (most do), map
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * it in and store relevant information about it in the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * aux vector, where the brand library can find it.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if ((err = lookupname(linker, UIO_SYSSPACE,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e FOLLOW, NULLVPP, &nvp)) != 0) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e uprintf("%s: not found.", brandlinker);
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 restoreexecenv(&origenv, &orig_sigaltstack);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (err);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (args->to_model == DATAMODEL_NATIVE) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e err = mapexec_brand(nvp, args, &ehdr,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e &uphdr_vaddr, &voffset, exec_file, &interp,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e NULL, NULL, NULL, &lddata);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#if defined(_LP64)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e else {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e Elf32_Ehdr ehdr32;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e Elf32_Addr uphdr_vaddr32;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e err = mapexec32_brand(nvp, args, &ehdr32,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e &uphdr_vaddr32, &voffset, exec_file, &interp,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e NULL, NULL, NULL, &lddata);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e Ehdr32to64(&ehdr32, &ehdr);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (uphdr_vaddr32 == (Elf32_Addr)-1)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e uphdr_vaddr = (Addr)-1;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e else
80e2ca8596e3435bc3b76f3c597833ea0a87f85e uphdr_vaddr = uphdr_vaddr32;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#endif /* _LP64 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e VN_RELE(nvp);
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 if (err != 0) {
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 restoreexecenv(&origenv, &orig_sigaltstack);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (err);
2ab1f1ec9729e08cce7a029b9e0e7180098a2d65 }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Now that we know the base address of the brand's
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * linker, place it in the aux vector.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_base = voffset;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_ldentry = voffset + ehdr.e_entry;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_lddata = voffset + lddata;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e } else {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * This program has no interpreter. The brand library
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * will jump to the address in the AT_SUN_BRAND_LDENTRY
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * aux vector, so in this case, put the entry point of
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * the main executable there.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (ehdr.e_type == ET_EXEC) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * An executable with no interpreter, this must
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * be a statically linked executable, which
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * means we loaded it at the address specified
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * in the elf header, in which case the e_entry
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * field of the elf header is an absolute
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * address.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_ldentry = ehdr.e_entry;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_entry = ehdr.e_entry;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_lddata = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_base = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e } else {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * A shared object with no interpreter, we use
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * the calculated address from above.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_ldentry = sedp->sed_entry;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_entry = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_phdr = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_phent = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_phnum = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_lddata = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sedp->sed_base = voffset;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (ehdr.e_type == ET_DYN) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Delay setting the brkbase until the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * first call to brk(); see elfexec()
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * for details.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e env.ex_bssbase = (caddr_t)0;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e env.ex_brkbase = (caddr_t)0;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e env.ex_brksize = 0;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e env.ex_magic = elfmagic;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e env.ex_vp = vp;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e setexecenv(&env);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * It's time to manipulate the process aux vectors. First
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * we need to update the AT_SUN_AUXFLAGS aux vector to set
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * the AF_SUN_NOPLM flag.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (args->to_model == DATAMODEL_NATIVE) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e auxv_t auxflags_auxv;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (copyin(args->auxp_auxflags, &auxflags_auxv,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sizeof (auxflags_auxv)) != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(auxflags_auxv.a_type == AT_SUN_AUXFLAGS);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e auxflags_auxv.a_un.a_val |= AF_SUN_NOPLM;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (copyout(&auxflags_auxv, args->auxp_auxflags,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sizeof (auxflags_auxv)) != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#if defined(_LP64)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e else {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e auxv32_t auxflags_auxv32;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (copyin(args->auxp_auxflags, &auxflags_auxv32,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sizeof (auxflags_auxv32)) != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(auxflags_auxv32.a_type == AT_SUN_AUXFLAGS);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e auxflags_auxv32.a_un.a_val |= AF_SUN_NOPLM;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (copyout(&auxflags_auxv32, args->auxp_auxflags,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sizeof (auxflags_auxv32)) != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#endif /* _LP64 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* Second, copy out the brand specific aux vectors. */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (args->to_model == DATAMODEL_NATIVE) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e auxv_t brand_auxv[] = {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e { AT_SUN_BRAND_AUX1, 0 },
80e2ca8596e3435bc3b76f3c597833ea0a87f85e { AT_SUN_BRAND_AUX2, 0 },
80e2ca8596e3435bc3b76f3c597833ea0a87f85e { AT_SUN_BRAND_AUX3, 0 }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e };
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(brand_auxv[0].a_type ==
80e2ca8596e3435bc3b76f3c597833ea0a87f85e AT_SUN_BRAND_COMMON_LDDATA);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_auxv[0].a_un.a_val = sed.sed_lddata;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (copyout(&brand_auxv, args->auxp_brand,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sizeof (brand_auxv)) != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#if defined(_LP64)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e else {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e auxv32_t brand_auxv32[] = {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e { AT_SUN_BRAND_AUX1, 0 },
80e2ca8596e3435bc3b76f3c597833ea0a87f85e { AT_SUN_BRAND_AUX2, 0 },
80e2ca8596e3435bc3b76f3c597833ea0a87f85e { AT_SUN_BRAND_AUX3, 0 }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e };
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(brand_auxv32[0].a_type == AT_SUN_BRAND_COMMON_LDDATA);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_auxv32[0].a_un.a_val = (uint32_t)sed.sed_lddata;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (copyout(&brand_auxv32, args->auxp_brand,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sizeof (brand_auxv32)) != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#endif /* _LP64 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Third, the /proc aux vectors set up by elfexec() point to
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * brand emulation library and it's linker. Copy these to the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * /proc brand specific aux vector, and update the regular
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * /proc aux vectors to point to the executable (and it's
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * linker). This will enable debuggers to access the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * executable via the usual /proc or elf notes aux vectors.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * The brand emulation library's linker will get it's aux
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * vectors off the stack, and then update the stack with the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * executable's aux vectors before jumping to the executable's
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * linker.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Debugging the brand emulation library must be done from
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * the global zone, where the librtld_db module knows how to
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * fetch the brand specific aux vectors to access the brand
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * emulation libraries linker.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ulong_t val;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e switch (up->u_auxv[i].a_type) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_SUN_BRAND_COMMON_LDDATA:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e up->u_auxv[i].a_un.a_val = sed.sed_lddata;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e continue;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_BASE:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e val = sedp->sed_base;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_ENTRY:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e val = sedp->sed_entry;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_PHDR:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e val = sedp->sed_phdr;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_PHENT:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e val = sedp->sed_phent;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_PHNUM:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e val = sedp->sed_phnum;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_SUN_LDDATA:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e val = sedp->sed_lddata;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e default:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e continue;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e up->u_auxv[i].a_un.a_val = val;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (val == NULL) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* Hide the entry for static binaries */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e up->u_auxv[i].a_type = AT_IGNORE;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * The last thing we do here is clear spd->spd_handler. This
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * is important because if we're already a branded process and
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * if this exec succeeds, there is a window between when the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * exec() first returns to the userland of the new process and
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * when our brand library get's initialized, during which we
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * don't want system calls to be re-directed to our brand
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * library since it hasn't been initialized yet.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e spd->spd_handler = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (0);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85evoid
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_solaris_exec(struct brand *pbrand)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_proc_data_t *spd = curproc->p_brand_data;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(curproc->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(curproc->p_brand_data != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(ttolwp(curthread)->lwp_brand != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * We should only be called from exec(), when we know the process
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * is single-threaded.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(curproc->p_tlist == curproc->p_tlist->t_forw);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* Upon exec, reset our lwp brand data. */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e (void) brand_solaris_freelwp(ttolwp(curthread), pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e (void) brand_solaris_initlwp(ttolwp(curthread), pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Upon exec, reset all the proc brand data, except for the elf
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * data associated with the executable we are exec'ing.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e spd->spd_handler = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85eint
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_solaris_fini(char **emul_table, struct modlinkage *modlinkage,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e struct brand *pbrand)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e int err;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * If there are any zones using this brand, we can't allow it
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * to be unloaded.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (brand_zone_count(pbrand))
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EBUSY);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e kmem_free(*emul_table, NSYSCALL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *emul_table = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e err = mod_remove(modlinkage);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (err)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e cmn_err(CE_WARN, "Couldn't unload brand module");
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (err);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85evoid
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_solaris_forklwp(klwp_t *p, klwp_t *c, struct brand *pbrand)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(p->lwp_procp->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(c->lwp_procp->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(p->lwp_procp->p_brand_data != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(c->lwp_procp->p_brand_data != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Both LWPs have already had been initialized via
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * brand_solaris_initlwp().
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(p->lwp_brand != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(c->lwp_brand != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85evoid
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_solaris_freelwp(klwp_t *l, struct brand *pbrand)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(l->lwp_procp->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(l->lwp_procp->p_brand_data != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(l->lwp_brand != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e l->lwp_brand = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85eint
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_solaris_initlwp(klwp_t *l, struct brand *pbrand)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(l->lwp_procp->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(l->lwp_procp->p_brand_data != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(l->lwp_brand == NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e l->lwp_brand = (void *)-1;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (0);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85evoid
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_solaris_lwpexit(klwp_t *l, struct brand *pbrand)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e proc_t *p = l->lwp_procp;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(l->lwp_procp->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(l->lwp_procp->p_brand_data != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(l->lwp_brand != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * We should never be called for the last thread in a process.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * (That case is handled by brand_solaris_proc_exit().)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Therefore this lwp must be exiting from a multi-threaded
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * process.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(p->p_tlist != p->p_tlist->t_forw);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e l->lwp_brand = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85evoid
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_solaris_proc_exit(struct proc *p, klwp_t *l, struct brand *pbrand)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(p->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(p->p_brand_data != NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni * When called from proc_exit(), we know that process is
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni * single-threaded and free our lwp brand data.
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni * otherwise just free p_brand_data and return.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni if (l != NULL) {
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni ASSERT(p->p_tlist == p->p_tlist->t_forw);
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni ASSERT(p->p_tlist->t_lwp == l);
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni (void) brand_solaris_freelwp(l, pbrand);
e9f7cbf00b5dbfafe45ffb00125fa0cc683595c6Vamsi Nagineni }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* upon exit, free our proc brand data */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e kmem_free(p->p_brand_data, sizeof (brand_proc_data_t));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e p->p_brand_data = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85evoid
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_solaris_setbrand(proc_t *p, struct brand *pbrand)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(p->p_brand == pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(p->p_brand_data == NULL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * We should only be called from exec(), when we know the process
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * is single-threaded.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ASSERT(p->p_tlist == p->p_tlist->t_forw);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e p->p_brand_data = kmem_zalloc(sizeof (brand_proc_data_t), KM_SLEEP);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e (void) brand_solaris_initlwp(p->p_tlist->t_lwp, pbrand);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}