80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * CDDL HEADER START
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * The contents of this file are subject to the terms of the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Common Development and Distribution License (the "License").
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * You may not use this file except in compliance with the License.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * or http://www.opensolaris.org/os/licensing.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * See the License for the specific language governing permissions
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * and limitations under the License.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * When distributing Covered Code, include this CDDL HEADER in each
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * If applicable, add the following below this CDDL HEADER, with the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * fields enclosed by brackets "[]" replaced with your own identifying
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * information: Portions Copyright [yyyy] [name of copyright owner]
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * CDDL HEADER END
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <errno.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <stdio.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <stdlib.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <strings.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <unistd.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <sys/auxv.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <sys/bitmap.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <sys/brand.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <sys/inttypes.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <sys/lwp.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <sys/syscall.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <sys/systm.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <sys/utsname.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <fcntl.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <brand_misc.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#include <sys/brand.h>
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85eextern brand_sysent_table_t brand_sysent_table[];
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*LINTED: static unused*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85estatic volatile int brand_abort_err;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*LINTED: static unused*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85estatic volatile const char *brand_abort_msg;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*LINTED: static unused*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85estatic volatile const char *brand_abort_file;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*LINTED: static unused*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85estatic volatile int brand_abort_line;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Principles of emulation 101.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * *** Setting errno
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Just don't do it. This emulation library is loaded onto a
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * seperate link map from the application who's address space we're
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * running in. We have our own private copy of libc, so there for,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * the errno value accessible from here is is also private and changing
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * it will not affect any errno value that the processes who's address
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * space we are running in will see. To return an error condition we
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * should return the errno value we'd like the system to return.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * For more information about this see the comments in brand_misc.h.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Basically, when we return to the caller that initiated the system
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * call it's their responsibility to set errno.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * *** Recursion Considerations
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * When emulating system calls we need to be very careful about what
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * library calls we invoke. Library calls should be kept to a minimum.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * One issue is that library calls can invoke system calls, so if we're
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * emulating a system call and we invoke a library call that depends on
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * that system call we will probably enter a recursive loop, which would
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * be bad.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * *** Return Values.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * See brand_misc.h.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * *** Agent lwp considerations
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * It is currently impossible to do any emulation for these system call
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * when they are being invoked on behalf of an agent lwp. To understand why
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * it's impossible you have to understand how agent lwp syscalls work.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * The agent lwp syscall process works as follows:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 1 The controlling process stops the target.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 2 The controlling process injects an agent lwp which is also stopped.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * This agent lwp assumes the userland stack and register values
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * of another stopped lwp in the current process.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 3 The controlling process configures the agent lwp to start
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * executing the requested system call.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 4 The controlling process configure /proc to stop the agent lwp when
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * it enters the requested system call.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 5 The controlling processes allows the agent lwp to start executing.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 6 The agent lwp traps into the kernel to perform the requested system
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * call and immediately stop.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 7 The controlling process copies all the arguments for the requested
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * system call onto the agent lwp's stack.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 8 The controlling process configures /proc to stop the agent lwp
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * when it completes the requested system call.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 9 The controlling processes allows the agent lwp to start executing.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 10 The agent lwp executes the system call and then stop before returning
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * to userland.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 11 The controlling process copies the return value and return arguments
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * back from the agent lwps stack.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * 12 The controlling process destroys the agent lwp and restarts
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * the target process.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * The fundamental problem is that when the agent executes the request
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * system call in step 5, if we're emulating that system call then the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * lwp is redirected back to our emulation layer without blocking
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * in the kernel. But our emulation layer can't access the arguments
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * for the system call because they haven't been copied to the stack
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * yet and they still only exist in the controlling processes address
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * space. This prevents us from being able to do any emulation of
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * agent lwp system calls. Hence, currently our brand trap interposition
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * callback (XXX_brand_syscall_callback_common) will detect if a system
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * call is being made by an agent lwp, and if this is the case it will
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * never redirect the system call to this emulation library.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * In the future, if this proves to be a problem the the easiest solution
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * would probably be to replace the branded versions of these application
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * with their native counterparts. Ie, truss, plimit, and pfiles could be
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * replace with wrapper scripts that execute the native versions of these
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * applications. In the case of plimit and pfiles this should be pretty
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * strait forward. Truss would probably be more tricky since it can
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * execute applications which would be branded applications, so in that
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * case it might be necessary to create a loadable library which could
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * be LD_PRELOADed into truss and this library would interpose on the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * exec() system call to allow truss to correctly execute branded
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * processes. It should be pointed out that this solution could work
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * because "native agent lwps" (ie, agent lwps created by native
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * processes) can be treated differently from "branded aged lwps" (ie,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * agent lwps created by branded processes), since native agent lwps
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * would presumably be making native system calls and hence not need
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * any interposition.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * *** General considerations
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * One of the differences between the lx brand and the s10
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * brand, is that the s10 brand only interposes on syscalls
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * that need some kind of emulation, whereas the lx brand interposes
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * on _all_ system calls. Lx branded system calls that don't need
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * any emulation are then redirected back to the kernel from the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * userland library via the IN_KERNEL_SYSCALL macro. The lx-syscall
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * dtrace provider depends on this behavior.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85evoid
80e2ca8596e3435bc3b76f3c597833ea0a87f85e_brand_abort(int err, const char *msg, const char *file, int line)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sysret_t rval;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* Save the error message into convenient globals */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_abort_err = err;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_abort_msg = msg;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_abort_file = file;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_abort_line = line;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* kill ourselves */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e abort();
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* If abort() didn't work, try something stronger. */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e (void) __systemcall(&rval, SYS_lwp_kill + 1024, _lwp_self(), SIGKILL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85eint
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_uucopy(const void *from, void *to, size_t size)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sysret_t rval;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (__systemcall(&rval, SYS_uucopy + 1024, from, to, size) != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (0);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * ATTENTION: uucopystr() does NOT ensure that string are null terminated!
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85eint
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_uucopystr(const void *from, void *to, size_t size)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sysret_t rval;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (__systemcall(&rval, SYS_uucopystr + 1024, from, to, size) != 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EFAULT);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (0);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * This function is defined to be NOSYS but it won't be called from the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * the kernel since the NOSYS system calls are not enabled in the kernel.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Thus, the only time this function is called is directly from within the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * indirect system call path.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85elong
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_unimpl(sysret_t *rv, uintptr_t p1)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sysret_t rval;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * We'd like to print out some kind of error message here like
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * "unsupported syscall", but we can't because it's not safe to
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * assume that stderr or STDERR_FILENO actually points to something
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * that is a terminal, and if we wrote to those files we could
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * inadvertantly write to some applications open files, which would
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * be bad.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Normally, if an application calls an invalid system call
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * it get a SIGSYS sent to it. So we'll just go ahead and send
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * ourselves a signal here. Note that this is far from ideal since
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * if the application has registered a signal handler, that signal
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * handler may recieve a ucontext_t as the third parameter to
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * indicate the context of the process when the signal was
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * generated, and in this case that context will not be what the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * application is expecting. Hence, we should probably create a
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * brandsys() kernel function that can deliver the signal to us
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * with the correct ucontext_t.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e (void) __systemcall(&rval, SYS_lwp_kill + 1024, _lwp_self(), SIGSYS);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (ENOSYS);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#if defined(__sparc) && !defined(__sparcv9)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Yuck. For 32-bit sparc applications, handle indirect system calls.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Note that we declare this interface to use the maximum number of
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * system call arguments. If we recieve a system call that uses less
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * arguments, then the additional arguments will be garbage, but they
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * will also be ignored so that should be ok.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85elong
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_indir(sysret_t *rv, int code,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e uintptr_t a5, uintptr_t a6, uintptr_t a7)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_sysent_table_t *sst = &(brand_sysent_table[code]);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_assert(code < NSYSCALL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e switch (sst->st_args & NARGS_MASK) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case 0:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return ((sst->st_callc)(rv));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case 1:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return ((sst->st_callc)(rv, a0));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case 2:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return ((sst->st_callc)(rv, a0, a1));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case 3:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return ((sst->st_callc)(rv, a0, a1, a2));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case 4:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return ((sst->st_callc)(rv, a0, a1, a2, a3));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case 5:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return ((sst->st_callc)(rv, a0, a1, a2, a3, a4));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case 6:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return ((sst->st_callc)(rv, a0, a1, a2, a3, a4, a5));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case 7:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return ((sst->st_callc)(rv, a0, a1, a2, a3, a4, a5, a6));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case 8:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return ((sst->st_callc)(rv, a0, a1, a2, a3, a4, a5, a6, a7));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_abort(0, "invalid entry in brand_sysent_table");
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (EINVAL);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#endif /* __sparc && !__sparcv9 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Close a libc file handle, but don't actually close the underlying
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * file descriptor.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85estatic void
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_close_fh(FILE *file)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e int fd, fd_new;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (file == NULL)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if ((fd = fileno(file)) < 0)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * We're a branded process but our handler isn't installed yet. We
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * can't use the dup() syscall since it no longer exists.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e fd_new = fcntl(fd, F_DUPFD, 0);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (fd_new == -1)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e (void) fclose(file);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e (void) dup2(fd_new, fd);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e (void) close(fd_new);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85evoid
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_pre_init()
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e int i;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* Sanity check our translation table return value codes */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e for (i = 0; i < NSYSCALL; i++) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_sysent_table_t *est = &(brand_sysent_table[i]);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_assert(BIT_ONLYONESET(est->st_args & RV_MASK));
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * We need to shutdown all libc stdio. libc stdio normally goes to
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * file descriptors, but since we're actually part of a another
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * process we don't own these file descriptors and we can't make
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * any assumptions about their state.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_close_fh(stdin);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_close_fh(stdout);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_close_fh(stderr);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e/*ARGSUSED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85eulong_t
80e2ca8596e3435bc3b76f3c597833ea0a87f85ebrand_post_init(int version, int argc, char *argv[], char *envp[])
80e2ca8596e3435bc3b76f3c597833ea0a87f85e{
80e2ca8596e3435bc3b76f3c597833ea0a87f85e sysret_t rval;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_proc_reg_t reg;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_elf_data_t sed;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e auxv_t *ap;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e uintptr_t *p;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e int err;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Register our syscall emulation table with the kernel.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Note that we don't have to do invoke (syscall_number + 1024)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * until we've actually establised a syscall emulation callback
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * handler address, which is what we're doing with this brand
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * syscall.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e reg.sbr_version = version;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#ifdef __x86
80e2ca8596e3435bc3b76f3c597833ea0a87f85e reg.sbr_handler = (caddr_t)brand_handler_table;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#else /* !__x86 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e reg.sbr_handler = (caddr_t)brand_handler;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e#endif /* !__x86 */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if ((err = __systemcall(&rval, SYS_brand, B_REGISTER, &reg)) != 0) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_abort(err, "Failed to brand current process");
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*NOTREACHED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* Get data about the executable we're running from the kernel. */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if ((err = __systemcall(&rval, SYS_brand + 1024,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e B_ELFDATA, (void *)&sed)) != 0) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e brand_abort(err,
80e2ca8596e3435bc3b76f3c597833ea0a87f85e "Failed to get required brand ELF data from the kernel");
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*NOTREACHED*/
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * Find the aux vector on the stack.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e p = (uintptr_t *)envp;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e while (*p != NULL)
80e2ca8596e3435bc3b76f3c597833ea0a87f85e p++;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * p is now pointing at the 0 word after the environ pointers.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * After that is the aux vectors.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * The aux vectors are currently pointing to the brand emulation
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * library and associated linker. We're going to change them to
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * point to the brand executable and associated linker (or to no
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * linker for static binaries). This matches the process data
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * stored within the kernel and visible from /proc, which was
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * all setup in sn1_elfexec(). We do this so that when a debugger
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * attaches to the process it sees the process as a normal solaris
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * process, this brand emulation library and everything on it's
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * link map will not be visible, unless our librtld_db plugin
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * is used. Note that this is very different from how Linux
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * branded processes are implemented within lx branded zones.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * In that situation, the primary linkmap of the process is the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * brand emulation libraries linkmap, not the Linux applications
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * linkmap.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e *
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * We also need to clear the AF_SUN_NOPLM flag from the AT_SUN_AUXFLAGS
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * aux vector. This flag told our linker that we don't have a
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * primary link map. Now that our linker is done initializing, we
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * want to clear this flag before we transfer control to the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * applications copy of the linker, since we want that linker to have
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * a primary link map which will be the link map for the application
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * we're running.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e p++;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e for (ap = (auxv_t *)p; ap->a_type != AT_NULL; ap++) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e switch (ap->a_type) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_BASE:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* Hide AT_BASE if static binary */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (sed.sed_base == NULL) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_type = AT_IGNORE;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_un.a_val = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e } else {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_un.a_val = sed.sed_base;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_ENTRY:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_un.a_val = sed.sed_entry;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_PHDR:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_un.a_val = sed.sed_phdr;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_PHENT:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_un.a_val = sed.sed_phent;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_PHNUM:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_un.a_val = sed.sed_phnum;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_SUN_AUXFLAGS:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_un.a_val &= ~AF_SUN_NOPLM;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_SUN_EMULATOR:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /*
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * ld.so.1 inspects AT_SUN_EMULATOR to see if
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * if it is the linker for the brand emulation
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * library. Hide AT_SUN_EMULATOR, as the
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * linker we are about to jump to is the linker
80e2ca8596e3435bc3b76f3c597833ea0a87f85e * for the binary.
80e2ca8596e3435bc3b76f3c597833ea0a87f85e */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_type = AT_IGNORE;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_un.a_val = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e case AT_SUN_LDDATA:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e /* Hide AT_SUN_LDDATA if static binary */
80e2ca8596e3435bc3b76f3c597833ea0a87f85e if (sed.sed_lddata == NULL) {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_type = AT_IGNORE;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_un.a_val = NULL;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e } else {
80e2ca8596e3435bc3b76f3c597833ea0a87f85e ap->a_un.a_val = sed.sed_lddata;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e default:
80e2ca8596e3435bc3b76f3c597833ea0a87f85e break;
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e }
80e2ca8596e3435bc3b76f3c597833ea0a87f85e
80e2ca8596e3435bc3b76f3c597833ea0a87f85e return (sed.sed_ldentry);
80e2ca8596e3435bc3b76f3c597833ea0a87f85e}