Пример #1
0
int
lx_sendfile64(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4)
{
	sysret_t rval;
	off64_t off = 0;
	off64_t *offp = (off64_t *)p3;
	size_t sz = (size_t)p4;
	int error;
	struct sendfilevec64 sfv;
	size_t xferred;

	if (sz > 0 && uucopy(offp, &off, sizeof (off)) != 0)
		return (-errno);

	sfv.sfv_fd = p2;
	sfv.sfv_flag = 0;
	sfv.sfv_off = off;
	sfv.sfv_len = sz;
	error = __systemcall(&rval, SYS_sendfilev, SENDFILEV64, p1, &sfv,
	    1, &xferred);

	if (error == 0 && xferred > 0) {
		off += xferred;
		error = uucopy(&off, offp, sizeof (off));
	}

	return (error ? -error : (int)rval.sys_rval1);
}
Пример #2
0
/*ARGSUSED*/
long
brand_unimpl(sysret_t *rv, uintptr_t p1)
{
    sysret_t rval;

    /*
     * We'd like to print out some kind of error message here like
     * "unsupported syscall", but we can't because it's not safe to
     * assume that stderr or STDERR_FILENO actually points to something
     * that is a terminal, and if we wrote to those files we could
     * inadvertantly write to some applications open files, which would
     * be bad.
     *
     * Normally, if an application calls an invalid system call
     * it get a SIGSYS sent to it.  So we'll just go ahead and send
     * ourselves a signal here.  Note that this is far from ideal since
     * if the application has registered a signal handler, that signal
     * handler may recieve a ucontext_t as the third parameter to
     * indicate the context of the process when the signal was
     * generated, and in this case that context will not be what the
     * application is expecting.  Hence, we should probably create a
     * brandsys() kernel function that can deliver the signal to us
     * with the correct ucontext_t.
     */
    (void) __systemcall(&rval, SYS_lwp_kill + 1024, _lwp_self(), SIGSYS);
    return (ENOSYS);
}
Пример #3
0
/*
 * ATTENTION: uucopystr() does NOT ensure that string are null terminated!
 */
int
brand_uucopystr(const void *from, void *to, size_t size)
{
    sysret_t rval;

    if (__systemcall(&rval, SYS_uucopystr + 1024, from, to, size) != 0)
        return (EFAULT);
    return (0);
}
Пример #4
0
ssize_t
zone_getattr(zoneid_t zoneid, int attr, void *valp, size_t size)
{
	sysret_t rval;
	int error;

	error = __systemcall(&rval, SYS_zone, ZONE_GETATTR, zoneid,
	    attr, valp, size);
	if (error)
		(void) __set_errno(error);
	return ((ssize_t)rval.sys_rval1);
}
Пример #5
0
size_t
rctllist(char *list_buf, size_t list_bufsz)
{
	sysret_t rval;
	int error;

	error = __systemcall(&rval, SYS_rctlsys, 2, NULL, list_buf, NULL,
	    list_bufsz, 0);

	if (error)
		(void) __set_errno(error);
	return ((size_t)rval.sys_rval1);
}
Пример #6
0
/*ARGSUSED*/
void
_brand_abort(int err, const char *msg, const char *file, int line)
{
    sysret_t rval;

    /* Save the error message into convenient globals */
    brand_abort_err = err;
    brand_abort_msg = msg;
    brand_abort_file = file;
    brand_abort_line = line;

    /* kill ourselves */
    abort();

    /* If abort() didn't work, try something stronger. */
    (void) __systemcall(&rval, SYS_lwp_kill + 1024, _lwp_self(), SIGKILL);
}
Пример #7
0
/*ARGSUSED*/
ulong_t
brand_post_init(int version, int argc, char *argv[], char *envp[])
{
    sysret_t		rval;
    brand_proc_reg_t	reg;
    brand_elf_data_t	sed;
    auxv_t			*ap;
    uintptr_t		*p;
    int			err;

    /*
     * Register our syscall emulation table with the kernel.
     * Note that we don't have to do invoke (syscall_number + 1024)
     * until we've actually establised a syscall emulation callback
     * handler address, which is what we're doing with this brand
     * syscall.
     */
    reg.sbr_version = version;
#ifdef	__x86
    reg.sbr_handler = (caddr_t)brand_handler_table;
#else	/* !__x86 */
    reg.sbr_handler = (caddr_t)brand_handler;
#endif	/* !__x86 */

    if ((err = __systemcall(&rval, SYS_brand, B_REGISTER, &reg)) != 0) {
        brand_abort(err, "Failed to brand current process");

        /*NOTREACHED*/
    }

    /* Get data about the executable we're running from the kernel. */
    if ((err = __systemcall(&rval, SYS_brand + 1024,
                            B_ELFDATA, (void *)&sed)) != 0) {
        brand_abort(err,
                    "Failed to get required brand ELF data from the kernel");
        /*NOTREACHED*/
    }

    /*
     * Find the aux vector on the stack.
     */
    p = (uintptr_t *)envp;
    while (*p != NULL)
        p++;

    /*
     * p is now pointing at the 0 word after the environ pointers.
     * After that is the aux vectors.
     *
     * The aux vectors are currently pointing to the brand emulation
     * library and associated linker.  We're going to change them to
     * point to the brand executable and associated linker (or to no
     * linker for static binaries).  This matches the process data
     * stored within the kernel and visible from /proc, which was
     * all setup in sn1_elfexec().  We do this so that when a debugger
     * attaches to the process it sees the process as a normal solaris
     * process, this brand emulation library and everything on it's
     * link map will not be visible, unless our librtld_db plugin
     * is used.  Note that this is very different from how Linux
     * branded processes are implemented within lx branded zones.
     * In that situation, the primary linkmap of the process is the
     * brand emulation libraries linkmap, not the Linux applications
     * linkmap.
     *
     * We also need to clear the AF_SUN_NOPLM flag from the AT_SUN_AUXFLAGS
     * aux vector.  This flag told our linker that we don't have a
     * primary link map.  Now that our linker is done initializing, we
     * want to clear this flag before we transfer control to the
     * applications copy of the linker, since we want that linker to have
     * a primary link map which will be the link map for the application
     * we're running.
     */
    p++;
    for (ap = (auxv_t *)p; ap->a_type != AT_NULL; ap++) {
        switch (ap->a_type) {
        case AT_BASE:
            /* Hide AT_BASE if static binary */
            if (sed.sed_base == NULL) {
                ap->a_type = AT_IGNORE;
                ap->a_un.a_val = NULL;
            } else {
                ap->a_un.a_val = sed.sed_base;
            }
            break;
        case AT_ENTRY:
            ap->a_un.a_val = sed.sed_entry;
            break;
        case AT_PHDR:
            ap->a_un.a_val = sed.sed_phdr;
            break;
        case AT_PHENT:
            ap->a_un.a_val = sed.sed_phent;
            break;
        case AT_PHNUM:
            ap->a_un.a_val = sed.sed_phnum;
            break;
        case AT_SUN_AUXFLAGS:
            ap->a_un.a_val &= ~AF_SUN_NOPLM;
            break;
        case AT_SUN_EMULATOR:
            /*
             * ld.so.1 inspects AT_SUN_EMULATOR to see if
             * if it is the linker for the brand emulation
             * library.  Hide AT_SUN_EMULATOR, as the
             * linker we are about to jump to is the linker
             * for the binary.
             */
            ap->a_type = AT_IGNORE;
            ap->a_un.a_val = NULL;
            break;
        case AT_SUN_LDDATA:
            /* Hide AT_SUN_LDDATA if static binary */
            if (sed.sed_lddata == NULL) {
                ap->a_type = AT_IGNORE;
                ap->a_un.a_val = NULL;
            } else {
                ap->a_un.a_val = sed.sed_lddata;
            }
            break;
        default:
            break;
        }
    }

    return (sed.sed_ldentry);
}